Annotation of XNU/osfmk/ppc/POWERMAC/mp/MP_2p.s, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * @OSF_COPYRIGHT_INTERNAL_USE_ONLY@
        !            24:  */
        !            25: 
        !            26: /*                                                                                                                                                                                     
        !            27:        MP_2p.s 
        !            28: 
        !            29:        MP low-level signaling, configuration, et all.  This is for a and Apple/Daystar 2p board
        !            30: 
        !            31:        Lovingly crafted by Bill Angell using traditional methods
        !            32: 
        !            33: */
        !            34: 
        !            35: #include <ppc/asm.h>
        !            36: #include <ppc/proc_reg.h>
        !            37: #include <ppc/POWERMAC/mp/MPPlugIn.h>
        !            38: #include <assym.s>
        !            39: #include <mach/machine/vm_param.h>
        !            40: 
        !            41: 
        !            42: 
        !            43:                        .set    MPPlugInVersion,0                                               /* Current version code */
        !            44: 
        !            45: /* */
        !            46: /*                     Interfaces to hardware */
        !            47: /* */
        !            48: 
        !            49:                        .set    PCI1ARdisp,             0x00800000                              /* Displacement from Bandit to PCI1 address configuiration register */
        !            50:                        .set    GrandCdisp,             0x01000000                              /* Displacement from Bandit to Grand Central */
        !            51:                        .set    EventsReg,              0x20                                    /* Interruption events register (latched) */
        !            52:                        .set    LevelsReg,              0x2C                                    /* Interruption levels register (unlatched) */
        !            53:                        .set    MaskReg,                0x24                                    /* Interruption mask register */
        !            54:                        .set    ClearReg,               0x28                                    /* Interruption clear register */
        !            55:                        .set    TicksPerMic,    11                                              /* We'll use 11 ticks per �S - 120MHz is really 10, 180MHz is 11.24 */
        !            56:                        .set    EtherNRdisp,    0x01019000                              /* Displacement into bandit of EtherNet ROM */
        !            57: 
        !            58: #ifdef __ELF__
        !            59:                        .section ".data"
        !            60: #else
        !            61:                        .data
        !            62: #endif
        !            63: 
        !            64:                        .align  5                                                                       /* Get us out to the end */
        !            65: 
        !            66:                        .globl MPPIwork
        !            67: #ifdef __ELF__
        !            68:                        .type  MPPIwork,@function
        !            69: #endif
        !            70: 
        !            71: MPPIwork:
        !            72: MPPIstatus:    .byte   0                                                                       /* Global MP board status */
        !            73:                        .set    MPPIinit,       0x80                                    /* Global initialization complete */
        !            74:                        .set    MPPI2Pv2,       0x40                                    /* Second rev of 2P board (no watchdog and different state machine) */
        !            75:                        .byte   0                                                                       /* Reserved */
        !            76: MPPIinst:      .byte   0                                                                       /* Mask of CPUs installed */
        !            77: MPPIonline:    .byte   0                                                                       /* Mask of CPUs online (i.e., initialized) */
        !            78: MPPIlogCPU:    .long   0                                                                       /* Used to configure CPU addresses */
        !            79: MPPITBsync:    .long   0                                                                       /* Used to sync time bases */
        !            80:                        .long   0
        !            81: MPPIHammer:    .long   0                                                                       /* Address of HammerHead */
        !            82: MPPIGrandC:    .long   0                                                                       /* Address of GrandCentral */
        !            83: MPPIPCI1Adr: .long     0                                                                       /* Address of PCI1's config reg addr */
        !            84: MPPIEther:     .long   0                                                                       /* Address of EtherNet ROM */
        !            85:                        
        !            86:                        .align  5
        !            87: MPPISncFght: .fill     4,4,0                                                           /* Space for 9 passes of a TB sync fight + 1 guard pass */
        !            88:                        .fill   4,4,0
        !            89:                        .fill   4,4,0
        !            90:                        .fill   4,4,0
        !            91:                        .fill   4,4,0
        !            92:                        .fill   4,4,0
        !            93:                        .fill   4,4,0
        !            94:                        .fill   4,4,0
        !            95:                        .fill   4,4,0
        !            96:                        .fill   4,4,0
        !            97:                        .align  7                                                                       /* Point to the start of the CPU status */
        !            98: 
        !            99:                        .globl EXT(MPPICPUs)
        !           100: #ifdef __ELF__
        !           101:                        .type  EXT(MPPICPUs),@function
        !           102: #endif
        !           103: EXT(MPPICPUs):                                                                                         /* Start of Processor specific areas */
        !           104: /*                     There are 8 of these indexed by processor number */
        !           105: 
        !           106: 
        !           107: MPPICPU0:      .fill   8,4,0                                                                   /* First processor */
        !           108: MPPICPU1:      .fill   8,4,0                                                                   /* Second processor */
        !           109: MPPICPU2:      .fill   8,4,0                                                                   /* Third processor */
        !           110: MPPICPU3:      .fill   8,4,0                                                                   /* Fourth processor */
        !           111:                        .set    MPPIMaxCPU, (.-EXT(MPPICPUs)-32)/32                     /* Get the maximum CPU address */
        !           112: 
        !           113: 
        !           114:                        .text
        !           115: 
        !           116: /******************************************************************************************************** */
        !           117: /******************************************************************************************************** */
        !           118: /* */
        !           119: /*                     Here starteth ye stuff */
        !           120: /* */
        !           121: /******************************************************************************************************** */
        !           122: /******************************************************************************************************** */
        !           123: 
        !           124: /******************************************************************************************************** */
        !           125: /* */
        !           126: /*                     Validate that the hardware matches with our code.  At this point, we cannot check */
        !           127: /*                     for anything other than the possibility of this working.  There's no version code */
        !           128: /*                     or nothin'.  So, if we have a second processor and are a 604 or 604e, we'll say */
        !           129: /*                     we're capable.  Also we'll check version codes for our code. */
        !           130: /* */
        !           131: /*                     When we get here, DDAT and IDAT are both on, 'rupts are disabled. */
        !           132: /*  */
        !           133: /*                     We're called like this:  */
        !           134: /*                             OSStatus MP_probe(MPPlugInSpecPtr spec, UInt32 HammerheadAddr); */
        !           135: /* */
        !           136: /******************************************************************************************************** */
        !           137: 
        !           138: ENTRY(MPprobe, TAG_NO_FRAME_USED)
        !           139: 
        !           140:                        
        !           141: MPPIbase:      mfpvr   r7                                                                      /* Get the processor version */
        !           142:                        rlwinm  r7,r7,16,16,31                                          /* Isolate the processor type */
        !           143: 
        !           144:                        lbz             r5,ArbConfig(r4)                                        /* See if there is another processor */
        !           145:                        
        !           146:                        andi.   r5,r5,TwoCPU                                            /* Are we a real live two processor? */
        !           147:                        beq             OneWay                                                          /* Nope, we be gone... */
        !           148:                        
        !           149:                        cmplwi  cr0,r7,4                                                        /* Are we a 604? */
        !           150:                        beq             SeemsOK                                                         /* Yeah, we're cool... */
        !           151:                        cmplwi  cr0,r7,9                                                        /* Are we a 604E? */
        !           152:                        beq             SeemsOK                                                         /* Yeah, go finish up... */
        !           153:                        
        !           154: OneWay:                li              r3,0                                                            /* Say we can't find the proper CPU */
        !           155:                        blr                                                                                     /* Leave... */
        !           156:                        
        !           157: SeemsOK:       mr              r10,r3                                                          /* Save the parameter list */
        !           158:                        
        !           159:                        lwz             r4,MPSversionID(r10)                            /* Get the version ID */
        !           160:                        cmplwi  cr0,r4,kMPPlugInVersionID                       /* Correct version? */
        !           161:                        beq             IsOK                                                            /* Yeah, we think we're ok... */
        !           162:                        
        !           163:                        li              r3,0                                                            /* Set bad version' */
        !           164:                        blr                                                                                     /* Leave... */
        !           165:                        
        !           166: IsOK:          mflr    r11                                                                     /* Save the LR */
        !           167:                        lis             r9,HIGH_ADDR(MPPIwork)                          /* Get the top half of the data area */
        !           168:                        bl              SetBase1                                                        /* Jump to the next instruction */
        !           169: SetBase1:      mflr    r12                                                                     /* Get the base register */
        !           170:                        ori             r9,r9,LOW_ADDR(MPPIwork)                        /* Get the bottom half of the data area */
        !           171:                        addi    r12,r12,LOW_ADDR(MPPIbase-SetBase1)     /* Adjust to the start of all our code */
        !           172:                        
        !           173:                        stw             r12,MPSbaseAddr(r10)                            /* Save off the common base for all functions */
        !           174:                        
        !           175:                        la              r5,LOW_ADDR(MPPIFunctions-MPPIbase)(r12)        /* Point to the base of all functions */
        !           176:                        stw             r5,MPSareaAddr(r10)                                     /* Pass back the code address */
        !           177:                        
        !           178:                        la              r5,LOW_ADDR(MPPIFuncOffs-MPPIbase)(r12) /* Point to the function offset table */
        !           179:                        stw             r5,MPSoffsetTableAddr(r10)                      /* Pass back the pointer to the offset table */
        !           180:                        
        !           181:                        li              r5,LOW_ADDR(MPPISize-MPPIFunctions)     /* Get our size without data area */
        !           182:                        stw             r5,MPSareaSize(r10)                                     /* Save it */
        !           183:                        
        !           184:                        stw             r9,MPSdataArea(r10)                                     /* Save it */
        !           185:                        
        !           186:                        la              r5,LOW_ADDR(EXT(MPPICPUs)-MPPIwork)(r9) /* Point to the CPU area base */
        !           187:                        stw             r5,MPSCPUArea(r10)                                      /* Save it */
        !           188:                        
        !           189:                        mtlr    r11                                                                     /* Restore that return address */
        !           190:                        li              r3,1                                                            /* Set no error */
        !           191:                        blr                                                                                     /* Leave, we're all done... */
        !           192: 
        !           193: /******************************************************************************************************** */
        !           194: /******************************************************************************************************** */
        !           195: /* */
        !           196: /*                     Here starteth ye code that starteth up ye second prothether. */
        !           197: /*                     Yea, though ye prothether executeth asynchronously, it appears unto men */
        !           198: /*                     in ye shape of a synchronous process.  By ye instruction of He who gave it */
        !           199: /*                     form and being, it stopeth to worship and praise its Lord, to joyously  */
        !           200: /*                     receive His blessings and teachings, to guide its way along the path to */
        !           201: /*                     righteous execution. */
        !           202: /* */
        !           203: /******************************************************************************************************** */
        !           204: /******************************************************************************************************** */
        !           205: 
        !           206: 
        !           207: /******************************************************************************************************** */
        !           208: /* */
        !           209: /*                     Initialize the MP hardware.  This will bring the other processor online. */
        !           210: /* */
        !           211: /*                     First we will tick the board to its 5th state the "TBEN off" state. */
        !           212: /* */
        !           213: /*                     Just for giggles, here's the states: */
        !           214: /* */
        !           215: /*                     1) 1st ROM                      - This state exists after motherboard reset */
        !           216: /*                     2) Open Firmware        - Transitions here when the SecInt line is first asserted */
        !           217: /*                                                               Open Firmware attempts to execute some code on the secondary */
        !           218: /*                                                               processor to obtain the PVR register.  It's got some problems */
        !           219: /*                                                               and hangs the secondary disabled. */
        !           220: /*                     3) Reset (my name)      - Entered when the SecInt line is deasserted. A timer starts and */
        !           221: /*                                                               468�S later the reset line is pulled.  I may have this wrong here, */
        !           222: /*                                                               it may be that the reset line is held for 468�S.  Either way, */
        !           223: /*                                                               this state is invisible to us. */
        !           224: /*                     4) 2nd ROM                      - This state exists when the secondary processor begins executing */
        !           225: /*                                                               after the reset. */
        !           226: /*                     5) TBEN off                     - We transition here when SecInt is asserted in the 2nd ROM state. */
        !           227: /*                                                               In this state, the TBEN pin is set to disable the timebase from  */
        !           228: /*                                                               running on all processors, thus freezing time. (Performace analysis */
        !           229: /*                                                               note: here would be the best time to run stats, all tests would */
        !           230: /*                                                               run in 0 time giving us infinite speed.) Also the "primary arbitration" */
        !           231: /*                                                               mode is set.  This mode causes the CPU board to arbitrate both processors */
        !           232: /*                                                               using a single bus master.  This gets us around the L2 cache dumbness. */
        !           233: /*                                                               We should also note that because of this, there is now no way to  */
        !           234: /*                                                               tell if we are on the secondary processor, the WhoAmI register will */
        !           235: /*                                                               always indicate the primary processor.  We need to have sewn */
        !           236: /*                                                               name tags into our underwear before now. */
        !           237: /*                                                               Finally, this state is the only way we can tell if we are executing */
        !           238: /*                                                               on the older version of the 2-way board.  When it is in this state */
        !           239: /*                                                               "primary arbitration" has not been enabled yet.  The WhoAmI register */
        !           240: /*                                                               will indicate if we are on the secondary processor on not.  We should */
        !           241: /*                                                               check this because we need to do signals differently. */
        !           242: /*                     6) TBEN on                      - The next assertion of SecInt brings us to our final destination.  For */
        !           243: /*                                                               those of you who will be deplaning, please remember that timebases */
        !           244: /*                                                               are running and primary arbitration is enabled.  Always remember: */
        !           245: /*                                                               buckle up for safety and if you're tired pull over for a rest. */
        !           246: /* */
        !           247: /******************************************************************************************************** */
        !           248: 
        !           249: ENTRY(MPinstall, TAG_NO_FRAME_USED)
        !           250: 
        !           251: /*                     int MP_install(unsigned int *physAddr, unsigned int band1, unsigned int hammerh, unsigned int grandc,
        !           252:  *                     unsigned int pci1ar, unsigned int enetr);
        !           253:  */
        !           254:        
        !           255:                        lis             r11,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           256:                        mflr    r0                                                                      /* Save the LR */
        !           257:                        ori             r11,r11,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           258:                        
        !           259:                        stw             r5,MPPIHammer-MPPIwork(r11)                     /* Save the HammerHead address for later */
        !           260:                        stw             r6,MPPIGrandC-MPPIwork(r11)                     /* Save address of Grand Central */
        !           261:                        stw             r7,MPPIPCI1Adr-MPPIwork(r11)            /* Save the PCI1 address register address */
        !           262:                        stw             r8,MPPIEther-MPPIwork(r11)                      /* Save Ethernet ROM address */
        !           263: 
        !           264:                        li              r4,LOW_ADDR(0xC080)                                     /* Set CPU 0&1 installed, CPU 0 online */
        !           265:                        lis             r10,(MPPICOnline+MPPICReady)>>16        /* Set CPU 0 online and ready */
        !           266:                        
        !           267:                        mfspr   r6,pir                                                          /* Get the PIR contents */
        !           268:                        
        !           269:                        sth             r4,MPPIinst-MPPIwork(r11)                       /* Set 'em for later */
        !           270:                        rlwinm  r6,r6,0,0,27                                            /* Clear to use processor 0 */
        !           271:                        stw             r10,EXT(MPPICPUs)-MPPIwork(r11)         /* Preset CPU 0 online and ready */
        !           272: 
        !           273:                        mtspr   pir,r6                                                          /* Set our PIR */
        !           274: 
        !           275: /* */
        !           276: /*                     Ok, ok, enough of this.  Let's really start 'em up. */
        !           277: /* */
        !           278: 
        !           279:                        lis             r9,HIGH_ADDR(CPUInit)                           /* Top of init code */
        !           280:                        li              r6,1                                                            /* Get the other guy's CPU address               */
        !           281:                        ori             r9,r9,LOW_ADDR(CPUInit)                         /* Get physical address of init code */
        !           282:                
        !           283:                        mfmsr   r8                                                                      /* Get the MSR */
        !           284: 
        !           285:                        stw             r6,MPPIlogCPU-MPPIwork(r11)                     /* Set the logical CPU address to assign */
        !           286:                                                
        !           287:                        rlwinm  r6,r8,0,17,15                                           /* Turn off interruptions */
        !           288:                        sync                                                                            /* Make sure the work area is updated */
        !           289:                        mtmsr   r6                                                                      /* Flip the EE bit off */
        !           290:                        isync                                                                           /* Chill a bit */
        !           291:                        
        !           292:                        stw             r9,0(r7)                                                        /* Pass the initialization code address to our friend */
        !           293:                        sync                                                                            /* Fence off the pig */
        !           294:                        
        !           295:                        li              r6,0                                                            /* Clear this out */
        !           296:                        stb             r6,IntReg(r5)                                           /* Kick the other processor */
        !           297:                        eieio                                                                           /* Pig in the sty */
        !           298: 
        !           299: /*                     At this point we should be in the "TBEN off" state.  The second processor should be starting */
        !           300: /*                     to come up. */
        !           301: 
        !           302: /*                     Note that we are assuming that the secondary processor will reset the interrupt request. */
        !           303: /*                     If we are on one of the old boards, we will die in about 256�S if it is not reset, 'cause */
        !           304: /*                     of that silly watchchihuahua timer.  We can't use the TB or decrimenter here to set a  */
        !           305: /*                     timeout because when we are in "TBEN off" state these guys don't run. */
        !           306: 
        !           307:                        lis             r4,HIGH_ADDR(SpinTimeOut)                       /* Get about 1 second at 200MHz */
        !           308:                                                                                                                /* At 120 MHz this is 1.66 seconds, at 400MHz it is .5 */
        !           309:                                                                                                                /* All these are more than enough time for this handshake */
        !           310:                        ori             r4,r4,LOW_ADDR(SpinTimeOut)                     /* Get the bottom part */
        !           311: 
        !           312: WaitReady:     lwz             r9,0(r7)                                                        /* Get this back */
        !           313:                        mr.             r9,r9                                                           /* The other processor will set to 0 */
        !           314:                                                                                                                /*    when it is ready for the work area address */
        !           315:                        beq             CodeUp                                                          /* The code is up on the other side */
        !           316:                        subi    r4,r4,1                                                         /* Count the try */
        !           317:                        mr.             r4,r4                                                           /* Did we timeout? */
        !           318:                        bne+    WaitReady                                                       /* Nope... */
        !           319:                        
        !           320:                        li              r3,kMPPInitTO1                                          /* Set that we timed out with initial code bringup */
        !           321:                        mtmsr   r8                                                                      /* Restore the interrupt state */
        !           322:                        mtlr    r0                                                                      /* Restore the return addess */
        !           323:                        blr                                                                                     /* Return a failure... */
        !           324: 
        !           325: CodeUp:                isync                                                                           /* Make sure we don't prefetch past here */
        !           326:                        
        !           327: /*                     Timebase is stopped here, no need for the funky "get time base right" loop */
        !           328: 
        !           329:                        mftbu   r4                                                                      /* Get upper timebase half */
        !           330:                        mftb    r9                                                                      /* Get bottom  */
        !           331:                        stw             r4,MPPITBsync-MPPIwork(r11)                     /* Save the top */
        !           332:                        stw             r9,MPPITBsync+4-MPPIwork(r11)           /* Save the second half */
        !           333:                        sync                                                                            /* Be very sure it's there */
        !           334:                        
        !           335:                        stw             r11,0(r7)                                                       /* Set the PCI1 adr reg non-zero - this releases the spin */
        !           336:                                                                                                                /*      loop and allows the timebase to be set. */
        !           337:                        eieio
        !           338: 
        !           339:                        lis             r9,HIGH_ADDR(SpinTimeOut)                       /* Get the spin time */
        !           340:                        ori             r9,r9,LOW_ADDR(SpinTimeOut)                     /* Get the bottom part */
        !           341:                        
        !           342: WaitTBset:     lwz             r4,0(r7)                                                        /* Get this back */
        !           343:                        mr.             r4,r4                                                           /* When zero, the other guy's TB is set up */
        !           344:                        beq-    TBSetUp                                                         /* She's'a all done... */
        !           345:                        subi    r9,r9,1                                                         /* Count the try */
        !           346:                        mr.             r9,r9                                                           /* Did we timeout? */
        !           347:                        bne+    WaitTBset                                                       /* Nope... */
        !           348:                        
        !           349:                        li              r3,kMPPInitTO3                                          /* Set that we timed out setting clock */
        !           350:                        mtmsr   r8                                                                      /* Restore the interrupt state */
        !           351:                        isync
        !           352:                        mtlr    r0                                                                      /* Restore the return addess */
        !           353:                        blr                                                                                     /* Return a failure... */
        !           354: 
        !           355: TBSetUp:       stb             r6,IntReg(r5)                                           /* Kick the other processor again */
        !           356:                                                                                                                /* This will tick us to the next state */
        !           357:                        eieio
        !           358:                                                
        !           359: SpinDelay:     addi    r6,r6,1                                                         /* Bump spin count (we finally are trashing R6) */
        !           360:                        cmplwi  cr0,r6,4096                                                     /* Spun enough? */
        !           361:                        ble+    SpinDelay                                                       /* Nope... */
        !           362:                        
        !           363:                        li              r6,SecInt                                                       /* Set the interrupt bit */
        !           364:                        stb             r6,IntReg(r5)                                           /* Deassert the external signal */
        !           365: /* */
        !           366: /*                     Ok, the other processor should be online in a spin waiting for a start signal from */
        !           367: /*                     us.  It should be in the reset state with no external interruptions pending.  There may */
        !           368: /*                     be a decrimenter pop waiting in the wings though. */
        !           369: /* */
        !           370:                        
        !           371:                        lwz             r7,MPPIGrandC-MPPIwork(r11)                     /* Point to GrandCentral */
        !           372:                        lwz             r4,MaskReg(r7)                                          /* Get the grand central mask register (note that this */
        !           373:                                                                                                                /* is a little-endian area, but I'm too lazy to access it that way */
        !           374:                                                                                                                /* so I'll document what it really should be, but, probably, it would */
        !           375:                                                                                                                /* have been much, much easier just to code up the lwbrx and be done */
        !           376:                                                                                                                /* with it rather than producing this monograph describing my alternate */
        !           377:                                                                                                                /* access method that I really don't explain anyway. */
        !           378:                        ori             r4,r4,0x0040                                            /* Flip on bit 30 (hah, figure that one out).  This enables the */
        !           379:                                                                                                                /* Ext10 interrupt which is connected to the MACE ethernet chip's */
        !           380:                                                                                                                /* chip-select pin. */
        !           381:                        stw             r4,MaskReg(r7)                                          /* Stick it on back */
        !           382:                        eieio
        !           383:                        
        !           384:                        mtlr    r0                                                                      /* Get back the original LR */
        !           385:                        sync                                                                            /* Make sure all storage ops are done */
        !           386:                        mtmsr   r8                                                                      /* Restore the MSR */
        !           387:                        isync
        !           388:                        li              r3,kSIGPnoErr                                           /* Set that we worked jest fine and dandy */
        !           389:                        blr                                                                                     /* Bye now... */
        !           390: 
        !           391:                        .align  5
        !           392: /******************************************************************************************************** */
        !           393: /******************************************************************************************************** */
        !           394: /* */
        !           395: /*                     This is where the individual SIGP function calls reside.  */
        !           396: /*                     Also, it is where we cram the second processor's initialization code wo'w we */
        !           397: /*                     can use physical addressing. */
        !           398: /* */
        !           399: /******************************************************************************************************** */
        !           400: /******************************************************************************************************** */
        !           401: 
        !           402: MPPIFunctions:                                                                                 /* Start of all externally called functions and interrupt handling code */
        !           403: 
        !           404: 
        !           405: /******************************************************************************************************** */
        !           406: /* */
        !           407: /*                     Count the number of processors.  This hardwires to 2 (or 1 if no secondary) */
        !           408: /* */
        !           409: /******************************************************************************************************** */
        !           410: 
        !           411: CountProcessors:
        !           412:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           413:                        mfmsr   r9                                                                      /* Get the MSR */
        !           414:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           415:                        
        !           416:                        ori             r10,r9,0x0010                                           /* Turn on DDAT */
        !           417:                        
        !           418:                        lwz             r8,MPPIHammer-MPPIwork(r12)                     /* Point to the HammerHead controller */
        !           419:                        
        !           420:                        mtmsr   r10                                                                     /* Turn on DDAT */
        !           421:                        isync                                                                           /* Kill speculation */
        !           422: 
        !           423:                        li              r3,2                                                            /* Assume we have them all */
        !           424:                        lbz             r5,ArbConfig(r8)                                        /* Check if we've seen a second processor */
        !           425:                        andi.   r5,r5,TwoCPU                                            /* Are we a real live two processor? */
        !           426:                        mtmsr   r9                                                                      /* Put back the DDAT */
        !           427:                        isync
        !           428:                        
        !           429:                        bnelr+                                                                          /* Yeah... */
        !           430:                        li              r3,1                                                            /* Nope, set a count of 1 */
        !           431:                        blr                                                                                     /* Leave, we're inadequate... */
        !           432: 
        !           433: /******************************************************************************************************** */
        !           434: /* */
        !           435: /*                     Start up the selected processor (R3=processor; R4=physical start address; R5=pass-thru parm) */
        !           436: /* */
        !           437: /******************************************************************************************************** */
        !           438:                        
        !           439: StartProcessor:
        !           440: 
        !           441:                        mr              r7,r5                                                           /* Copy pass-thru parameter */
        !           442:                        mfspr   r10,pir                                                         /* Get our processor number */
        !           443:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           444:                        cmplw   cr0,r3,r10                                                      /* Trying to start ourselves? */
        !           445:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           446:                        cmplwi  cr1,r3,MPPIMaxCPU                                       /* See if we are bigger than max */
        !           447:                        li              r3,kMPPHairyPalms                                       /* Set trying to do it to ourselves */
        !           448:                        beqlr-                                                                          /* Self abuse... */
        !           449:                        li              r3,kSIGPTargetAddrErr                           /* CPU number is too big */
        !           450:                        bgtlr-  cr1                                                                     /* Sure are... (Get our address also) */
        !           451:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           452:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !           453:                        mflr    r11                                                                     /* Save the return address */
        !           454:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !           455:                        
        !           456: SPretry:       lwarx   r5,0,r9                                                         /* Pick up the status flags (MPPICStat) and reserve it */
        !           457:                        li              r3,kSIGPInterfaceBusyErr                        /* Fill dead space and get busy return code */
        !           458:                        rlwinm. r0,r5,0,0,0                                                     /* Are we marked as busy? */
        !           459:                        lis             r6,MPPICOnline>>16                                      /* Get the online flag */
        !           460:                        bne-    ErrorReturn                                                     /* Yeah, go leave, don't bother me now... */
        !           461:                        and.    r0,r5,r6                                                        /* Are we online */
        !           462:                        li              r3,kMPPOffline                                          /* Set offline */
        !           463:                        beq-    ErrorReturn                                                     /* Ain't online, ain't ready, buzz off... */
        !           464:                        li              r3,kMPPBadState                                         /* Set bad state */
        !           465:                        oris    r5,r5,(MPPICBusy>>16)&0x0000FFFF        /* Turn on the busy bit */
        !           466:                        
        !           467:                        stwcx.  r5,0,r9                                                         /* Try to set busy */
        !           468:                        bne-    SPretry                                                         
        !           469:                        
        !           470:                        ori             r6,r10,MPPICfStrt<<8                            /* Put the Start function in front of the processor ID */
        !           471:                        rlwimi  r5,r6,0,16,31                                           /* Put these behind the status flags */
        !           472:                        stw             r4,MPPICParm0(r9)                                       /* Set the starting physical address parameter */
        !           473:                        stw             r7,MPPICParm2(r9)                                       /* Set pass-thru parameter */
        !           474:                        
        !           475:                        sync                                                                            /* Make sure it's all out there */
        !           476:                        b               KickAndGo                                                       /* We're done now... */
        !           477: 
        !           478: /******************************************************************************************************** */
        !           479: /* */
        !           480: /*                     Reset the selected processor (R3=processor).  You can't reset yourself or the primary. */
        !           481: /*                     We're gonna try, try real hard...  This is not for the faint-of-heart. */
        !           482: /*                     If there's ever any way to yank a reset line, we'll do it here. */
        !           483: /* */
        !           484: /******************************************************************************************************** */
        !           485:                        
        !           486: ResetProcessor:
        !           487:                        mfspr   r10,pir                                                         /* Get our processor number */
        !           488:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           489:                        rlwinm  r10,r10,0,28,31                                         /* Clean up the PIR */
        !           490:                        cmplw   cr0,r3,r10                                                      /* Trying to start ourselves? */
        !           491:                        cmplwi  cr1,r3,MPPIMaxCPU                                       /* See if we are bigger than max */
        !           492:                        li              r3,kMPPHairyPalms                                       /* Set trying to do it to ourselves */
        !           493:                        beqlr-                                                                          /* Self abuse... */
        !           494:                        mr.             r9,r9                                                           /* Trying to reset the primary?!?  Dude, that's insubordination!!!! */
        !           495:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           496:                        li              r3,kMPPInvalCPU                                         /* Say that that's a major offense */
        !           497:                        beqlr-                                                                          /* Bye now... */
        !           498:                        li              r3,kSIGPTargetAddrErr                           /* CPU number is too big */
        !           499:                        bgtlr-  cr1                                                                     /* Sure are... (Get our address also) */
        !           500:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           501:                        
        !           502:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)           /* Point into the proccessor control area                */
        !           503:                        mflr    r11                                                                     /* Save the return address */
        !           504:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !           505:                        
        !           506:                        li              r4,16                                                           /* Try for 16 times to get the busy lock */
        !           507: 
        !           508: RSlockS:       mftb    r6                                                                      /* Time stamp start */
        !           509: 
        !           510: RSlock:                lwarx   r5,0,r9                                                         /* Pick up the status flags (MPPICStat) and reserve it */
        !           511:                        rlwinm. r0,r5,0,2,2                                                     /* Are we online */
        !           512:                        li              r3,kMPPOffline                                          /* Set offline */
        !           513:                        cmplwi  cr1,r5,0                                                        /* Check for busy */
        !           514:                        beq-    ErrorReturn                                                     /* Ain't online, ain't ready, buzz off... */
        !           515:                        bge+    cr1,RSnotBusy                                           /* Not busy, make it so... */
        !           516:                        
        !           517:                        mftb    r7                                                                      /* Stamp the time */
        !           518:                        sub             r7,r7,r6                                                        /* Get elapsed time */
        !           519:                        rlwinm. r7,r7,16,16,31                                          /* Divide ticks by microseconds (this is pretty darn "kinda-in-the-ballpark") */
        !           520:                        cmplwi  cr0,r7,TicksPerMic                                      /* See if we hit 65536�S yet */
        !           521:                        blt+    RSlock                                                          /* Not yet... */
        !           522:                        
        !           523: RSatmtCnt:     subi    r4,r4,1                                                         /* Count the retries */
        !           524:                        mr.             r4,r4                                                           /* Are we done yet? */
        !           525:                        bgt+    RSlockS                                                         /* Start the lock attempt again... */
        !           526:                        
        !           527:                        li              r3,kMPPCantLock                                         /* Say we can't get the lock */
        !           528:                        b               ErrorReturn                                                     /* Bye, dude... */
        !           529:                        
        !           530: RSnotBusy:     rlwinm  r5,r5,0,0,15                                            /* Clear out the function and requestor */
        !           531:                        oris    r5,r5,(MPPICBusy>>16)&0x0000FFFF        /* Set busy */
        !           532:                        or              r5,r10,r5                                                       /* Add in our processor */
        !           533:                        ori             r5,r5,MPPICfReset<<8                            /* Set the reset function */
        !           534:                        stwcx.  r5,0,r9                                                         /* Cram it back */
        !           535:                        bne-    RSatmtCnt                                                       /* We lost the reservation... */
        !           536:                        b               KickAndGo                                                       /* Try to send it across... */
        !           537:                        
        !           538: 
        !           539: /******************************************************************************************************** */
        !           540: /* */
        !           541: /*                     Here we will try to resume execution of a stopped processor (R3=processor). */
        !           542: /* */
        !           543: /******************************************************************************************************** */
        !           544:                        
        !           545: ResumeProcessor:
        !           546:                        mfspr   r10,pir                                                         /* Get our processor number */
        !           547:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           548:                        cmplw   cr0,r3,r10                                                      /* Trying to resume ourselves? */
        !           549:                        cmplwi  cr1,r3,MPPIMaxCPU                                       /* See if we are bigger than max */
        !           550:                        li              r3,kMPPHairyPalms                                       /* Set trying to do it to ourselves */
        !           551:                        beqlr-                                                                          /* Self abuse... */
        !           552:                        li              r3,kSIGPTargetAddrErr                           /* CPU number is too big */
        !           553:                        bgtlr-  cr1                                                                     /* Sure are... (Get our address also) */
        !           554:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           555:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !           556:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           557:                        mflr    r11                                                                     /* Save the link register */
        !           558:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !           559:                        
        !           560: RPretry:       lwarx   r5,0,r9                                                         /* Pick up the status flags (MPPICStat) and reserve it */
        !           561:                        li              r3,kSIGPInterfaceBusyErr                        /* Fill dead space and get busy return code */
        !           562:                        rlwinm. r0,r5,0,0,0                                                     /* Are we marked as busy? */
        !           563:                        lis             r6,MPPICOnline>>16                                      /* Get the online flag */
        !           564:                        bne-    ErrorReturn                                                     /* Yeah, go leave, don't bother me now... */
        !           565:                        and.    r0,r5,r6                                                        /* Are we online */
        !           566:                        li              r3,kMPPOffline                                          /* Set offline */
        !           567:                        lis             r6,MPPICReady>>16                                       /* Get the ready bit */
        !           568:                        beq-    ErrorReturn                                                     /* Ain't online, ain't ready, buzz off... */
        !           569:                        and.    r0,r5,r6                                                        /* Are we ready? */
        !           570:                        li              r3,kMPPNotReady                                         /* Set not ready */
        !           571:                        lis             r6,MPPICStop>>16                                        /* Get the stopped bit */
        !           572:                        beq-    ErrorReturn                                                     /* Ain't ready, buzz off... */
        !           573:                        and.    r0,r5,r6                                                        /* Are we stopped? */
        !           574:                        li              r3,kMPPNotStopped                                       /* Set not stopped */
        !           575:                        oris    r5,r5,(MPPICBusy>>16)&0x0000FFFF        /* Turn on the busy bit */
        !           576:                        beq-    ErrorReturn                                                     /* Nope, not stopped, so how do we resume? */
        !           577:                        
        !           578:                        stwcx.  r5,0,r9                                                         /* Try to set busy */
        !           579:                        bne-    RPretry
        !           580:                        
        !           581:                        ori             r6,r10,MPPICfResm<<8                            /* Put the resume function in front of the processor ID */
        !           582:                        rlwimi  r5,r6,0,16,31                                           /* Put these behind the status flags */
        !           583:                        b               KickAndGo                                                       /* We're done now... */
        !           584: 
        !           585: 
        !           586: 
        !           587: /******************************************************************************************************** */
        !           588: /* */
        !           589: /*                     Here we will try to stop execution of a running processor (R3=processor). */
        !           590: /* */
        !           591: /******************************************************************************************************** */
        !           592:                        
        !           593: StopProcessor:
        !           594:                        mfspr   r10,pir                                                         /* Get our processor number */
        !           595:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           596:                        cmplw   cr0,r3,r10                                                      /* Are we doing ourselves? */
        !           597:                        cmplwi  cr1,r3,MPPIMaxCPU                                       /* See if we are bigger than max */
        !           598:                        li              r3,kMPPHairyPalms                                       /* Set trying to do it to ourselves */
        !           599:                        beqlr-                                                                          /* Self abuse... */
        !           600:                        li              r3,kSIGPTargetAddrErr                           /* CPU number is too big */
        !           601:                        bgtlr-  cr1                                                                     /* Sure are... (Get our address also) */
        !           602:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           603:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !           604:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           605:                        mflr    r11                                                                     /* Save the link register */
        !           606:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !           607:                        
        !           608: PPretry:       lwarx   r5,0,r9                                                         /* Pick up the status flags (MPPICStat) and reserve it */
        !           609:                        li              r3,kSIGPInterfaceBusyErr                        /* Fill dead space and get busy return code */
        !           610:                        rlwinm. r0,r5,0,0,0                                                     /* Are we marked as busy? */
        !           611:                        lis             r6,MPPICOnline>>16                                      /* Get the online flag */
        !           612:                        bne-    ErrorReturn                                                     /* Yeah, go leave, don't bother me now... */
        !           613:                        and.    r0,r5,r6                                                        /* Are we online */
        !           614:                        li              r3,kMPPOffline                                          /* Set offline */
        !           615:                        lis             r6,MPPICReady>>16                                       /* Get the ready bit */
        !           616:                        beq-    ErrorReturn                                                     /* Ain't online, ain't ready, buzz off... */
        !           617:                        and.    r0,r5,r6                                                        /* Are we ready? */
        !           618:                        li              r3,kMPPNotReady                                         /* Set not ready */
        !           619:                        lis             r6,MPPICStop>>16                                        /* Get the stopped bit */
        !           620:                        beq-    ErrorReturn                                                     /* Ain't ready, buzz off... */
        !           621:                        and.    r0,r5,r6                                                        /* Are we stopped? */
        !           622:                        li              r3,kMPPNotRunning                                       /* Set not running */
        !           623:                        oris    r5,r5,(MPPICBusy>>16)&0x0000FFFF        /* Turn on the busy bit */
        !           624:                        bne-    ErrorReturn                                                     /* Nope, already stopped, so how do we stop? */
        !           625:                        
        !           626:                        stwcx.  r5,0,r9                                                         /* Try to set busy */
        !           627:                        ori             r10,r10,MPPICfStop<<8                           /* Put the stop function in front of the processor ID */
        !           628:                        bne-    PPretry
        !           629:                        
        !           630:                        rlwimi  r5,r10,0,16,31                                          /* Put these behind the status flags */
        !           631:                        b               KickAndGo                                                       /* We're done now... */
        !           632: 
        !           633: 
        !           634: /******************************************************************************************************** */
        !           635: /* */
        !           636: /*                     Here we will try to signal a running processor (R3=processor). */
        !           637: /*                     Note that this should have good performace.  Well, actually, seeing as how slow we really are, it */
        !           638: /*                     probably is moot anyhow. */
        !           639: /*                     Another note: this function (and all most others as well) will return a timeout when the  */
        !           640: /*                     second processor tries to do itself on the old version of the board.  This happens because */
        !           641: /*                     In order to keep the watchchihuahua from popping (just imagine the scene: that little runt-dog just so */
        !           642: /*                     excited that its veins and eyes bulge and then explode) signaling to the secondary  */
        !           643: /*                     is done syncronously and disabled.  If the secondary signals the secondary, it will never enable so */
        !           644: /*                     it will never see the 'rupt, so it will never clear it, so it will time out, so there... */
        !           645: /* */
        !           646: /******************************************************************************************************** */
        !           647:                        
        !           648: SignalProcessor:
        !           649:                        mfspr   r10,pir                                                         /* Get our processor number */
        !           650:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           651:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           652:                        cmplwi  cr1,r3,MPPIMaxCPU                                       /* See if we are bigger than max */
        !           653:                        li              r3,kSIGPTargetAddrErr                           /* CPU number is too big */
        !           654:                        bgtlr-  cr1                                                                     /* Sure are... (Get our address also) */
        !           655:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !           656:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           657:                        mflr    r11                                                                     /* Save the link register */
        !           658:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !           659:                        
        !           660: SiPretry:      lwarx   r5,0,r9                                                         /* Pick up the status flags (MPPICStat) and reserve it */
        !           661:                        li              r3,kSIGPInterfaceBusyErr                        /* Fill dead space and get busy return code */
        !           662:                        rlwinm. r0,r5,0,0,0                                                     /* Are we marked as busy? */
        !           663:                        lis             r6,MPPICOnline>>16                                      /* Get the online flag */
        !           664:                        bne-    ErrorReturn                                                     /* Yeah, go leave, don't bother me now... */
        !           665:                        and.    r0,r5,r6                                                        /* Are we online */
        !           666:                        li              r3,kMPPOffline                                          /* Set offline */
        !           667:                        lis             r6,MPPICReady>>16                                       /* Get the ready bit */
        !           668:                        beq-    ErrorReturn                                                     /* Ain't online, ain't ready, buzz off... */
        !           669:                        and.    r0,r5,r6                                                        /* Are we ready? */
        !           670:                        li              r3,kMPPNotReady                                         /* Set not ready */
        !           671:                        oris    r5,r5,(MPPICBusy>>16)&0x0000FFFF        /* Turn on the busy bit */
        !           672:                        beq-    ErrorReturn                                                     /* Ain't ready, buzz off... */
        !           673:                        
        !           674:                        stwcx.  r5,0,r9                                                         /* Try to set busy */
        !           675:                        ori             r10,r10,MPPICfSigp<<8                           /* Put the SIGP function in front of the processor ID */
        !           676:                        bne-    SiPretry
        !           677:                        
        !           678:                        stw             r4,MPPICParm0(r9)                                       /* Pass along the SIGP parameter */
        !           679:                        
        !           680:                        rlwimi  r5,r10,0,16,31                                          /* Put these behind the status flags */
        !           681:                        b               KickAndGo                                                       /* We're done now... */
        !           682: 
        !           683: 
        !           684: /******************************************************************************************************** */
        !           685: /* */
        !           686: /*                     Here we will store the state of a processor (R3=processor; R4=status area). */
        !           687: /*                     Self abuse will store the state as is, is not asynchronous, and grows hair on your palms. */
        !           688: /* */
        !           689: /******************************************************************************************************** */
        !           690:                        
        !           691: StoreProcessorStatus:
        !           692:                        mfspr   r10,pir                                                         /* Get our processor number */
        !           693:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           694:                        cmplw   cr0,r3,r10                                                      /* Saving our own state???  Abusing oneself??? */
        !           695:                        cmplwi  cr1,r3,MPPIMaxCPU                                       /* See if we are bigger than max */
        !           696:                        li              r3,kSIGPTargetAddrErr                           /* CPU number is too big */
        !           697:                        mflr    r11                                                                     /* Save the link register */
        !           698:                        beq             Flagellant                                                      /* Oh baby, oh baby... */
        !           699:                        bgtlr-  cr1                                                                     /* Sure are... (Get our address also) */
        !           700:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           701:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !           702:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           703:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !           704:                        
        !           705: SSretry:       lwarx   r5,0,r9                                                         /* Pick up the status flags (MPPICStat) and reserve it */
        !           706:                        li              r3,kSIGPInterfaceBusyErr                        /* Fill dead space and get busy return code */
        !           707:                        rlwinm. r0,r5,0,0,0                                                     /* Are we marked as busy? */
        !           708:                        lis             r6,MPPICOnline>>16                                      /* Get the online flag */
        !           709:                        bne-    ErrorReturn                                                     /* Yeah, go leave, don't bother me now... */
        !           710:                        and.    r0,r5,r6                                                        /* Are we online */
        !           711:                        li              r3,kMPPOffline                                          /* Set offline */
        !           712:                        beq-    ErrorReturn                                                     /* Ain't online, buzz off... */
        !           713:                        oris    r5,r5,(MPPICBusy>>16)&0x0000FFFF        /* Turn on the busy bit */
        !           714:                        
        !           715:                        stwcx.  r5,0,r9                                                         /* Try to set busy */
        !           716:                        ori             r10,r10,MPPICfStat<<8                           /* Put the store status function in front of the processor ID */
        !           717:                        bne-    SSretry                                                         /* Lost reservation, return busy... */
        !           718:                        
        !           719:                        li              r0,0                                                            /* Get false */
        !           720:                        stb             r0,CSAregsAreValid(r4)                          /* Set that the registers ain't valid */
        !           721:                        stw             r4,MPPICParm0(r9)                                       /* Set the status area physical address parameter */
        !           722:                        
        !           723:                        rlwimi  r5,r10,0,16,31                                          /* Put these behind the status flags */
        !           724:                        b               KickAndGo                                                       /* We're done now... */
        !           725:                        
        !           726: /*                     Spill one's seed upon the soil */
        !           727: 
        !           728: Flagellant:    bl              StoreStatus                                                     /* Go store off all the registers 'n' stuff */
        !           729:                        mtlr    r11                                                                     /* Restore the return address */
        !           730:                        li              r3,kSIGPnoErr                                           /* Return no error */
        !           731:                        blr                                                                                     /* Leave... */
        !           732: 
        !           733: 
        !           734: /******************************************************************************************************** */
        !           735: /* */
        !           736: /*                     Here we will attempt to syncronize clocks (R3=processor). */
        !           737: /*                     Self abuse will just return with an all-ok code. */
        !           738: /* */
        !           739: /******************************************************************************************************** */
        !           740:                        
        !           741: SynchClock:
        !           742:                        mfspr   r10,pir                                                         /* Get our processor number */
        !           743:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           744:                        cmplw   cr0,r3,r10                                                      /* Cleaning our own clock?? */
        !           745:                        cmplwi  cr1,r3,MPPIMaxCPU                                       /* See if we are bigger than max */
        !           746:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           747:                        li              r3,kSIGPnoErr                                           /* Assume self-cleaning clock */
        !           748:                        beqlr                                                                           /* Oh baby, oh baby... */
        !           749:                        li              r3,kSIGPTargetAddrErr                           /* CPU number is too big */
        !           750:                        bgtlr-  cr1                                                                     /* Sure are... (Get our address also) */
        !           751:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           752:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !           753:                        mflr    r11                                                                     /* Save the link register */
        !           754:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !           755:                        
        !           756: SyCretry:      lwarx   r5,0,r9                                                         /* Pick up the status flags (MPPICStat) and reserve it */
        !           757:                        li              r3,kSIGPInterfaceBusyErr                        /* Fill dead space and get busy return code */
        !           758:                        rlwinm. r0,r5,0,0,0                                                     /* Are we marked as busy? */
        !           759:                        lis             r6,MPPICOnline>>16                                      /* Get the online flag */
        !           760:                        bne-    ErrorReturn                                                     /* Yeah, go leave, don't bother me now... */
        !           761:                        and.    r0,r5,r6                                                        /* Are we online */
        !           762:                        li              r3,kMPPOffline                                          /* Set offline */
        !           763:                        beq-    ErrorReturn                                                     /* Ain't online, ain't ready, buzz off... */
        !           764:                        oris    r5,r5,(MPPICBusy>>16)&0x0000FFFF        /* Turn on the busy bit */
        !           765:                        li              r0,0                                                            /* Clear this */
        !           766:                        
        !           767:                        stwcx.  r5,0,r9                                                         /* Try to set busy */
        !           768:                        ori             r10,r10,MPPICfTBsy<<8                           /* Put the timebase sync function in front of the processor ID */
        !           769:                        bne-    SyCretry                                                        /* Lost reservation, return busy... */
        !           770: 
        !           771:                        stw             r0,MPPITBsync+4-MPPIwork(r12)           /* Make sure the parm area is 0 */
        !           772:                        mr              r0,r11                                                          /* Save the LR */
        !           773:                        bl              SyCbase                                                         /* Get a base register */
        !           774: SyCbase:       rlwimi  r5,r10,0,16,31                                          /* Put these behind the status flags */
        !           775:                        mflr    r11                                                                     /* Get the base */
        !           776:                        la              r11,(4*4)(r11)                                          /* DON'T MESS WITH THESE INSTRUCTIONS Make up the return point */
        !           777:                        b               KickAndGo                                                       /* Go signal the other side */
        !           778: 
        !           779: SyCKrtrn:      mr              r11,r0                                                          /* Restore the return */
        !           780: 
        !           781: /* */
        !           782: /*                     Start sync'ing 'er up */
        !           783: /* */
        !           784:                
        !           785:                        mftb    r4                                                                      /* Take a timeout stamp (don't need top half, we have at least 13 hours) */
        !           786: 
        !           787: SyCInP0:       lwz             r5,0(r9)                                                        /* Get the CPU status word */
        !           788:                        rlwinm  r5,r5,24,24,31                                          /* Isolate the command byte */
        !           789:                        cmplwi  cr0,r5,MPPICfTBsy1                                      /* Have we reached time base sync phase 1 yet? */
        !           790:                        beq             SyCInP1                                                         /* Yeah, we're in phase 1... */
        !           791:                        mftb    r5                                                                      /* Get the bottom half of the timer again */
        !           792:                        sub             r5,r5,r4                                                        /* How long we been messin' around? */
        !           793:                        cmplwi  cr0,r5,1000*TicksPerMic                         /* Don't try more'n' a 1000�S */
        !           794:                        blt+    SyCInP0                                                         /* We haven't, so wait some more... */
        !           795:                        li              r3,kMPPTimeOut                                          /* Signal timeout */
        !           796:                        b               ErrorReturn                                                     /* By dude... */
        !           797:                        
        !           798: /* */
        !           799: /*                     Here we make sure there is enough time to sync the clocks before the lower part of the TB ticks */
        !           800: /*                     up into the high part.  This eliminates the need for any funky  */
        !           801: /*                     "get-the-top-then-get-the-bottom-then-get-the-top-again-to-see-if-it-changed" stuff.  That would */
        !           802: /*                     only make the sync harder to do. */
        !           803: /*                      */
        !           804: /*                     Also, because we use the lower TB value for the signal, we also need to make sure we do not have */
        !           805: /*                     a value of 0, we would be ever-so-sorry if it was. */
        !           806: /* */
        !           807: 
        !           808: SyCInP1:       li              r4,lo16(0xC000)                                         /* Get the minimum time left on clock before tick ('bout 1 1/4 ms) */
        !           809:                        li              r8,0                                                            /* Get a 0 constant */
        !           810:                        
        !           811: SyCdelay:      mftb    r5                                                                      /* Get the time left */
        !           812:                        cmplw   cr0,r5,r4                                                       /* See if there is sufficient time before carry into high clock */
        !           813:                        bgt-    SyCdelay                                                        /* Nope, hang until it is... */
        !           814:                        mr.             r5,r5                                                           /* Did we just tick, however? */
        !           815:                        beq-    SyCdelay                                                        /* Yeah, wait until it is at least 1... */
        !           816:                        
        !           817:                        mftbu   r4                                                                      /* Get the upper */
        !           818:                        stw             r4,MPPITBsync-MPPIwork(r12)                     /* Make sure the top half is set */
        !           819:                        sync                                                                            /* Wait until it is done */
        !           820:                        
        !           821:                        mftb    r5                                                                      /* Get the lower timebase now */
        !           822:                        stw             r5,MPPITBsync+4-MPPIwork(r12)           /* Shove it out for the other processor */
        !           823: 
        !           824:                        la              r6,MPPISncFght-MPPIwork(r12)            /* Point to the courtroom area */
        !           825:                        li              r5,0                                                            /* Point to the first line */
        !           826: 
        !           827: SyCclear:      dcbz    r5,r6                                                           /* Clear the court */
        !           828:                        addi    r5,r5,32                                                        /* Point to the next line */
        !           829:                        cmplwi  cr0,r5,10*2*32                                          /* Enough for 9 iterations, 2 chunks at a time */
        !           830:                        blt+    SyCclear                                                        /* Clear the whole smear... */
        !           831:                        sync                                                                            /* Make sure everyone's out */
        !           832: 
        !           833:                        mftb    r5                                                                      /* Get the lower timebase now */
        !           834:                
        !           835: SyCWait:       lwz             r7,MPPITBsync+4-MPPIwork(r12)           /* Get it back */
        !           836:                        mftb    r6                                                                      /* Get the bottom half again */
        !           837:                        mr.             r7,r7                                                           /* Have they set their clock yet? */
        !           838:                        sub             r0,r6,r5                                                        /* See if we're hung up */
        !           839:                        beq-    SyCdonesync                                                     /* Clock is set */
        !           840:                        cmplwi  cr0,r0,1000*TicksPerMic                         /* Timeout if we spend more than 1000�S doing this */
        !           841:                        blt+    SyCWait                                                         /* No timeout, wait some more... */
        !           842:                        li              r3,kMPPTimeOut                                          /* Set timeout */
        !           843:                        b               ErrorReturn                                                     /* Leave... */
        !           844:                        
        !           845: /* */
        !           846: /*                     Ok, so now we have set a preliminary TB value on the second processor.  It's close, but only */
        !           847: /*                     within handgranade range.   */
        !           848: /* */
        !           849: /*                     What we will do now is to let the processors (starting with the other guy) argue about the time for */
        !           850: /*                     a while (10 passes-we use the middle 8).  We'll look at the results and try to adjust the other processor's */
        !           851: /*                     time such that the timing windows are overlapping evenly. This should put the TBs close enough together */
        !           852: /*                     (0-2 ticks) that the difference is undetectable. */
        !           853: /* */
        !           854: 
        !           855: 
        !           856:                        
        !           857: SyCdonesync:
        !           858:                        li              r4,0                                                            /* Clear this */
        !           859:                        la              r5,MPPISncFght-MPPIwork(r12)            /* Point to the squared circle */
        !           860: 
        !           861: SyCWtArg:      
        !           862:                        dcbf    0,r5                                                            /* Make sure of it */
        !           863:                        sync                                                                            /* Doubly shure */
        !           864:                        lwz             r6,0(r5)                                                        /* Listen for the defence argument */
        !           865: 
        !           866:                        mr.             r6,r6                                                           /* See if they are done */
        !           867:                        beq+    SyCWtArg                                                        /* Nope, still going... */
        !           868: 
        !           869:                        mftb    r7                                                                      /* They're done, time for rebuttal */
        !           870:                        stw             r7,32(r5)                                                       /* Make rebuttle */
        !           871:        
        !           872:                        addi    r4,r4,1                                                         /* Count rounds */
        !           873: 
        !           874:                        cmplwi  cr0,r4,10                                                       /* See if we've gone 8 rounds plus an extra one */
        !           875:                        addi    r5,r5,64                                                        /* Point to the next round areas */
        !           876: 
        !           877:                        blt+    SyCWtArg                                                        /* Not yet, come out of your corners fighting... */
        !           878:                        
        !           879:                        mftb    r5                                                                      /* Stamp the wait */
        !           880:                        
        !           881: SyCWadj:       lwz             r7,MPPITBsync+4-MPPIwork(r12)           /* Get adjustment flag */
        !           882:                        mftb    r6                                                                      /* Get timebase again */
        !           883:                        
        !           884:                        mr.             r7,r7                                                           /* Have they set their timebase with adjusted time yet? */
        !           885:                        sub             r6,r6,r5                                                        /* Get elapsed time */
        !           886:                        bne+    SyCdone                                                         /* They say it, sync done... */
        !           887:                        cmplwi  cr0,r6,1000*TicksPerMic                         /* Timeout if we spend more than 1000�S doing this */
        !           888:                        blt+    SyCWadj                                                         /* Still time, wait until adjustment is done... */
        !           889:                        
        !           890:                        li              r3,kMPPTimeOut                                          /* Set timeout */
        !           891:                        b               ErrorReturn                                                     /* Pass it back... */
        !           892:                        
        !           893: SyCdone:       li              r3,kSIGPnoErr                                           /* No errors */
        !           894:                        mtlr    r11                                                                     /* Restore LR */
        !           895:                        blr                                                                                     /* Leave... */
        !           896: 
        !           897: 
        !           898: /******************************************************************************************************** */
        !           899: /* */
        !           900: /*                     Here we will get the physical address of the interrupt handler. */
        !           901: /* */
        !           902: /******************************************************************************************************** */
        !           903:                        
        !           904: GetExtHandlerAddress:
        !           905:                        mflr    r11                                                                     /* Save our return */
        !           906:                        bl              GEXbase                                                         /* Make a base address */
        !           907: GEXbase:       mflr    r3                                                                      /* Get address into our base */
        !           908:                        addi    r3,r3,LOW_ADDR(GotSignal-GEXbase)       /* Get the logical address of the 'rupt handler */
        !           909: 
        !           910:                        mtlr    r11                                                                     /* Restore LR */
        !           911:                        blr
        !           912: 
        !           913: 
        !           914: /******************************************************************************************************** */
        !           915: /* */
        !           916: /*                     Here we will get a snapshot of the processor's current signaling state (R3=processor). */
        !           917: /* */
        !           918: /******************************************************************************************************** */
        !           919:                        
        !           920: ProcessorState:
        !           921:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           922:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           923:                        cmplwi  cr1,r3,MPPIMaxCPU                                       /* See if we are bigger than max */
        !           924:                        li              r3,kSIGPTargetAddrErr                           /* CPU number is too big */
        !           925:                        bgtlr-  cr1                                                                     /* Sure are... (Get our address also) */
        !           926:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !           927:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           928:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !           929:                        lwz             r4,MPPICStat(r9)                                        /* Get the status word */
        !           930:                        li              r3,kSIGPnoErr                                           /* Set no errors */
        !           931:                        rlwinm. r4,r4,0,0,0                                                     /* Test for busy status */
        !           932:                        beqlr                                                                           /* Return kSIGPnoErr if not busy */
        !           933:                        li              r3,kSIGPInterfaceBusyErr                        /* Otherwise, return busy */
        !           934:                        blr                                                                                     /* Return it */
        !           935: 
        !           936: /******************************************************************************************************** */
        !           937: /* */
        !           938: /*                     Here we will try to handle any pending messages (just as if an interruption occurred). */
        !           939: /*                     The purpose of this function is to assure the message passing system runs even */
        !           940: /*                     though external interrupts are disabled. Lacking a separate physical signalling */
        !           941: /*                     class, we have to share the external interrupt signal. Unfortunately, there are */
        !           942: /*                     times when disabled loops occur (in spin locks, in the debugger, etc.), and when they */
        !           943: /*                     happen, a low level message sent to a processor will not get processed, hence this */
        !           944: /*                     function exists to be called from those disabled loops. Since the calls are often */
        !           945: /*                     from disabled code, all that can be done is to process any pending *message*. Any */
        !           946: /*                     pending notification interruption (referred to throughtout this code as a SIGP */
        !           947: /*                     interruption) must remain pending. */
        !           948: /* */
        !           949: /******************************************************************************************************** */
        !           950:                        
        !           951: RunSIGPRun:
        !           952:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !           953:                        mfspr   r3,pir                                                          /* Get our CPU address */
        !           954:                        rlwinm  r9,r3,5,23,26                                           /* Get index into CPU array */
        !           955:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !           956:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !           957:                        mflr    r11                                                                     /* Save the link register */
        !           958:                        add             r9,r9,r12                                                       /* Point right at our entry */
        !           959:                        lwz             r3,MPPICPriv(r9)                                        /* Get our privates */
        !           960:                        cmplw   cr1,r11,r11                                                     /* Make sure IdleWait doesn't try to clear 'rupt request */
        !           961:                        oris    r3,r3,MPPICXRun>>16                                     /* Diddle with them and show we entered here */
        !           962:                        stw             r3,MPPICPriv(r9)                                        /* Put away our privates */
        !           963:                        b               IdleWait                                                        /* Go pretend there was an interrupt... */
        !           964: 
        !           965: /******************************************************************************************************** */
        !           966: /* */
        !           967: /*                     Error return.  We only need this when we leave with a reservation.  We really SHOULD clear it... */
        !           968: /* */
        !           969: /******************************************************************************************************** */
        !           970: 
        !           971: ErrorReturn:
        !           972:                        mtlr    r11                                                                     /* Restore LR */
        !           973:                        blr                                                                                     
        !           974: 
        !           975: /******************************************************************************************************** */
        !           976: /* */
        !           977: /*                     Kick the target processor.  Note that we won't set the passing bit until we are ready to exit. */
        !           978: /*                     The reason for this is that we have the silly, old watchchihuahua board to deal with.  Because  */
        !           979: /*                     we can't just set the interrupt and leave, we gotta wait for it to be seen on the other side. */
        !           980: /*                     This means that there could be a timeout and if so, we need to back off the function request else */
        !           981: /*                     we'd see busy when they tried to redrive it.  We'll have to deal with a tad of spin on the secondary side. */
        !           982: /*                     note that this just applies to a primary to secondary function on the old board. */
        !           983: /* */
        !           984: /******************************************************************************************************** */
        !           985:        
        !           986: KickAndGo:
        !           987:                        la              r8,MPPICPU0-MPPIwork(r12)                       /* Get the primary work area address */
        !           988:                        mtlr    r11                                                                     /* Restore the link register */
        !           989:                        cmplw   cr0,r8,r9                                                       /* Which is target?  primary or secondary? */
        !           990:                        mfmsr   r11                                                                     /* Save off the MSR */
        !           991:                        oris    r5,r5,MPPICPass>>16                                     /* Set the passing bit on */
        !           992:                        stw             r5,MPPICStat(r9)                                        /* Store the pass and let the other processor go on */
        !           993:                        
        !           994:                        beq             KickPrimary                                                     /* The target is the primary... */
        !           995:                        
        !           996:                        ori             r3,r11,0x0010                                           /* Turn on DDAT bit */
        !           997:                        lbz             r4,MPPIstatus-MPPIwork(r12)                     /* Load up the global status byte */
        !           998:                        lwz             r8,MPPIHammer-MPPIwork(r12)                     /* Point to the Hammerhead area */
        !           999:        
        !          1000:                        mtmsr   r3                                                                      /* Turn on DDAT */
        !          1001:                        isync
        !          1002:                        
        !          1003:                        andi.   r4,r4,MPPI2Pv2                                          /* Are we on the new or old board? */
        !          1004:                        li              r3,0                                                            /* Set the bit for an interrupt request */
        !          1005:                        beq             KickOld                                                         /* Ok, it's the old board... */
        !          1006:                        
        !          1007:                        sync                                                                            /* Make sure this is out there */
        !          1008:                        stb             r3,IntReg(r8)                                           /* Set the interruption signal */
        !          1009:                        eieio
        !          1010:        
        !          1011:                        mtmsr   r11                                                                     /* Set DDAT back to what it was */
        !          1012:                        isync
        !          1013:                        li              r3,kSIGPnoErr                                           /* Set no errors */
        !          1014:                        blr                                                                                     /* Leave... */
        !          1015:                        
        !          1016: KickOld:       li              r4,8                                                            /* Set the number of tries */
        !          1017: 
        !          1018: KickAgain:     mftb    r6                                                                      /* Stamp the bottom half of time base */
        !          1019:                        stb             r3,IntReg(r8)                                           /* Stick the interrupt */
        !          1020:                        eieio                                                                           /* Fence me in */
        !          1021:                        
        !          1022: CheckKick:     lbz             r10,IntReg(r8)                                          /* Get the interrupt request back again */
        !          1023:                        mr.             r10,r10                                                         /* Yes? Got it? */
        !          1024:                        bne             FinalDelay                                                      /* Yeah, do the final delay and then go away... */
        !          1025:                        
        !          1026:                        mftb    r7                                                                      /* Get the time again */
        !          1027:                        sub             r7,r7,r6                                                        /* Get time-so-far */
        !          1028:                        cmplwi  cr0,r7,75*TicksPerMic                           /* Hold it for 75�S (average disable is supposed to be 100�S or so) */
        !          1029:                        blt+    CheckKick                                                       /* Keep waiting the whole time... */
        !          1030:                        
        !          1031:                        li              r10,SecInt                                                      /* Set the deassert bit */
        !          1032:                        mftb    r6                                                                      /* Stamp start of deassert time */
        !          1033:                        stb             r10,IntReg(r8)                                          /* Deassert the interrupt request */
        !          1034:                        eieio
        !          1035:                        
        !          1036: DeassertWT:    mftb    r7                                                                      /* Stamp out the time */
        !          1037:                        sub             r7,r7,r6                                                        /* Get elapsed */
        !          1038:                        cmplwi  cr0,r7,16*TicksPerMic                           /* Hold off 16�S (minimum is 12�S) */
        !          1039:                        blt+    DeassertWT                                                      /* Keep spinning... */
        !          1040:                        
        !          1041:                        subi    r4,r4,1                                                         /* See if we have another retry we can do */
        !          1042:                        mr.             r4,r4                                                           /* Are we there yet? */
        !          1043:                        blt+    KickAgain                                                       /* Retry one more time... */
        !          1044:                        
        !          1045:                        rlwinm  r5,r5,0,2,31                                            /* Clear busy and passing bits */
        !          1046:                        rlwinm  r5,r5,0,24,15                                           /* Clear the function request to idle */
        !          1047:                        
        !          1048:                        mtmsr   r11                                                                     /* Restore DDAT stuff */
        !          1049:                        isync
        !          1050: 
        !          1051:                        stw             r5,MPPICStat(r9)                                        /* Rescind the request */
        !          1052:                        li              r3,kMPPTimeOut                                          /* Set timeout */
        !          1053:                        blr                                                                                     /* Leave... */
        !          1054:                        
        !          1055: FinalDelay:    mftb    r6                                                                      /* Stamp the start of the final delay */
        !          1056: 
        !          1057: FinalDelayW:
        !          1058:                        mftb    r7                                                                      /* Stamp out the time */
        !          1059:                        sub             r7,r7,r6                                                        /* Get elapsed */
        !          1060:                        cmplwi  cr0,r7,16*TicksPerMic                           /* Hold off 16�S (minimum is 12�S) */
        !          1061:                        blt+    FinalDelayW                                                     /* Keep spinning... */
        !          1062: 
        !          1063:                        mtmsr   r11                                                                     /* Restore DDAT stuff */
        !          1064:                        isync
        !          1065:                        li              r3,kSIGPnoErr                                           /* Set no errors */
        !          1066:                        blr                                                                                     /* Leave... */
        !          1067:                        
        !          1068: KickPrimary:
        !          1069:                        ori             r3,r11,0x0010                                           /* Turn on the DDAT bit */
        !          1070:                        lwz             r8,MPPIEther-MPPIwork(r12)                      /* Get the address of the ethernet ROM */
        !          1071:                        
        !          1072:                        mtmsr   r3                                                                      /* Turn on DDAT */
        !          1073:                        isync
        !          1074: 
        !          1075:                        li              r4,4                                                            /* Get flip count */
        !          1076:                        
        !          1077:                        sync                                                                            /* Make sure the status word is out there */
        !          1078: 
        !          1079: FlipOff:       lbz             r3,0(r8)                                                        /* Reference ethernet ROM to get chip select twiddled */
        !          1080:                        eieio                                                                           /* Make sure of this (Hmm, this is chip select, not memory-mapped */
        !          1081:                                                                                                                /* storage.  Do we even need the eieio?) */
        !          1082:                                                                                                                
        !          1083:                        addic.  r4,r4,-1                                                        /* Have we flipped them off enough? */
        !          1084:                        bgt+    FlipOff                                                         /* Not yet, they deserve more... */
        !          1085:                        
        !          1086:                        mtmsr   r11                                                                     /* Restore DDAT stuff */
        !          1087:                        isync
        !          1088:                        li              r3,kSIGPnoErr                                           /* Set no errors */
        !          1089:                        blr                                                                                     /* Return... */
        !          1090: 
        !          1091: /******************************************************************************************************** */
        !          1092: /* */
        !          1093: /*                     This is the code for the secondary processor */
        !          1094: /* */
        !          1095: /******************************************************************************************************** */
        !          1096: 
        !          1097: /*                     Note that none of this code needs locks because there's kind of a synchronization */
        !          1098: /*                     shuffle going on. */
        !          1099: 
        !          1100: /* */
        !          1101: /*                     First, we need to do a bit of initialization of the processor. */
        !          1102: /* */
        !          1103: 
        !          1104: 
        !          1105: CPUInit:       
        !          1106:                        li              r27,0x3040                                                      /* Set floating point and machine checks on, IP to 0xFFF0xxxx */
        !          1107:                        mtmsr   r27                                                                     /* Load 'em on in */
        !          1108:                        isync
        !          1109:                        
        !          1110:                        lis             r28,-32768                                                      /* Turn on machine checks */
        !          1111:                                                                                                                /* should be 0x8000 */
        !          1112:                        ori             r28,r28,0xCC84                                          /* Enable caches, clear them,  */
        !          1113:                                                                                                                /* disable serial execution and turn BHT on */
        !          1114:                        sync
        !          1115:                        mtspr   HID0,r28                                                        /* Start the cache clear */
        !          1116:                        sync
        !          1117: 
        !          1118: /* */
        !          1119: /*                     Clear out the TLB.  They be garbage after hard reset. */
        !          1120: /* */
        !          1121: 
        !          1122:                        li              r0,512                                                          /* Get number of TLB entries (FIX THIS) */
        !          1123:                        li              r3,0                                                            /* Start at 0 */
        !          1124:                        mtctr   r0                                                                      /* Set the CTR */
        !          1125:                        
        !          1126: purgeTLB:      tlbie   r3                                                                      /* Purge this entry */
        !          1127:                        addi    r3,r3,4096                                                      /* Next page */
        !          1128:                        bdnz    purgeTLB                                                        /* Do 'em all... */
        !          1129:                                        
        !          1130:                        sync                                                                            /* Make sure all TLB purges are done */
        !          1131:                        tlbsync                                                                         /* Make sure on other processors also */
        !          1132:                        sync                                                                            /* Make sure the TLBSYNC is done */
        !          1133: 
        !          1134: /* */
        !          1135: /*                     Clear out the BATs.  They are garbage after hard reset. */
        !          1136: /* */
        !          1137: 
        !          1138:                        li              r3,0                                                            /* Clear a register */
        !          1139:                        
        !          1140:                        mtspr   DBAT0L,r3                                                       /* Clear BAT */
        !          1141:                        mtspr   DBAT0U,r3                                                       /* Clear BAT */
        !          1142:                        mtspr   DBAT1L,r3                                                       /* Clear BAT */
        !          1143:                        mtspr   DBAT1U,r3                                                       /* Clear BAT */
        !          1144:                        mtspr   DBAT2L,r3                                                       /* Clear BAT */
        !          1145:                        mtspr   DBAT2U,r3                                                       /* Clear BAT */
        !          1146:                        mtspr   DBAT3L,r3                                                       /* Clear BAT */
        !          1147:                        mtspr   DBAT3U,r3                                                       /* Clear BAT */
        !          1148:                        
        !          1149:                        mtspr   IBAT0L,r3                                                       /* Clear BAT */
        !          1150:                        mtspr   IBAT0U,r3                                                       /* Clear BAT */
        !          1151:                        mtspr   IBAT1L,r3                                                       /* Clear BAT */
        !          1152:                        mtspr   IBAT1U,r3                                                       /* Clear BAT */
        !          1153:                        mtspr   IBAT2L,r3                                                       /* Clear BAT */
        !          1154:                        mtspr   IBAT2U,r3                                                       /* Clear BAT */
        !          1155:                        mtspr   IBAT3L,r3                                                       /* Clear BAT */
        !          1156:                        mtspr   IBAT3U,r3                                                       /* Clear BAT */
        !          1157: 
        !          1158: /* */
        !          1159: /*                     Map 0xF0000000 to 0xFFFFFFFF for I/O; make it R/W non-cacheable */
        !          1160: /*                     Map     0x00000000 to 0x0FFFFFFF for mainstore; make it R/W cachable */
        !          1161: /* */
        !          1162: 
        !          1163:                        lis             r6,0xF000                                                       /* Set RPN to last segment */
        !          1164:                        ori             r6,r6,0x1FFF                                            /* Set up upper BAT for 256M, access both */
        !          1165:                        
        !          1166:                        lis             r7,0xF000                                                       /* Set RPN to last segment */
        !          1167:                        ori             r7,r7,0x0032                                            /* Set up lower BAT for 256M, access both, non-cachable */
        !          1168:                
        !          1169:                        mtspr   DBAT0L,r7                                                       /* Setup ROM and I/O mapped areas */
        !          1170:                        mtspr   DBAT0U,r6                                                       /* Now do the upper DBAT */
        !          1171:                        sync
        !          1172:        
        !          1173:                        li              r6,0x1FFF                                                       /* Set up upper BAT for 256M, access both */
        !          1174:                        li              r7,0x0012                                                       /* Set up lower BAT for r/w access */
        !          1175:                        
        !          1176:                        mtspr   DBAT1L,r7                                                       /* Set up an initial view of mainstore */
        !          1177:                        mtspr   DBAT1U,r6                                                       /* Now do the upper DBAT */
        !          1178:                        sync
        !          1179: 
        !          1180: /* */
        !          1181: /*                     Clean up SDR and segment registers */
        !          1182: /* */
        !          1183: 
        !          1184:                        li              r3,0                                                            /* Clear a register */
        !          1185:                        mtspr   SDR1,r3                                                         /* Clear SDR1 */
        !          1186:                        
        !          1187:                        li              r4,0                                                            /* Clear index for segment registers */
        !          1188:                        lis             r5,0x1000                                                       /* Set the segment indexer */
        !          1189:                        
        !          1190: clearSR:       mtsrin  r3,r4                                                           /* Zero out the SR */
        !          1191:                        add.    r4,r4,r5                                                        /* Point to the next segment */
        !          1192:                        bne-    clearSR                                                         /* Keep going until we wrap back to 0 */
        !          1193:                        
        !          1194:                        lis             r5,HIGH_ADDR(EXT(FloatInit))            /* Get top of floating point init value */
        !          1195:                        ori             r5,r5,LOW_ADDR(EXT(FloatInit))          /* Slam bottom */
        !          1196:                        lfd             f0,0(r5)                                                        /* Initialize FP0 */
        !          1197:                        fmr             f1,f0                                                           /* Ours in not */                                       
        !          1198:                        fmr             f2,f0                                                           /* to wonder why, */
        !          1199:                        fmr             f3,f0                                                           /* ours is but to */
        !          1200:                        fmr             f4,f0                                                           /* do or die! */
        !          1201:                        fmr             f5,f0                                           
        !          1202:                        fmr             f6,f0                                           
        !          1203:                        fmr             f7,f0                                           
        !          1204:                        fmr             f8,f0                                           
        !          1205:                        fmr             f9,f0                                           
        !          1206:                        fmr             f10,f0                                          
        !          1207:                        fmr             f11,f0                                          
        !          1208:                        fmr             f12,f0                                          
        !          1209:                        fmr             f13,f0                                          
        !          1210:                        fmr             f14,f0                                          
        !          1211:                        fmr             f15,f0                                          
        !          1212:                        fmr             f16,f0                                          
        !          1213:                        fmr             f17,f0                                          
        !          1214:                        fmr             f18,f0                                          
        !          1215:                        fmr             f19,f0                                          
        !          1216:                        fmr             f20,f0                                          
        !          1217:                        fmr             f21,f0                                          
        !          1218:                        fmr             f22,f0                                          
        !          1219:                        fmr             f23,f0                                          
        !          1220:                        fmr             f24,f0                                          
        !          1221:                        fmr             f25,f0                                          
        !          1222:                        fmr             f26,f0                                          
        !          1223:                        fmr             f27,f0                                          
        !          1224:                        fmr             f28,f0                                          
        !          1225:                        fmr             f29,f0                                          
        !          1226:                        fmr             f30,f0                                          
        !          1227:                        fmr             f31,f0                                          
        !          1228:                        
        !          1229: /* */
        !          1230: /*                     Whew, that was like, work, man!  What a cleaning job, I should be neater */
        !          1231: /*                     when I reset. */
        !          1232: /* */
        !          1233: /*                     Finally we can get some data DAT turned on and we can reset the interrupt */
        !          1234: /*                     (which may have been done before we get here) and get into the bring up */
        !          1235: /*                     handshakes. */
        !          1236: /*              */
        !          1237: /*                     Note that here we need to use the actual V=R addresses for HammerHead */
        !          1238: /*                     and PCI1 adr.  There are no virtual mappings set up on this processor. */
        !          1239: /*                     We need to switch once the firmware is initialized.  Also, we don't know */
        !          1240: /*                     where our control block is yet. */
        !          1241: /* */
        !          1242:                
        !          1243:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !          1244:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !          1245: 
        !          1246:                        mfmsr   r3                                                                      /* Get the MSR */
        !          1247:                        ori             r3,r3,0x0010                                            /* Turn data DAT on */
        !          1248:                        mtmsr   r3                                                                      /* DAT is on (well, almost) */
        !          1249:                        isync                                                                           /* Now it is for sure */
        !          1250:                
        !          1251:                        lis             r8,HammerHead>>16                                       /* Point to the HammerHead controller */
        !          1252:                        li              r7,SecInt                                                       /* Get value to reset */
        !          1253:                        stb             r7,IntReg(r8)                                           /* Reset the interrupt */
        !          1254:                        eieio                                                                           /* Fence it off */
        !          1255:                
        !          1256: /* */
        !          1257: /*                     Now we can plant and harvest some bits. */
        !          1258: /* */
        !          1259:                
        !          1260:                        lwz             r6,MPPIlogCPU-MPPIwork(r12)                     /* Get the logical CPU address to assign */
        !          1261:                        mfspr   r7,pir                                                          /* Get the old PIR */
        !          1262:                        rlwimi  r7,r6,0,27,31                                           /* Copy all of the reserved parts */
        !          1263:                        mtspr   pir,r7                                                          /* Set it */
        !          1264:                        
        !          1265: /* */
        !          1266: /*                     This little piece of code here determines if we are on the first or second version */
        !          1267: /*                     of the two processor board.  The old one shouldn't ever be shipped (well, maybe by  */
        !          1268: /*                     DayStar) but there are some around here. */
        !          1269: /* */
        !          1270: /*                     The newer version of the 2P board has a different state machine than the older one. */
        !          1271: /*                     When we are in the board state we're in now, primary arbitration is turned on while */
        !          1272: /*                     it is not until the next state in the old board.  By checking the our bus address */
        !          1273: /*                     (WhoAmI) we can tell. */
        !          1274: /* */
        !          1275: 
        !          1276:                        lbz             r7,WhoAmI(r8)                                           /* Get the current bus master ID */
        !          1277:                        andi.   r7,r7,PriCPU                                            /* Do we think we're the primary? */
        !          1278:                        beq             On2Pv1                                                          /* No, that means we're on the old 2P board */
        !          1279:                        
        !          1280:                        lbz             r7,MPPIstatus-MPPIwork(r12)                     /* Get the status byte */
        !          1281:                        ori             r7,r7,MPPI2Pv2                                          /* Show we're on the new board */
        !          1282:                        stb             r7,MPPIstatus-MPPIwork(r12)                     /* Set the board version */
        !          1283:                        
        !          1284: On2Pv1:                rlwinm  r9,r6,5,23,26                                           /* Get index into the CPU specific area */
        !          1285:                                
        !          1286:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Index to processor */
        !          1287:                        add             r9,r9,r12                                                       /* Get a base for our CPU specific area */
        !          1288:                        
        !          1289:                        oris    r6,r6,((MPPICBusy+MPPICOnline+MPPICStop)>>16)&0x0000FFFF        /* Set CPU busy, online, stopped,  */
        !          1290:                                                                                                                                                                /*   and busy set by himself */
        !          1291:                        stw             r6,MPPICStat(r9)                                        /* Save the whole status word */
        !          1292:                        
        !          1293:                        li              r4,0x80                                                         /* Get beginnings of a CPU address mask */
        !          1294:                        lhz             r11,MPPIinst-MPPIwork(r12)                      /* Get the installed and online status flags */
        !          1295:                        srw             r4,r4,r6                                                        /* Make a mask */
        !          1296:                        rlwimi  r4,r4,8,16,23                                           /* Double up the mask for both flags */
        !          1297:                        or              r11,r11,r4                                                      /* Set that we are installed and online */
        !          1298:                        sync                                                                            /* Make sure the main processor sees the rest of the stuff */
        !          1299:                        
        !          1300:                        sth             r11,MPPIinst-MPPIwork(r12)                      /* We're almost done, just need to set the TB */
        !          1301:                        
        !          1302:                        lis             r5,PCI1AdrReg>>16                                       /* Point to the PCI1 address register            */
        !          1303:                        li              r4,0                                                            /* Clear this out */
        !          1304:                        stw             r4,0(r5)                                                        /* Set PCI register to 0 to show we're ready for TB sync */
        !          1305:                        eieio                                                                           /* Fence it off */
        !          1306: 
        !          1307: Wait4TB:       lwz             r7,0(r5)                                                        /* Get the PCI1 reg to see if time to set time */
        !          1308:                        mr.             r7,r7                                                           /* Is it ready yet? */
        !          1309:                        beq             Wait4TB                                                         /* Nope, wait for it... */
        !          1310:                        isync                                                                           /* No peeking... */
        !          1311:                        
        !          1312:                        lwz             r3,MPPITBsync-MPPIwork(r12)                     /* Get the high word of TB */
        !          1313:                        lwz             r4,MPPITBsync+4-MPPIwork(r12)           /* Get the low word */
        !          1314:                        
        !          1315: /*                     Note that we need no TB magic here 'cause they ain't running */
        !          1316: 
        !          1317:                        mttbu   r3                                                                      /* Set the high part */
        !          1318:                        mttbl   r4                                                                      /* Set the low part */
        !          1319:                        
        !          1320:                        rlwinm  r6,r6,0,2,31                                            /* Clear the busy bit and passed */
        !          1321:                        stw             r6,MPPICStat(r9)                                        /* Store the status word */
        !          1322:                        
        !          1323:                        sync                                                                            /* Make sure all is right with the world */
        !          1324:                        
        !          1325:                        li              r3,0                                                            /* Set the init done signal */
        !          1326:                        stw             r3,0(r5)                                                        /* Feed the dog and let him out */
        !          1327:                        sync                                                                            /* Make sure this is pushed on out */
        !          1328: 
        !          1329:                        li              r27,0x3040                                                      /* Make MSR the way we likes it */
        !          1330:                        mtmsr   r27                                                                     /* Load 'em on in */
        !          1331:                        isync
        !          1332: 
        !          1333: /* */
        !          1334: /*                     Jump on to the idle wait loop.  We're online and ready, but we're */
        !          1335: /*                     still in the reset state.  We need to wait until we see a start signal. */
        !          1336: /* */
        !          1337: /*                     Note that the idle loop expects R9 to be our CPU-specific work area; */
        !          1338: /*                     R12 is the base of the code and global work area  */
        !          1339: /* */
        !          1340: 
        !          1341:                        cmplw   cr1,r11,r12                                                     /* Make sure IdleWait knows to clear 'rupt request */
        !          1342:                        b               IdleWait
        !          1343: 
        !          1344: 
        !          1345: /******************************************************************************************************** */
        !          1346: /******************************************************************************************************** */
        !          1347: /* */
        !          1348: /*                     Here is the interruption handler. */
        !          1349: /* */
        !          1350: /*                     What we'll do here is to get our registers into a standard state and figure out which */
        !          1351: /*                     which processor we are on.  The processors have pretty much the same code.  The primary */
        !          1352: /*                     will reset the the secondary to primary interruption bit and the secondary will reset the SecInt */
        !          1353: /*                     flags. */
        !          1354: /* */
        !          1355: /*                     The primary to secondary interrupt is an exception interruption contolled by a bit in the  */
        !          1356: /*                     Hammerhead IntReg.  The only bit in here is SecInt which is active low.  Writing a 0 into the */
        !          1357: /*                     bit (bit 0) yanks on the external pin on the secondary.  Note that it is the only external */
        !          1358: /*                     connected on the secondary.  SecInt must be set to 1 to clear the interruption.  On the old */
        !          1359: /*                     2P board, asserting the external interrupt causes a watchdog timer to start which expires unless */
        !          1360: /*                     the interrupt request is withdrawn. On a 180Mhz system the time to expire is about 256�S,  */
        !          1361: /*                     not very long.  So, what we need to do is to time the assertion and if it has not been reset */
        !          1362: /*                     reset, do it ourself.  Unfortunatelty we need to keep it deasserted for at least 12�S or the  */
        !          1363: /*                     watchdog will not stop.  This leads to another problem: even if the secondary processor sees */
        !          1364: /*                     the interrupt and deasserts the request itself,  we cannot reassert before the 12�S limit, */
        !          1365: /*                     else havoc will be wrought.  We just gotta make sure. */
        !          1366: /* */
        !          1367: /*                     So, the secondary to primary interrupt is megafunky.  The mother board is wired with the  */
        !          1368: /*                     MACE ethernet chip's chip-select pin wired to Grand Centeral's external interrrupt #10 pin. */
        !          1369: /*                     This causes a transient interrupt whenever MACE is diddled. GC latches the interrupt into the */
        !          1370: /*                     events register where we can see it and clear it. */
        !          1371: /* */
        !          1372: /******************************************************************************************************** */
        !          1373: /******************************************************************************************************** */
        !          1374: 
        !          1375: GotSignal:     mfspr   r9,pir                                                          /* Get our processor ID */
        !          1376:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top half of the data area */
        !          1377:                        rlwinm  r9,r9,5,23,26                                           /* Clean this up */
        !          1378:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get the bottom half of the data area */
        !          1379:                        la              r9,EXT(MPPICPUs)-MPPIwork(r9)                   /* Point into the proccessor control area */
        !          1380:                        mflr    r11                                                                     /* Save our return */
        !          1381:                        add             r9,r9,r12                                                       /* Point right at the entry */
        !          1382: 
        !          1383: /*                     We'll come in here if we're stopped and found the 'rupt via polling */
        !          1384: /*                     or we were kicked off by the PollSIGP call.  We  need */
        !          1385: /*                     to wipe out the interrupt request no matter how we got here. */
        !          1386: 
        !          1387: SimRupt:       mfmsr   r4                                                                      /* Get the MSR */
        !          1388: 
        !          1389:                        la              r8,MPPICPU0-MPPIwork(r12)                       /* Get address of main processor's work area */
        !          1390:                        ori             r5,r4,0x0010                                            /* Turn on the DDAT bit */
        !          1391:                        cmplw   cr0,r8,r9                                                       /* Are we on the main? */
        !          1392:                        cmplw   cr1,r4,r4                                                       /* Set CR1 to indicate we've cleared any 'rupts */
        !          1393:                        bne             SecondarySig                                            /* Go if we are not on main processor... */
        !          1394: 
        !          1395: /* */
        !          1396: /*                     Handle the secondary to primary signal */
        !          1397: /* */
        !          1398: 
        !          1399: PrimarySig:
        !          1400: 
        !          1401:                        lwz             r8,MPPIGrandC-MPPIwork(r12)                     /* Get the address of the Grand Central area base */
        !          1402:                        mtmsr   r5                                                                      /* Turn on DDAT */
        !          1403:                        isync                                                                           /* Now don't be usin' dem speculative executions */
        !          1404:                        li              r7,EventsReg                                            /* Get address of the interrupt events register */
        !          1405:                        lwbrx   r6,r7,r8                                                        /* Grab the interruption events */
        !          1406: 
        !          1407:                        lis             r5,0x4000                                                       /* Get the mask for the Ext10 pin */
        !          1408:                        and.    r0,r6,r5                                                        /* See if our bit is on */
        !          1409:                        li              r7,ClearReg                                                     /* Point to the interruption clear register */
        !          1410:                
        !          1411:                        beq+    SkpClr                                                          /* Skip the clear 'cause it's supposed to be soooo slow... */
        !          1412:                        
        !          1413:                        stwbrx  r5,r7,r8                                                        /* Reset the interrupt latch */
        !          1414:                        eieio                                                                           /* Fence off the last 'rupt */
        !          1415: 
        !          1416: SkpClr:                mtmsr   r4                                                                      /* Set MSR to entry state */
        !          1417:                        isync                                                                           /* Make sure we ain't gunked up no future storage references */
        !          1418:                
        !          1419:                        bne+    IdleWait                                                        /* Go join up and decode the function... */
        !          1420:                        
        !          1421:                        mtlr    r11                                                                     /* Restore return address */
        !          1422:                        andc.   r0,r6,r5                                                        /* Any other bits on? */
        !          1423:                        li              r3,kMPVainInterrupt                                     /* Assume we got nothing */
        !          1424:                        beqlr                                                                           /* We got nothing, tell 'em to eat 'rupt... */
        !          1425:                        li              r3,kMPIOInterruptPending                        /* Tell them to process an I/O 'rupt */
        !          1426:                        blr                                                                                     /* Ignore the interrupt... */
        !          1427: 
        !          1428: /* */
        !          1429: /*                     Handle the primary to secondary signal */
        !          1430: /* */
        !          1431: 
        !          1432: SecondarySig:
        !          1433:                        lwz             r3,MPPICStat(r9)                                        /* Pick up our status word */
        !          1434:                        lis             r8,HammerHead>>16                                       /* Get the address of the hammerhead (used during INIT on non-main processor) */
        !          1435:                        rlwinm. r3,r3,0,3,3                                                     /* Check if we are already "in-the-know" (all started up) */
        !          1436:                        beq-    UseAltAddr                                                      /* Nope, use hardcoded Hammerhead address */
        !          1437:                        lwz             r8,MPPIHammer-MPPIwork(r12)                     /* Get the kernel's HammerHead area */
        !          1438: 
        !          1439: UseAltAddr:    mtmsr   r5                                                                      /* Turn on DDAT */
        !          1440:                        isync                                                                           /* Now don't be usin' dem speculative executions */
        !          1441:                        li              r0,SecInt                                                       /* Get the Secondary interrupt bit */
        !          1442:                        stb             r0,IntReg(r8)                                           /* Reset the interrupt request */
        !          1443:                        mtmsr   r4                                                                      /* Set MSR to entry state */
        !          1444:                        eieio                                                                           /* Fence me in */
        !          1445:                        isync                                                                           /* Make sure we ain't gunked up no future storage references */
        !          1446:                        
        !          1447:                        b               IdleWait                                                        /* Go decode this request... */
        !          1448:                        
        !          1449: /******************************************************************************************************** */
        !          1450: /******************************************************************************************************** */
        !          1451: /* */
        !          1452: /*                     This is the idle wait.   */
        !          1453: /* */
        !          1454: /*                     We're stuck in here so long as we are stopped or reset. */
        !          1455: /*                     All functions except for "start" pass back through here.  Start is weird because */
        !          1456: /*                     it is an initial thing, i.e., we can't have gotten here via any kind of exception, */
        !          1457: /*                     so there is no state to restore.  The "started" code is expected to require no know */
        !          1458: /*                     state and will take care of all initialization/fixup required. */
        !          1459: /* */
        !          1460: /******************************************************************************************************** */
        !          1461: /******************************************************************************************************** */
        !          1462: 
        !          1463: BadRuptState:                                                                                  /* We don't do anything special yet for a bad state, just eat request */
        !          1464: KillBusy:      rlwinm  r3, r3, 0, 2, 31                                        /* Remove the message pending flags. */
        !          1465:                        rlwinm  r3, r3, 0, 24, 16                                       /* Set the function to idle. */
        !          1466:                        stw             r3,MPPICStat(r9)                                        /* Update/unlock the status word. */
        !          1467: 
        !          1468: ReenterWait: cmplwi    cr1,r9,0                                                        /* Turn off the 'rupt cleared flag */
        !          1469: 
        !          1470: IdleWait:      lis             r4,MPPICBusy>>16                                        /* Get busy status */
        !          1471: 
        !          1472: SpinIdle:                              
        !          1473:                        lwz             r3,MPPICStat(r9)                                        /* Pick up our status word */
        !          1474:                
        !          1475:                        and.    r5,r3,r4                                                        /* Isolate the busy bit */
        !          1476:                        lis             r6,MPPICPass>>16                                        /* Get the passed busy flag */
        !          1477:                        bne             TooBusy                                                         /* Work, work, work, that's all we do is work... */
        !          1478:                        
        !          1479:                        rlwinm. r5,r3,0,4,4                                                     /* See if we are stopped */
        !          1480:                        lwz             r8,MPPICPriv(r9)                                        /* Pick up our private flags */
        !          1481:                        bne-    SpinIdle                                                        /* Yeah, keep spinning... */
        !          1482:                        
        !          1483:                        
        !          1484: /* */
        !          1485: /*                     Restore the state and get outta here.  Now, we shouldn't be in a reset state and not be stopped, */
        !          1486: /*                     so we can go ahead and safely return up a level because it exists.  If we are reset, no state exists */
        !          1487: /*                     and we should always be stopped. */
        !          1488: /* */
        !          1489:                        
        !          1490:                        rlwinm  r4, r8, 1, 0, 0                                         /* Get the explicit run bit, shifted left one. */
        !          1491:                        rlwinm. r5, r8, 0, 0, 0                                         /* See if there is a SIGP signal pending */
        !          1492:                        and             r4, r8, r4                                                      /* Turn off the SIGP pending bit if this was not an explicit run */
        !          1493:                                                                                                                /* Also the explicit run bit is cleared */
        !          1494:                        mtlr    r11                                                                     /* Restore the return point */
        !          1495:                        li              r3,kMPVainInterrupt                                     /* Tell the interrupt handler to ignore the interrupt */
        !          1496:                        stw             r4,MPPICPriv(r9)                                        /* Set that flag back for later */
        !          1497:                        beqlr                                                                           /* Time to leave if we ate the 'rupt... */
        !          1498: 
        !          1499:                        li              r3,kMPSignalPending                                     /* Set that there is a SIGP interruption pending */
        !          1500:                        
        !          1501:                        blr                                                                                     /* Go away, let our caller handle this thing... QED!!!!!!!!! */
        !          1502: 
        !          1503: /* */
        !          1504: /*           QQQQQ       EEEEEEEEEE    DDDDDDDDD */
        !          1505: /*         QQQQQQQQQ     EEEEEEEEEE    DDDDDDDDDDD */
        !          1506: /*        QQQQ   QQQQ    EEEE          DDD     DDD */
        !          1507: /*       QQQQ     QQQQ   EEEEEEEEEE    DDD     DDD */
        !          1508: /*       QQQQ   Q QQQQ   EEEEEEEEEE    DDD     DDD */
        !          1509: /*        QQQQ  QQQQQ    EEEE          DDD     DDD */
        !          1510: /*         QQQQQQQQQQQ   EEEEEEEEEE    DDDDDDDDDDD */
        !          1511: /*           QQQQQ QQQ   EEEEEEEEEE    DDDDDDDDD */
        !          1512: /* */
        !          1513: /*                     (I finished here) */
        !          1514: /* */
        !          1515: 
        !          1516:                        
        !          1517: /* */
        !          1518: /*                     This is where we decode the function and do what's right. */
        !          1519: /*                     First we need to check if it's really time to do something. */
        !          1520: /* */
        !          1521: 
        !          1522: TooBusy:       and.    r5,r3,r6                                                        /* See if the passed flag is on */
        !          1523:                        beq             SpinIdle                                                        /* No, not yet, try the whole smear again... */
        !          1524:                        
        !          1525:                        beq+    cr1,KeepRupt                                            /* Don't clear 'rupt if we already did (or entered via RunSIGRun) */
        !          1526: 
        !          1527:                        lwz             r5,MPPICPriv(r9)                                        /* Get the private flags */
        !          1528:                        rlwinm. r5, r5, 0, 1, 1                                         /* Did we enter via RunSIGPRun? */
        !          1529:                        beq             SimRupt                                                         /* Nope, 's'ok, go clear physical 'rupt... */
        !          1530:                        
        !          1531: KeepRupt:
        !          1532:                        bl              GetOurBase                                                      /* Get our address */
        !          1533: GetOurBase:    rlwinm  r4,r3,26,22,29                                          /* Get the opcode index * 4 */
        !          1534:                        mflr    r12                                                                     /* Get the base address */
        !          1535:                        la              r7,LOW_ADDR(IFuncTable-GetOurBase)(r12)         /* Point to the function table */
        !          1536:                        
        !          1537:                        cmplwi  cr0,r4,7*4                                                      /* See if they sent us some bogus junk */
        !          1538:                                                                                                                /* Change 7 if we add more functions */
        !          1539:                        add             r7,r7,r4                                                        /* Point right at the entry */
        !          1540:                        bgt-    KillBusy                                                        /* Bad request code, reset busy and eat it... */
        !          1541:                        
        !          1542:                        mtlr    r7                                                                      /* Set up the LR */
        !          1543:                        
        !          1544:                        blr                                                                                     /* Go execute the function... */
        !          1545:        
        !          1546: IFuncTable:
        !          1547:                        b               KillBusy                                                        /* This handles the signal in vain... */
        !          1548:                        b               IStart                                                          /* This handles the start function */
        !          1549:                        b               IResume                                                         /* This handles the resume function */
        !          1550:                        b               IStop                                                           /* This handles the stop function */
        !          1551:                        b               ISIGP                                                           /* This handles the SIGP function */
        !          1552:                        b               IStatus                                                         /* This handles the store status function */
        !          1553:                        b               ITBsync                                                         /* This handles the synchronize timer base function */
        !          1554:                        b               IReset                                                          /* This handles the reset function */
        !          1555: 
        !          1556: /******************************************************************************************************** */
        !          1557: /******************************************************************************************************** */
        !          1558: /* */
        !          1559: /*                     Here are the functions handled at interrupt time */
        !          1560: /* */
        !          1561: /******************************************************************************************************** */
        !          1562: /******************************************************************************************************** */
        !          1563: 
        !          1564: /******************************************************************************************************** */
        !          1565: /* */
        !          1566: /*                     The Start function.  This guy requires that the processor be in the reset and online state. */
        !          1567: /* */
        !          1568: /******************************************************************************************************** */
        !          1569: 
        !          1570: IStart:                lis             r4,MPPICOnline>>16                                      /* Get bits required to be on */
        !          1571:                        isync                                                                           /* Make sure we haven't gone past here */
        !          1572:                        and             r6,r3,r4                                                        /* See if they are on */
        !          1573:                        cmplw   cr1,r6,r4                                                       /* Are they all on? */
        !          1574:                        lwz             r4,MPPICParm0(r9)                                       /* Get the physical address of the code to go to */
        !          1575:                        bne-    cr1,BadRuptState                                        /* Some required state bits are off */
        !          1576:                        rlwinm  r3,r3,0,2,31                                            /* Kill the busy bits */
        !          1577:                        rlwinm  r3,r3,0,24,15                                           /* Set the function to idle */
        !          1578:                        oris    r3,r3,MPPICReady>>16                            /* Set ready state */
        !          1579:                        rlwinm  r3,r3,0,5,3                                                     /* Clear out the stop bit */
        !          1580:                        mtlr    r4                                                                      /* Set the LR */
        !          1581:                        stw             r3,MPPICStat(r9)                                        /* Clear out the status flags */
        !          1582:                        lwz             r3,MPPICParm2(r9)                                       /* Get pass-thru parameter */
        !          1583:                        blrl                                                                            /* Start up the code... */
        !          1584: /* */
        !          1585: /*                     The rules for coming back here via BLR are just opposite the normal way:  you can trash R0-R3 and */
        !          1586: /*                     R13-R31, all the CRs; don't touch SPRG1 or SPRG3, the MSR, the SRs or BATs 0 and 1. */
        !          1587: /*                     Follow these simple rules and you allowed back; don't follow them and die. */
        !          1588: /*                     We only come back here if there is some kind of startup failure so's we can try again later */
        !          1589: /* */
        !          1590: 
        !          1591:                        lwz             r3,MPPICStat(r9)                                        /* Get back the status word */
        !          1592:                        cmplw   cr1,r4,r4                                                       /* Show that we have already taken care of the 'rupt */
        !          1593:                        rlwinm  r3,r3,0,4,2                                                     /* Reset the ready bit */
        !          1594:                        b               KillBusy                                                        /* Back into the fold... */
        !          1595: 
        !          1596: /******************************************************************************************************** */
        !          1597: /* */
        !          1598: /*                     The Resume function.  This guy requires that the processor be online and ready. */
        !          1599: /* */
        !          1600: /******************************************************************************************************** */
        !          1601: 
        !          1602: IResume:       lis             r4,(MPPICOnline+MPPICReady)>>16         /* Get states required to be set */
        !          1603:                        and             r6,r3,r4                                                        /* See if they are on */
        !          1604:                        cmplw   cr0,r6,r4                                                       /* Are they all on? */
        !          1605:                        bne-    BadRuptState                                            /* Some required off state bits are on */
        !          1606:                        rlwinm  r3,r3,0,5,3                                                     /* Clear out the stop bit */
        !          1607:                        b               KillBusy                                                        /* Get going... */
        !          1608: 
        !          1609: /******************************************************************************************************** */
        !          1610: /* */
        !          1611: /*                     The Stop function.  All we care about here is that the guy is online. */
        !          1612: /* */
        !          1613: /******************************************************************************************************** */
        !          1614: 
        !          1615: IStop:         lis             r4,MPPICOnline>>16                                      /* All we care about is if we are online or not */
        !          1616:                        and.    r6,r3,r4                                                        /* See if we are online */
        !          1617:                        beq-    BadRuptState                                            /* Some required off state bits are on */
        !          1618:                        oris    r3,r3,MPPICStop>>16                                     /* Set the stop bit */
        !          1619:                        b               KillBusy                                                        /* Get stopped... */
        !          1620: 
        !          1621: 
        !          1622: /******************************************************************************************************** */
        !          1623: /* */
        !          1624: /*                     The SIGP function.  All we care about here is that the guy is online. */
        !          1625: /* */
        !          1626: /******************************************************************************************************** */
        !          1627: 
        !          1628: ISIGP:         lis             r4,(MPPICOnline+MPPICReady)>>16         /* Get states required to be set */
        !          1629:                        and             r6,r3,r4                                                        /* See if they are on */
        !          1630:                        lwz             r7,MPPICPriv(r9)                                        /* Get the private flags */
        !          1631:                        cmplw   cr0,r6,r4                                                       /* Are they all on? */
        !          1632:                        oris    r6,r7,(MPPICSigp>>16)&0x0000FFFF        /* Set the SIGP pending bit */
        !          1633:                        bne-    BadRuptState                                            /* Some required off state bits are on */
        !          1634:                        lwz             r4,MPPICParm0(r9)                                       /* Get the SIGP parameter */
        !          1635:                        stw             r6,MPPICPriv(r9)                                        /* Stick the pending bit back */
        !          1636:                        stw             r4,MPPICParm0BU(r9)                                     /* Back up parm 0 so it is safe once we unlock */
        !          1637:                        b               KillBusy                                                        /* Get stopped... */
        !          1638: 
        !          1639: /******************************************************************************************************** */
        !          1640: /* */
        !          1641: /*                     The store status function.  This guy requires that the processor be in the stopped state. */
        !          1642: /* */
        !          1643: /******************************************************************************************************** */
        !          1644: 
        !          1645: IStatus:       lis             r4,MPPICOnline>>16                                      /* All we care about is if we are online or not */
        !          1646:                        and.    r6,r3,r4                                                        /* See if we are online */
        !          1647:                        isync                                                                           /* Make sure we havn't gone past here */
        !          1648:                        beq-    BadRuptState                                            /* Some required off state bits are on */
        !          1649:                        lwz             r4,MPPICParm0(r9)                                       /* Get the status area physical address */
        !          1650:                        rlwinm. r6,r3,0,3,3                                                     /* Test processor ready */
        !          1651:                        
        !          1652:                        beq             INotReady                                                       /* Not ready, don't assume valid exception save area */
        !          1653:                        bl              StoreStatus                                                     /* Go store off all the registers 'n' stuff */
        !          1654:                        b               KillBusy                                                        /* All done... */
        !          1655:                        
        !          1656: INotReady:
        !          1657:                        lis             r7,0xDEAD                                                       /* Get 0xDEAD + 1 */
        !          1658:                        ori             r7,r7,0xF1D0                                            /* Get 0xDEADF1D0 */
        !          1659:                        stw             r7,CSAgpr+(0*4)(r4)                                     /* Store invalid R0 */
        !          1660:                        stw             r7,CSAgpr+(1*4)(r4)                                     /* Store invalid R1 */
        !          1661:                        stw             r7,CSAgpr+(2*4)(r4)                                     /* Store invalid R2 */
        !          1662:                        stw             r7,CSAgpr+(3*4)(r4)                                     /* Store invalid R3 */
        !          1663:                        stw             r7,CSAgpr+(4*4)(r4)                                     /* Store invalid R4 */
        !          1664:                        stw             r7,CSAgpr+(5*4)(r4)                                     /* Store invalid R5 */
        !          1665:                        stw             r7,CSAgpr+(6*4)(r4)                                     /* Store invalid R6 */
        !          1666:                        stw             r7,CSAgpr+(7*4)(r4)                                     /* Store invalid R7 */
        !          1667:                        stw             r7,CSAgpr+(8*4)(r4)                                     /* Store invalid R8 */
        !          1668:                        stw             r7,CSAgpr+(9*4)(r4)                                     /* Store invalid R9 */
        !          1669:                        stw             r7,CSAgpr+(10*4)(r4)                            /* Store invalid R10 */
        !          1670:                        stw             r7,CSAgpr+(11*4)(r4)                            /* Store invalid R11 */
        !          1671:                        stw             r7,CSAgpr+(12*4)(r4)                            /* Store invalid R12 */
        !          1672:                        stw             r13,CSAgpr+(13*4)(r4)                           /* Save general registers */
        !          1673:                        stw             r14,CSAgpr+(14*4)(r4)                           /* Save general registers */
        !          1674:                        stw             r15,CSAgpr+(15*4)(r4)                           /* Save general registers */
        !          1675:                        stw             r16,CSAgpr+(16*4)(r4)                           /* Save general registers */
        !          1676:                        stw             r17,CSAgpr+(17*4)(r4)                           /* Save general registers */
        !          1677:                        stw             r18,CSAgpr+(18*4)(r4)                           /* Save general registers */
        !          1678:                        stw             r19,CSAgpr+(19*4)(r4)                           /* Save general registers */
        !          1679:                        stw             r20,CSAgpr+(20*4)(r4)                           /* Save general registers */
        !          1680:                        stw             r21,CSAgpr+(21*4)(r4)                           /* Save general registers */
        !          1681:                        stw             r22,CSAgpr+(22*4)(r4)                           /* Save general registers */
        !          1682:                        stw             r23,CSAgpr+(23*4)(r4)                           /* Save general registers */
        !          1683:                        stw             r24,CSAgpr+(24*4)(r4)                           /* Save general registers */
        !          1684:                        stw             r25,CSAgpr+(25*4)(r4)                           /* Save general registers */
        !          1685:                        stw             r26,CSAgpr+(26*4)(r4)                           /* Save general registers */
        !          1686:                        stw             r27,CSAgpr+(27*4)(r4)                           /* Save general registers */
        !          1687:                        stw             r28,CSAgpr+(28*4)(r4)                           /* Save general registers */
        !          1688:                        stw             r29,CSAgpr+(29*4)(r4)                           /* Save general registers */
        !          1689:                        stw             r30,CSAgpr+(30*4)(r4)                           /* Save general registers */
        !          1690:                        stw             r31,CSAgpr+(31*4)(r4)                           /* Save general registers */
        !          1691:                        bl              StoreLiveStatus
        !          1692:                        b               KillBusy
        !          1693: 
        !          1694: /* */
        !          1695: /*                     Save the whole status.  Lot's of busy work. */
        !          1696: /*                     Anything marked unclean is of the devil and should be shunned.  Actually, it depends upon  */
        !          1697: /*                     knowledge of firmware control areas and is no good for a plug in.  But, we've sacrificed the */
        !          1698: /*                     white ram and are standing within a circle made of his skin, so we can dance with the devil */
        !          1699: /*                     safely. */
        !          1700: /* */
        !          1701: 
        !          1702: StoreStatus:
        !          1703:                        mfspr   r10,sprg0                                                       /* Get the pointer to the exception save area (unclean) */
        !          1704:                        
        !          1705:                        lwz             r5,saver0(r13)                                          /* Get R0 (unclean) */
        !          1706:                        lwz             r6,saver1(r13)                                          /* Get R1 (unclean) */
        !          1707:                        lwz             r7,saver2(r13)                                          /* Get R2 (unclean) */
        !          1708:                        stw             r5,CSAgpr+(0*4)(r4)                                     /* Save R0 */
        !          1709:                        stw             r6,CSAgpr+(1*4)(r4)                                     /* Save R1 */
        !          1710:                        stw             r7,CSAgpr+(2*4)(r4)                                     /* Save R2 */
        !          1711:                        lwz             r5,saver3(r13)                                          /* Get R3 (unclean) */
        !          1712:                        lwz             r6,saver4(r13)                                          /* Get R4 (unclean) */
        !          1713:                        lwz             r7,saver5(r13)                                          /* Get R5 (unclean) */
        !          1714:                        stw             r5,CSAgpr+(3*4)(r4)                                     /* Save R3 */
        !          1715:                        stw             r6,CSAgpr+(4*4)(r4)                                     /* Save R4 */
        !          1716:                        stw             r7,CSAgpr+(5*4)(r4)                                     /* Save R5 */
        !          1717:                        lwz             r5,saver6(r13)                                          /* Get R6 (unclean) */
        !          1718:                        lwz             r6,saver7(r13)                                          /* Get R7 (unclean) */
        !          1719:                        lwz             r7,saver8(r13)                                          /* Get R8 (unclean) */
        !          1720:                        stw             r5,CSAgpr+(6*4)(r4)                                     /* Save R6 */
        !          1721:                        stw             r6,CSAgpr+(7*4)(r4)                                     /* Save R7 */
        !          1722:                        stw             r7,CSAgpr+(8*4)(r4)                                     /* Save R8 */
        !          1723:                        lwz             r5,saver9(r13)                                          /* Get R9 (unclean) */
        !          1724:                        lwz             r6,saver10(r13)                                         /* Get R10 (unclean) */
        !          1725:                        lwz             r7,saver11(r13)                                         /* Get R11 (unclean) */
        !          1726:                        stw             r5,CSAgpr+(9*4)(r4)                                     /* Save R9 */
        !          1727:                        stw             r6,CSAgpr+(10*4)(r4)                            /* Save R10 */
        !          1728:                        lwz             r5,saver12(r13)                                         /* Get R12 (unclean) */
        !          1729:                        stw             r7,CSAgpr+(11*4)(r4)                            /* Save R11 */
        !          1730:                        stw             r5,CSAgpr+(12*4)(r4)                            /* Save R12 */
        !          1731:                        
        !          1732:                        lwz             r5,saver13(r13)                                         /* Get R13 (unclean) */
        !          1733:                        lwz             r6,saver14(r13)                                         /* Get R14 (unclean) */
        !          1734:                        lwz             r7,saver15(r13)                                         /* Get R15 (unclean) */
        !          1735:                        stw             r5,CSAgpr+(13*4)(r4)                            /* Save R13 */
        !          1736:                        stw             r6,CSAgpr+(14*4)(r4)                            /* Save R14 */
        !          1737:                        stw             r7,CSAgpr+(15*4)(r4)                            /* Save R15 */
        !          1738:                        lwz             r5,saver16(r13)                                         /* Get R16 (unclean) */
        !          1739:                        lwz             r6,saver17(r13)                                         /* Get R17 (unclean) */
        !          1740:                        lwz             r7,saver18(r13)                                         /* Get R18 (unclean) */
        !          1741:                        stw             r5,CSAgpr+(16*4)(r4)                            /* Save R16 */
        !          1742:                        stw             r6,CSAgpr+(17*4)(r4)                            /* Save R17 */
        !          1743:                        stw             r7,CSAgpr+(18*4)(r4)                            /* Save R18 */
        !          1744:                        lwz             r5,saver19(r13)                                         /* Get R19 (unclean) */
        !          1745:                        lwz             r6,saver20(r13)                                         /* Get R20 (unclean) */
        !          1746:                        lwz             r7,saver21(r13)                                         /* Get R21 (unclean) */
        !          1747:                        stw             r5,CSAgpr+(19*4)(r4)                            /* Save R19 */
        !          1748:                        stw             r6,CSAgpr+(20*4)(r4)                            /* Save R20 */
        !          1749:                        stw             r7,CSAgpr+(21*4)(r4)                            /* Save R21 */
        !          1750:                        lwz             r5,saver22(r13)                                         /* Get R22 (unclean) */
        !          1751:                        lwz             r6,saver23(r13)                                         /* Get R23 (unclean) */
        !          1752:                        lwz             r7,saver24(r13)                                         /* Get R24 (unclean) */
        !          1753:                        stw             r5,CSAgpr+(22*4)(r4)                            /* Save R22 */
        !          1754:                        stw             r6,CSAgpr+(23*4)(r4)                            /* Save R23*/
        !          1755:                        stw             r7,CSAgpr+(24*4)(r4)                            /* Save R24 */
        !          1756:                        lwz             r5,saver25(r13)                                         /* Get R25 (unclean) */
        !          1757:                        lwz             r6,saver26(r13)                                         /* Get R26 (unclean) */
        !          1758:                        lwz             r7,saver27(r13)                                         /* Get R27 (unclean) */
        !          1759:                        stw             r5,CSAgpr+(25*4)(r4)                            /* Save R25 */
        !          1760:                        stw             r6,CSAgpr+(26*4)(r4)                            /* Save R26 */
        !          1761:                        stw             r7,CSAgpr+(27*4)(r4)                            /* Save R27 */
        !          1762: 
        !          1763:                        lwz             r5,saver28(r13)                                         /* Get R28 (unclean) */
        !          1764:                        lwz             r6,saver29(r13)                                         /* Get R29 (unclean) */
        !          1765:                        lwz             r7,saver30(r13)                                         /* Get R30 (unclean) */
        !          1766:                        stw             r5,CSAgpr+(28*4)(r4)                            /* Save R28 */
        !          1767:                        lwz             r5,saver31(r13)                                         /* Get R31(unclean) */
        !          1768:                        stw             r6,CSAgpr+(29*4)(r4)                            /* Save R29 */
        !          1769:                        stw             r7,CSAgpr+(30*4)(r4)                            /* Save R30 */
        !          1770:                        stw             r5,CSAgpr+(31*4)(r4)                            /* Save R31 */
        !          1771: 
        !          1772: StoreLiveStatus:
        !          1773:                        mfmsr   r5                                                                      /* Get the current MSR */
        !          1774:                        ori             r6,r5,0x2000                                            /* Turn on floating point instructions */
        !          1775:                        mtmsr   r6                                                                      /* Turn them on */
        !          1776:                        isync                                                                           /* Make sure they're on */
        !          1777:                        
        !          1778:                        stfd    f0,CSAfpr+(0*8)(r4)                                     /* Save floating point registers */
        !          1779:                        stfd    f1,CSAfpr+(1*8)(r4)                                     /* Save floating point registers */
        !          1780:                        stfd    f2,CSAfpr+(2*8)(r4)                                     /* Save floating point registers */
        !          1781:                        stfd    f3,CSAfpr+(3*8)(r4)                                     /* Save floating point registers */
        !          1782:                        stfd    f4,CSAfpr+(4*8)(r4)                                     /* Save floating point registers */
        !          1783:                        stfd    f5,CSAfpr+(5*8)(r4)                                     /* Save floating point registers */
        !          1784:                        stfd    f6,CSAfpr+(6*8)(r4)                                     /* Save floating point registers */
        !          1785:                        stfd    f7,CSAfpr+(7*8)(r4)                                     /* Save floating point registers */
        !          1786:                        stfd    f8,CSAfpr+(8*8)(r4)                                     /* Save floating point registers */
        !          1787:                        stfd    f9,CSAfpr+(9*8)(r4)                                     /* Save floating point registers */
        !          1788:                        stfd    f10,CSAfpr+(10*8)(r4)                           /* Save floating point registers */
        !          1789:                        stfd    f11,CSAfpr+(11*8)(r4)                           /* Save floating point registers */
        !          1790:                        stfd    f12,CSAfpr+(12*8)(r4)                           /* Save floating point registers */
        !          1791:                        stfd    f13,CSAfpr+(13*8)(r4)                           /* Save floating point registers */
        !          1792:                        stfd    f14,CSAfpr+(14*8)(r4)                           /* Save floating point registers */
        !          1793:                        stfd    f15,CSAfpr+(15*8)(r4)                           /* Save floating point registers */
        !          1794:                        stfd    f16,CSAfpr+(16*8)(r4)                           /* Save floating point registers */
        !          1795:                        stfd    f17,CSAfpr+(17*8)(r4)                           /* Save floating point registers */
        !          1796:                        stfd    f18,CSAfpr+(18*8)(r4)                           /* Save floating point registers */
        !          1797:                        stfd    f19,CSAfpr+(19*8)(r4)                           /* Save floating point registers */
        !          1798:                        stfd    f20,CSAfpr+(20*8)(r4)                           /* Save floating point registers */
        !          1799:                        stfd    f21,CSAfpr+(21*8)(r4)                           /* Save floating point registers */
        !          1800:                        stfd    f22,CSAfpr+(22*8)(r4)                           /* Save floating point registers */
        !          1801:                        stfd    f23,CSAfpr+(23*8)(r4)                           /* Save floating point registers */
        !          1802:                        stfd    f24,CSAfpr+(24*8)(r4)                           /* Save floating point registers */
        !          1803:                        stfd    f25,CSAfpr+(25*8)(r4)                           /* Save floating point registers */
        !          1804:                        stfd    f26,CSAfpr+(26*8)(r4)                           /* Save floating point registers */
        !          1805:                        stfd    f27,CSAfpr+(27*8)(r4)                           /* Save floating point registers */
        !          1806:                        stfd    f28,CSAfpr+(28*8)(r4)                           /* Save floating point registers */
        !          1807:                        stfd    f29,CSAfpr+(29*8)(r4)                           /* Save floating point registers */
        !          1808:                        stfd    f30,CSAfpr+(30*8)(r4)                           /* Save floating point registers */
        !          1809:                        stfd    f31,CSAfpr+(31*8)(r4)                           /* Save floating point registers */
        !          1810:                        
        !          1811:                        mffs    f1                                                                      /* Get the FPSCR */
        !          1812:                        stfd    f1,CSAfpscr-4(r4)                                       /* Save the whole thing (we'll overlay the first half with CR later) */
        !          1813:                        
        !          1814:                        lfd             f1,CSAfpr+(1*4)(r4)                                     /* Restore F1 */
        !          1815:                        
        !          1816:                        mtmsr   r5                                                                      /* Put the floating point back to what it was before */
        !          1817:                        isync                                                                           /* Wait for it */
        !          1818:                        
        !          1819:                        lwz             r6,savecr(r13)                                          /* Get the old CR (unclean) */
        !          1820:                        stw             r6,CSAcr(r4)                                            /* Save the CR */
        !          1821:                        
        !          1822:                        mfxer   r6                                                                      /* Get the XER */
        !          1823:                        stw             r6,CSAxer(r4)                                           /* Save the XER */
        !          1824:                        
        !          1825:                        lwz             r6,savelr(r13)                                          /* Get the old LR (unclean) */
        !          1826:                        stw             r6,CSAlr(r4)                                            /* Save the LR */
        !          1827:                        
        !          1828:                        mfctr   r6                                                                      /* Get the CTR */
        !          1829:                        stw             r6,CSActr(r4)                                           /* Save the CTR */
        !          1830:                        
        !          1831: STtbase:       mftbu   r5                                                                      /* Get the upper timebase */
        !          1832:                        mftb    r6                                                                      /* Get the lower */
        !          1833:                        mftbu   r7                                                                      /* Get the top again */
        !          1834:                        cmplw   cr0,r5,r7                                                       /* Did it tick? */
        !          1835:                        bne-    STtbase                                                         /* Yeah, do it again... */
        !          1836:                        
        !          1837:                        mfdec   r7                                                                      /* Get the decrimenter (make it at about the same time as the TB) */
        !          1838:                        stw             r7,CSAdec(r4)                                           /* Save the decrimenter */
        !          1839:                        
        !          1840:                        
        !          1841:                        stw             r5,CSAtbu(r4)                                           /* Stash the top part */
        !          1842:                        stw             r6,CSAtbl(r4)                                           /* Stash the lower part */
        !          1843:                        
        !          1844:                        lwz             r5,savesrr1(r13)                                        /* SRR1 at exception is as close as we get to the MSR (unclean) */
        !          1845:                        lwz             r6,savesrr0(r13)                                        /* Get SRR0 also */
        !          1846:                        stw             r5,CSAmsr(r4)                                           /* Save the MSR */
        !          1847:                        stw             r6,CSApc(r4)                                            /* Save the PC */
        !          1848:                        stw             r5,CSAsrr1(r4)                                          /* Set SRR1 also */
        !          1849:                        stw             r6,CSAsrr0(r4)                                          /* Save SRR0 */
        !          1850:                        
        !          1851:                        mfpvr   r5                                                                      /* Get the PVR */
        !          1852:                        stw             r5,CSApvr(r4)                                           /* Save the PVR */
        !          1853:                        
        !          1854:                        mfspr   r5,pir                                                          /* Get the PIR */
        !          1855:                        stw             r5,CSApir(r4)                                           /* Save the PIR */
        !          1856:                        
        !          1857:                        mfspr   r5,ibat0u                                                       /* Get the upper IBAT0 */
        !          1858:                        mfspr   r6,ibat0l                                                       /* Get the lower IBAT0 */
        !          1859:                        stw             r5,CSAibat+(0*8+0)(r4)                          /* Save the upper IBAT0 */
        !          1860:                        stw             r6,CSAibat+(0*8+4)(r4)                          /* Save the upper IBAT0 */
        !          1861: 
        !          1862:                        mfspr   r5,ibat1u                                                       /* Get the upper IBAT1 */
        !          1863:                        mfspr   r6,ibat1l                                                       /* Get the lower IBAT1 */
        !          1864:                        stw             r5,CSAibat+(1*8+0)(r4)                          /* Save the upper IBAT1 */
        !          1865:                        stw             r6,CSAibat+(1*8+4)(r4)                          /* Save the upper IBAT1 */
        !          1866: 
        !          1867:                        mfspr   r5,ibat2u                                                       /* Get the upper IBAT2 */
        !          1868:                        mfspr   r6,ibat2l                                                       /* Get the lower IBAT2 */
        !          1869:                        stw             r5,CSAibat+(2*8+0)(r4)                          /* Save the upper IBAT2 */
        !          1870:                        stw             r6,CSAibat+(2*8+4)(r4)                          /* Save the upper IBAT2 */
        !          1871: 
        !          1872:                        mfspr   r5,ibat3u                                                       /* Get the upper IBAT3 */
        !          1873:                        mfspr   r6,ibat3l                                                       /* Get the lower IBAT3 */
        !          1874:                        stw             r5,CSAibat+(3*8+0)(r4)                          /* Save the upper IBAT3 */
        !          1875:                        stw             r6,CSAibat+(3*8+4)(r4)                          /* Save the upper IBAT3 */
        !          1876: 
        !          1877:                        mfspr   r5,dbat0u                                                       /* Get the upper DBAT0 */
        !          1878:                        mfspr   r6,dbat0l                                                       /* Get the lower DBAT0 */
        !          1879:                        stw             r5,CSAdbat+(0*8+0)(r4)                          /* Save the upper DBAT0 */
        !          1880:                        stw             r6,CSAdbat+(0*8+4)(r4)                          /* Save the upper DBAT0 */
        !          1881: 
        !          1882:                        mfspr   r5,dbat1u                                                       /* Get the upper DBAT1 */
        !          1883:                        mfspr   r6,dbat1l                                                       /* Get the lower DBAT1 */
        !          1884:                        stw             r5,CSAdbat+(1*8+0)(r4)                          /* Save the upper DBAT1 */
        !          1885:                        stw             r6,CSAdbat+(1*8+4)(r4)                          /* Save the upper DBAT1 */
        !          1886: 
        !          1887:                        mfspr   r5,dbat2u                                                       /* Get the upper DBAT2 */
        !          1888:                        mfspr   r6,dbat2l                                                       /* Get the lower DBAT2 */
        !          1889:                        stw             r5,CSAdbat+(2*8+0)(r4)                          /* Save the upper DBAT2 */
        !          1890:                        stw             r6,CSAdbat+(2*8+4)(r4)                          /* Save the upper DBAT2 */
        !          1891: 
        !          1892:                        mfspr   r5,dbat3u                                                       /* Get the upper DBAT3 */
        !          1893:                        mfspr   r6,dbat3l                                                       /* Get the lower DBAT3 */
        !          1894:                        stw             r5,CSAdbat+(3*8+0)(r4)                          /* Save the upper DBAT3 */
        !          1895:                        stw             r6,CSAdbat+(3*8+4)(r4)                          /* Save the upper DBAT3 */
        !          1896:                        
        !          1897:                        mfsdr1  r5                                                                      /* Get the SDR1 */
        !          1898:                        stw             r5,CSAsdr1(r4)                                          /* Save the SDR1 */
        !          1899:                        
        !          1900:                        mfsr    r5,sr0                                                          /* Get SR 0 */
        !          1901:                        mfsr    r6,sr1                                                          /* Get SR 1 */
        !          1902:                        mfsr    r7,sr2                                                          /* Get SR 2 */
        !          1903:                        stw             r5,CSAsr+(0*4)(r4)                                      /* Save SR 0 */
        !          1904:                        stw             r6,CSAsr+(1*4)(r4)                                      /* Save SR 1 */
        !          1905:                        mfsr    r5,sr3                                                          /* Get SR 3 */
        !          1906:                        mfsr    r6,sr4                                                          /* Get SR 4 */
        !          1907:                        stw             r7,CSAsr+(2*4)(r4)                                      /* Save SR 2 */
        !          1908:                        mfsr    r7,sr5                                                          /* Get SR 5 */
        !          1909:                        stw             r5,CSAsr+(3*4)(r4)                                      /* Save SR 3 */
        !          1910:                        stw             r6,CSAsr+(4*4)(r4)                                      /* Save SR 4 */
        !          1911:                        mfsr    r5,sr6                                                          /* Get SR 6 */
        !          1912:                        mfsr    r6,sr7                                                          /* Get SR 7 */
        !          1913:                        stw             r7,CSAsr+(5*4)(r4)                                      /* Save SR 5 */
        !          1914:                        mfsr    r7,sr8                                                          /* Get SR 8 */
        !          1915:                        stw             r5,CSAsr+(6*4)(r4)                                      /* Save SR 6 */
        !          1916:                        stw             r6,CSAsr+(7*4)(r4)                                      /* Save SR 7 */
        !          1917:                        mfsr    r5,sr9                                                          /* Get SR 9 */
        !          1918:                        mfsr    r6,sr10                                                         /* Get SR 11 */
        !          1919:                        stw             r7,CSAsr+(8*4)(r4)                                      /* Save SR 8 */
        !          1920:                        mfsr    r7,sr11                                                         /* Get SR 11 */
        !          1921:                        stw             r5,CSAsr+(9*4)(r4)                                      /* Save SR 9 */
        !          1922:                        stw             r6,CSAsr+(10*4)(r4)                                     /* Save SR 10 */
        !          1923:                        mfsr    r5,sr12                                                         /* Get SR 12 */
        !          1924:                        mfsr    r6,sr13                                                         /* Get SR 13 */
        !          1925:                        stw             r7,CSAsr+(11*4)(r4)                                     /* Save SR 11 */
        !          1926:                        mfsr    r7,sr14                                                         /* Get SR 14 */
        !          1927:                        stw             r5,CSAsr+(12*4)(r4)                                     /* Save SR 12 */
        !          1928:                        stw             r6,CSAsr+(13*4)(r4)                                     /* Save SR 13 */
        !          1929:                        mfsr    r5,sr15                                                         /* Get SR 15 */
        !          1930:                        stw             r7,CSAsr+(14*4)(r4)                                     /* Save SR 14 */
        !          1931:                        stw             r5,CSAsr+(15*4)(r4)                                     /* Save SR 15 */
        !          1932:                        
        !          1933:                        mfdar   r6                                                                      /* Get the DAR */
        !          1934:                        stw             r6,CSAdar(r4)                                           /* Save it */
        !          1935:                        
        !          1936:                        mfdsisr r5                                                                      /* Get the DSISR */
        !          1937:                        stw             r5,CSAdsisr(r4)                                         /* Save it */
        !          1938:                        
        !          1939:                        stw             r10,CSAsprg+(1*4)(r4)                           /* Save SPRG1 */
        !          1940:                        mfspr   r7,sprg0                                                        /* Get SPRG0 */
        !          1941:                        mfspr   r6,sprg2                                                        /* Get SPRG2 */
        !          1942:                        stw             r7,CSAsprg+(0*4)(r4)                            /* Save SPRG0 */
        !          1943:                        mfspr   r5,sprg3                                                        /* Get SPRG3 */
        !          1944:                        stw             r6,CSAsprg+(2*4)(r4)                            /* Save SPRG2 */
        !          1945:                        stw             r5,CSAsprg+(3*4)(r4)                            /* Save SPRG4 */
        !          1946:                        
        !          1947:                        mfspr   r6,1013                                                         /* Get the DABR */
        !          1948:                        mfspr   r7,1010                                                         /* Get the IABR */
        !          1949:                        stw             r6,CSAdabr(r4)                                          /* Save the DABR */
        !          1950:                        stw             r7,CSAiabr(r4)                                          /* Save the IABR */
        !          1951:                        
        !          1952:                        mfspr   r5,282                                                          /* Get the EAR */
        !          1953:                        stw             r5,CSAear(r4)                                           /* Save the EAR */
        !          1954:                        
        !          1955:                        lis             r7,0xDEAD                                                       /* Get 0xDEAD */
        !          1956:                        ori             r7,r7,0xF1D0                                            /* Get 0xDEADF1D0 */
        !          1957:                        
        !          1958:                        mfpvr   r5                                                                      /* Get the processor type */
        !          1959:                        rlwinm  r5,r5,16,16,31                                          /* Isolate the processor */
        !          1960:                        cmplwi  cr1,r5,4                                                        /* Set CR1_EQ if this is a plain 604, something else if it's a 604E */
        !          1961:                        
        !          1962:                        mfspr   r6,hid0                                                         /* Get HID0 */
        !          1963:                        mr              r5,r7                                                           /* Assume 604 */
        !          1964:                        beq             cr1,NoHID1                                                      /* It is... */
        !          1965:                        mfspr   r5,hid1                                                         /* Get the HID1 */
        !          1966: 
        !          1967: NoHID1:                stw             r6,CSAhid+(0*4)(r4)                                     /* Save HID0 */
        !          1968:                        stw             r5,CSAhid+(1*4)(r4)                                     /* Save HID1 */
        !          1969:                        stw             r7,CSAhid+(2*4)(r4)                                     /* Save HID2 */
        !          1970:                        stw             r7,CSAhid+(3*4)(r4)                                     /* Save HID3 */
        !          1971:                        stw             r7,CSAhid+(4*4)(r4)                                     /* Save HID4 */
        !          1972:                        stw             r7,CSAhid+(5*4)(r4)                                     /* Save HID5 */
        !          1973:                        stw             r7,CSAhid+(6*4)(r4)                                     /* Save HID6 */
        !          1974:                        stw             r7,CSAhid+(7*4)(r4)                                     /* Save HID7 */
        !          1975:                        stw             r7,CSAhid+(8*4)(r4)                                     /* Save HID8 */
        !          1976:                        stw             r7,CSAhid+(9*4)(r4)                                     /* Save HID9 */
        !          1977:                        stw             r7,CSAhid+(10*4)(r4)                            /* Save HID10 */
        !          1978:                        stw             r7,CSAhid+(11*4)(r4)                            /* Save HID11 */
        !          1979:                        stw             r7,CSAhid+(12*4)(r4)                            /* Save HID12 */
        !          1980:                        stw             r7,CSAhid+(13*4)(r4)                            /* Save HID13 */
        !          1981:                        stw             r7,CSAhid+(14*4)(r4)                            /* Save HID14 */
        !          1982:                        stw             r7,CSAhid+(15*4)(r4)                            /* Save HID15 */
        !          1983:                        
        !          1984:                        mfspr   r6,952                                                          /* Get MMCR0 */
        !          1985:                        mr              r5,r7                                                           /* Assume 604 */
        !          1986:                        beq             NoMMCR1                                                         /* It is... */
        !          1987:                        mfspr   r5,956                                                          /* Get the MMCR1 */
        !          1988: 
        !          1989: NoMMCR1:       stw             r6,CSAmmcr+(0*4)(r4)                            /* Save MMCR0 */
        !          1990:                        stw             r5,CSAmmcr+(1*4)(r4)                            /* Save MMCR1 */
        !          1991:                        
        !          1992:                        mfspr   r6,953                                                          /* Get PMC1 */
        !          1993:                        mfspr   r5,954                                                          /* Get PMC2 */
        !          1994:                        stw             r6,CSApmc+(0*4)(r4)                                     /* Save PMC1 */
        !          1995:                        stw             r5,CSApmc+(1*4)(r4)                                     /* Save PMC2 */
        !          1996:                        
        !          1997:                        mr              r6,r7                                                           /* Assume 604 */
        !          1998:                        mr              r5,r7                                                           /* Assume 604 */
        !          1999:                        beq             NoPMC3                                                          /* Yeah... */
        !          2000:                        mfspr   r6,957                                                          /* Get the PMC3 for a 604E */
        !          2001:                        mfspr   r5,958                                                          /* Get the PMC4 for a 604E */
        !          2002:                        
        !          2003: NoPMC3:                stw             r6,CSApmc+(2*4)(r4)                                     /* Save PMC3 */
        !          2004:                        stw             r5,CSApmc+(3*4)(r4)                                     /* Save PMC4 */
        !          2005: 
        !          2006:                        mfspr   r6,955                                                          /* Get SIA */
        !          2007:                        mfspr   r5,959                                                          /* Get SDA */
        !          2008:                        stw             r6,CSAsia(r4)                                           /* Save the SIA */
        !          2009:                        stw             r5,CSAsda(r4)                                           /* Save the SDA */
        !          2010:                        
        !          2011:                        stw             r7,CSAmq(r4)                                            /* There is no MQ on either the 604 or 604E */
        !          2012:                        
        !          2013:                        
        !          2014:                        lwz             r6,MPPICStat(r9)                                        /* Get the status of this processor */
        !          2015:                        lis             r10,MPPICReady>>16                                      /* Get the flag for reset or not */
        !          2016:                        li              r5,kSIGPResetState                                      /* Assume we're operating */
        !          2017:                        and.    r0,r6,r10                                                       /* See if the ready bit is set */
        !          2018:                        lis             r10,MPPICStop>>16                                       /* Get the flag for stopped or not */
        !          2019:                        beq             SetStateInf                                                     /* Go set that we are reset... */
        !          2020:                        and.    r0,r6,r10                                                       /* Are we stopped? */
        !          2021:                        li              r5,kSIGPStoppedState                            /* Assume we area */
        !          2022:                        bne             SetStateInf                                                     /* We are, go set it... */
        !          2023:                        li              r5,kSIGPOperatingState                          /* Not stopped, so we're going */
        !          2024:                        
        !          2025: SetStateInf: stb               r5,CSAstate(r4)                                 /* Set the state byte */
        !          2026:                        
        !          2027:                        li              r0,1                                                            /* Set the truth */
        !          2028:                        sync                                                                            /* Make sure it's stored */
        !          2029:                        
        !          2030:                        stb             r0,CSAregsAreValid(r4)                          /* Set that the status is valid */
        !          2031: 
        !          2032:                        blr                                                                                     /* We're done here... */
        !          2033:                        
        !          2034: 
        !          2035: /******************************************************************************************************** */
        !          2036: /* */
        !          2037: /*                     The synchronize time base function.  No state requirements for this one. */
        !          2038: /* */
        !          2039: /******************************************************************************************************** */
        !          2040: 
        !          2041: ITBsync:                                                                                               /* This handles the synchronize time base function */
        !          2042:                        lis             r12,HIGH_ADDR(MPPIwork)                         /* Get the top of work area */
        !          2043:                        li              r0,MPPICfTBsy1                                          /* Get the flag for TB sync state 1 */
        !          2044:                        li              r7,0                                                            /* Get a 0 */
        !          2045:                        ori             r12,r12,LOW_ADDR(MPPIwork)                      /* Get low part of work area */
        !          2046:                        mttbl   r7                                                                      /* Clear the bottom of the TB so's there's noupper ticks */
        !          2047:                        mttbu   r7                                                                      /* Clear the top part, just 'cause I wanna */
        !          2048:                        
        !          2049:                        sync                                                                            /* Make sure all is saved */
        !          2050:                        stb             r0,MPPICStat+2(r9)                                      /* Tell the main dude to tell us the time */
        !          2051:                        isync                                                                           /* Make sure we don't go nowhere's */
        !          2052: 
        !          2053: /* */
        !          2054: /*                     Remember that the sync'ing processor insures that the TB won't tick the high part for at least */
        !          2055: /*                     16k ticks.  That should be way longer than we need for the whole process here */
        !          2056: /* */
        !          2057: 
        !          2058: WaitTBLower: lwz       r5,MPPITBsync+4-MPPIwork(r12)           /* Get the lower part of the TB */
        !          2059:                        mttbl   r5                                                                      /* Put it in just in case it's set now */
        !          2060:                        mr.             r5,r5                                                           /* Was it actually? */
        !          2061:                        beq+    WaitTBLower                                                     /* Nope, go check again... */
        !          2062:                        lwz             r4,MPPITBsync-MPPIwork(r12)                     /* Get the high order part */
        !          2063:                        mttbu   r4                                                                      /* Set the top half also */
        !          2064: 
        !          2065:                        stw             r7,MPPITBsync+4-MPPIwork(r12)           /* Tell 'em we've got it */
        !          2066:                        
        !          2067:                        sync
        !          2068:                        
        !          2069:                        li              r4,0                                                            /* Clear this */
        !          2070:                        la              r5,MPPISncFght-32-MPPIwork(r12)         /* Point to the squared circle (our corner) */
        !          2071: 
        !          2072:                        b               TB1stPnch                                                       /* Go take the first punch... */
        !          2073: 
        !          2074: TBSargue:      
        !          2075:                        dcbf    0,r5                                                            /* *** Fix cache coherency (data integrity) HW bug *** */
        !          2076:                        sync                                                                            /* *** Fix cache coherency (data integrity) HW bug *** */
        !          2077:                        lwz             r6,0(r5)                                                        /* Listen for the procecution's argument */
        !          2078:                        mr.             r6,r6                                                           /* See if they are done */
        !          2079:                        beq+    TBSargue                                                        /* Nope, still going... */
        !          2080:                        
        !          2081: TB1stPnch:     mftb    r7                                                                      /* They're done, time for rebuttal */
        !          2082:                        stw             r7,32(r5)                                                       /* Make rebuttle */
        !          2083:        
        !          2084:                        addi    r4,r4,1                                                         /* Count rounds */
        !          2085: 
        !          2086:                        cmplwi  cr0,r4,10                                                       /* See if we've gone 9 more rounds */
        !          2087:                        addi    r5,r5,64                                                        /* Point to the next round areas */
        !          2088:                
        !          2089:                        blt+    TBSargue                                                        /* Not yet, come out of your corners fighting... */
        !          2090:                        
        !          2091: /* */
        !          2092: /*                     We'll set the latest-up-to-datest from the other processor now */
        !          2093: /* */
        !          2094: TBSetTB:               
        !          2095:                        dcbf    0,r5                                                            /* *** Fix cache coherency (data integrity) HW bug *** */
        !          2096:                        sync                                                                            /* *** Fix cache coherency (data integrity) HW bug *** */
        !          2097:                        lwz             r6,0(r5)                                                        /* Listen for the procecution's argument */
        !          2098:                        mttbl   r6                                                                      /* Set it just in case it's ok */
        !          2099:                        mr.             r6,r6                                                           /* See if they are done */
        !          2100:                        beq+    TBSetTB                                                         /* Nope, still going... */
        !          2101: 
        !          2102: /* */
        !          2103: /*                     Get average duration for each processor.  We skip the first pass on the asumption */
        !          2104: /*                     that the caches were not warmed up and it would take longer.  In proctice this */
        !          2105: /*                     is what was seen. */
        !          2106: /* */
        !          2107: 
        !          2108:                        mr              r0,r11                                                          /* Move return address to a safe register */
        !          2109: 
        !          2110:                        li              r4,0                                                            /* Clear a counter */
        !          2111:                        li              r3,0                                                            /* Clear accumulator for duration */
        !          2112:                        li              r10,0                                                           /* Clear start time accumulator top half */
        !          2113:                        li              r11,0                                                           /* Clear start time accumulator bottom half */
        !          2114:                        li              r1,0                                                            /* Clear start time accumulator top half */
        !          2115:                        li              r2,0                                                            /* Clear start time accumulator bottom half */
        !          2116:                        li              r10,0                                                           /* Clear accumulator for durations */
        !          2117:                        la              r5,MPPISncFght+64-MPPIwork(r12)         /* Get second round start time address */
        !          2118:                
        !          2119: TBSaccumU:     lwz             r6,0(r5)                                                        /* Get start time */
        !          2120:                        lwz             r11,32(r5)                                                      /* Get the other processor's start time */
        !          2121:                        lwz             r7,64(r5)                                                       /* Get end time */
        !          2122:                        lwz             r8,96(r5)                                                       /* Other proc's end time */
        !          2123:                        sub             r7,r7,r6                                                        /* Get duration */
        !          2124:                        sub             r8,r8,r11                                                       /* Get other side's duration */
        !          2125:                        addi    r4,r4,1                                                         /* Count arguments */
        !          2126:                        add             r3,r3,r7                                                        /* Accumulate durations */
        !          2127:                        add             r2,r2,r7                                                        /* Accumulate other side's durations */
        !          2128:                        cmplwi  cr0,r4,8                                                        /* Have we gotten them all yet? */
        !          2129:                        addi    r5,r5,64                                                        /* Step to the next argument */
        !          2130:                        blt+    TBSaccumU                                                       /* We're not done yet... */
        !          2131: 
        !          2132:                        add             r7,r2,r3                                                        /* Sum the two differences */
        !          2133:                        addi    r7,r7,0x10                                                      /* Round up */
        !          2134:                        rlwinm  r7,r7,27,5,31                                           /* Get the average difference divided in half */
        !          2135: 
        !          2136:                        mftb    r8                                                                      /* Get the time now */
        !          2137:                        add             r8,r8,r7                                                        /* Slide the window */
        !          2138:                        mttbl   r8                                                                      /* Set the time */
        !          2139:                        
        !          2140:                        stw             r12,MPPITBsync+4-MPPIwork(r12)          /* Show that we are done */
        !          2141:                        
        !          2142:                        lwz             r3,MPPICStat(r9)                                        /* Get back our status */
        !          2143:                        mr              r11,r0                                                          /* Restore the return register */
        !          2144:                        b               KillBusy                                                        /* We're all done now, done for it, c'est la vie... */
        !          2145:                        
        !          2146: 
        !          2147: /******************************************************************************************************** */
        !          2148: /* */
        !          2149: /*                     The reset function.  No state requirements for this one. */
        !          2150: /*                     This suicides the processor. Our caller is never returned to (good english).  The only way out of  */
        !          2151: /*                     this is a start function subsequently.  So, we give a flying f**k about the registers 'n' sutff. */
        !          2152: /* */
        !          2153: /******************************************************************************************************** */
        !          2154: 
        !          2155: IReset:                lis             r28,0x8000                                                      /* Turn on machine checks */
        !          2156:                        
        !          2157:                        ori             r28,r28,0xCC84                                          /* Enable caches, clear them,  */
        !          2158:                                                                                                                /* disable serial execution and turn BHT on */
        !          2159:                        sync
        !          2160:                        mtspr   HID0,r28                                                        /* Start the cache clear */
        !          2161:                        sync
        !          2162: 
        !          2163: /* */
        !          2164: /*                     Clear out the TLB.  They be garbage after hard reset. */
        !          2165: /* */
        !          2166: 
        !          2167:                        li              r0,512                                                          /* Get number of TLB entries (FIX THIS) */
        !          2168:                        li              r3,0                                                            /* Start at 0 */
        !          2169:                        mtctr   r0                                                                      /* Set the CTR */
        !          2170:                        
        !          2171: IRpurgeTLB:    tlbie   r3                                                                      /* Purge this entry */
        !          2172:                        addi    r3,r3,4096                                                      /* Next page */
        !          2173:                        bdnz    IRpurgeTLB                                                      /* Do 'em all... */
        !          2174:                        
        !          2175:                        sync                                                                            /* Make sure all TLB purges are done */
        !          2176:                        tlbsync                                                                         /* Make sure on other processors also */
        !          2177:                        sync                                                                            /* Make sure the TLBSYNC is done */
        !          2178: 
        !          2179: /* */
        !          2180: /*                     Clear out the BATs. */
        !          2181: /* */
        !          2182: 
        !          2183:                        li              r3,0                                                            /* Clear a register */
        !          2184:                        
        !          2185:                        mtspr   DBAT0L,r3                                                       /* Clear BAT */
        !          2186:                        mtspr   DBAT0U,r3                                                       /* Clear BAT */
        !          2187:                        mtspr   DBAT1L,r3                                                       /* Clear BAT */
        !          2188:                        mtspr   DBAT1U,r3                                                       /* Clear BAT */
        !          2189:                        mtspr   DBAT2L,r3                                                       /* Clear BAT */
        !          2190:                        mtspr   DBAT2U,r3                                                       /* Clear BAT */
        !          2191:                        mtspr   DBAT3L,r3                                                       /* Clear BAT */
        !          2192:                        mtspr   DBAT3U,r3                                                       /* Clear BAT */
        !          2193:                        
        !          2194:                        mtspr   IBAT0L,r3                                                       /* Clear BAT */
        !          2195:                        mtspr   IBAT0U,r3                                                       /* Clear BAT */
        !          2196:                        mtspr   IBAT1L,r3                                                       /* Clear BAT */
        !          2197:                        mtspr   IBAT1U,r3                                                       /* Clear BAT */
        !          2198:                        mtspr   IBAT2L,r3                                                       /* Clear BAT */
        !          2199:                        mtspr   IBAT2U,r3                                                       /* Clear BAT */
        !          2200:                        mtspr   IBAT3L,r3                                                       /* Clear BAT */
        !          2201:                        mtspr   IBAT3U,r3                                                       /* Clear BAT */
        !          2202: 
        !          2203: /* */
        !          2204: /*                     Map 0xF0000000 to 0xFFFFFFFF for I/O; make it R/W non-cacheable */
        !          2205: /*                     Map     0x00000000 to 0x0FFFFFFF for mainstore; make it R/W cachable */
        !          2206: /* */
        !          2207: 
        !          2208:                        lis             r6,0xF000                                                       /* Set RPN to last segment */
        !          2209:                        ori             r6,r6,0x1FFF                                            /* Set up upper BAT for 256M, access both */
        !          2210:                        
        !          2211:                        lis             r7,0xF000                                                       /* Set RPN to last segment */
        !          2212:                        ori             r7,r7,0x0032                                            /* Set up lower BAT for 256M, access both, non-cachable */
        !          2213:                
        !          2214:                        mtspr   DBAT0L,r7                                                       /* Setup ROM and I/O mapped areas */
        !          2215:                        mtspr   DBAT0U,r6                                                       /* Now do the upper DBAT */
        !          2216:                        sync
        !          2217:        
        !          2218:                        li              r6,0x1FFF                                                       /* Set up upper BAT for 256M, access both */
        !          2219:                        li              r7,0x0012                                                       /* Set up lower BAT for r/w access */
        !          2220:                        
        !          2221:                        mtspr   DBAT1L,r7                                                       /* Set up an initial view of mainstore */
        !          2222:                        mtspr   DBAT1U,r6                                                       /* Now do the upper DBAT */
        !          2223:                        sync
        !          2224: 
        !          2225: /* */
        !          2226: /*                     Clean up SDR and segment registers */
        !          2227: /* */
        !          2228: 
        !          2229:                        li              r3,0                                                            /* Clear a register */
        !          2230:                        mtspr   SDR1,r3                                                         /* Clear SDR1 */
        !          2231:                        
        !          2232:                        li              r4,0                                                            /* Clear index for segment registers */
        !          2233:                        lis             r5,0x1000                                                       /* Set the segment indexer */
        !          2234:                        
        !          2235: IRclearSR:     mtsrin  r3,r4                                                           /* Zero out the SR */
        !          2236:                        add.    r4,r4,r5                                                        /* Point to the next segment */
        !          2237:                        bne-    IRclearSR                                                       /* Keep going until we wrap back to 0 */
        !          2238:                        
        !          2239:                        lis             r3,(MPPICOnline+MPPICStop)>>16          /* Set the reset/online state flags */
        !          2240:                        b               KillBusy                                                        /* Go wipe out the busy flags... */
        !          2241: 
        !          2242: /*     (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG)  */
        !          2243: /* */
        !          2244: /*                     Here lies the Phoney Firmware used to test SIGPs.  Take this out later. */
        !          2245: /* */
        !          2246: /*     (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG)  */
        !          2247: 
        !          2248: mp_PhoneyFirmware:
        !          2249: 
        !          2250:                        li              r27,0x3040                                                      /* Set floating point and machine checks on, IP to 0xFFF0xxxx */
        !          2251:                        mtmsr   r27                                                                     /* Load 'em on in */
        !          2252:                        isync
        !          2253:                        
        !          2254:                        bl              PhoneyBase                                                      /* Make a base register */
        !          2255: PhoneyBase:    mflr    r26                                                                     /* Get it */
        !          2256:                        addi    r26,r26,LOW_ADDR(MPPIbase-PhoneyBase)   /* Adjust it back */
        !          2257: 
        !          2258:                        la              r20,LOW_ADDR(rupttab-MPPIbase)(r26)             /* Get the address of the interrupt table */
        !          2259:                        la              r21,LOW_ADDR(rupttabend-MPPIbase)(r26)  /* Get the end of the table */
        !          2260:                        
        !          2261: relocate:      lwz             r22,0(r20)                                                      /* Get the displacement to routine */
        !          2262:                        add             r22,r22,r12                                                     /* Relocate to the physical address */
        !          2263:                        stw             r22,0(r20)                                                      /* Stick it back */
        !          2264:                        addi    r20,r20,4                                                       /* Point to the next one */
        !          2265:                        cmplw   cr0,r20,r21                                                     /* Still in table? */
        !          2266:                        ble+    cr0,relocate                                            /* Yeah... */
        !          2267:                        
        !          2268:                        la              r20,LOW_ADDR(rupttab-MPPIbase)(r26)     /* Get the interrupt table back again */
        !          2269:                        mtsprg  3,r20                                                           /* Activate the phoney Rupt table */
        !          2270:                        
        !          2271:                        lis             r24,hi16(HammerHead)                            /* Get the actual hammerhead address */
        !          2272:                        ori             r24,r24,0x0032                                          /* Make R/W non-cachable */
        !          2273:                        lwz             r23,MPPIHammer-MPPIwork(r12)            /* Get the address mapped on the main processor */
        !          2274:                        ori             r23,r23,0x0003                                          /* Set both super and user valid for 128KB */
        !          2275:                        
        !          2276:                        mtspr   DBAT0L,r24                                                      /* Setup hammerhead's real address */
        !          2277:                        mtspr   DBAT0U,r23                                                      /* Map hammerhead to the same virtual address as on the main processor */
        !          2278:                        sync                                                                            /* Make sure it is done */
        !          2279: 
        !          2280:                        la              r25,MPPICPU2-MPPIwork(r12)                      /* Point to a phoney register save area */
        !          2281:                        mtsprg  1,r25                                                           /* Phoney up initialized processor state */
        !          2282: 
        !          2283:                        lis             r24,0xFEED                                                      /* Get 0xFEED */
        !          2284:                        ori             r24,r24,0xF1D0                                          /* Get 0xFEEDF1D0 */
        !          2285:                        
        !          2286:                        stw             r24,CSAgpr+(0*4)(r25)                           /* Store invalid R0 */
        !          2287:                        stw             r24,CSAgpr+(1*4)(r25)                           /* Store invalid R1 */
        !          2288:                        stw             r24,CSAgpr+(2*4)(r25)                           /* Store invalid R2 */
        !          2289:                        stw             r24,CSAgpr+(3*4)(r25)                           /* Store invalid R3 */
        !          2290:                        stw             r24,CSAgpr+(4*4)(r25)                           /* Store invalid r4 */
        !          2291:                        stw             r24,CSAgpr+(5*4)(r25)                           /* Store invalid R5 */
        !          2292:                        stw             r24,CSAgpr+(6*4)(r25)                           /* Store invalid R6 */
        !          2293:                        stw             r24,CSAgpr+(7*4)(r25)                           /* Store invalid r7 */
        !          2294:                        stw             r24,CSAgpr+(8*4)(r25)                           /* Store invalid R8 */
        !          2295:                        stw             r24,CSAgpr+(9*4)(r25)                           /* Store invalid R9 */
        !          2296:                        stw             r24,CSAgpr+(10*4)(r25)                          /* Store invalid R10 */
        !          2297:                        stw             r24,CSAgpr+(11*4)(r25)                          /* Store invalid R11 */
        !          2298:                        stw             r24,CSAgpr+(12*4)(r25)                          /* Store invalid R12 */
        !          2299:                        
        !          2300: waititout:     lwz             r25,0x30(br0)                                           /* Get wait count */
        !          2301:                        mfmsr   r24                                                                     /* Get the MSR */
        !          2302:                        addi    r25,r25,1                                                       /* Bounce it up */
        !          2303:                        ori             r24,r24,0x8000                                          /* Turn on external interruptions */
        !          2304:                        stw             r25,0x30(br0)                                           /* Save back the count */
        !          2305:                        mtmsr   r24                                                                     /* Set it */
        !          2306:                        isync                                                                           /* Stop until we're here */
        !          2307:                        b               waititout                                                       /* Loop forever... */
        !          2308:                        
        !          2309: /* */
        !          2310: /*                     Phoney interrupt handlers */
        !          2311: /* */
        !          2312: 
        !          2313: pexternal:     mflr    r29                                                                     /* Get the LR value */
        !          2314:                        lwz             r29,0(r29)                                                      /* Get the rupt code */
        !          2315:                        stw             r29,0x0B0(br0)                                          /* Save the code */
        !          2316:                        bl              GotSignal                                                       /* Call the signal handler */
        !          2317:                        oris    r3,r3,0x8000                                            /* Turn on high bit so we see a code 0 */
        !          2318:                        stw             r3,0xA8(br0)                                            /* Save return code in debug area */
        !          2319:                        
        !          2320: ignorerupt:    mflr    r29                                                                     /* Get the LR value */
        !          2321:                        lwz             r29,0(r29)                                                      /* Get the rupt code */
        !          2322:                        stw             r29,0x0B0(br0)                                          /* Save the code */
        !          2323:                        rfi                                                                                     /* Bail to from whence we commest... */
        !          2324:                        .long   0                       
        !          2325:                        .long   0                       
        !          2326:                        .long   0                       
        !          2327:                        .long   0                       
        !          2328:                        .long   0                       
        !          2329:                        .long   0                       
        !          2330:                        .long   0                       
        !          2331: 
        !          2332: rupttab:       .long   ignorerupt
        !          2333:                        .long   ignorerupt
        !          2334:                        .long   ignorerupt
        !          2335:                        .long   ignorerupt
        !          2336:                        .long   ignorerupt
        !          2337:                        .long   pexternal                                                       /* Phoney external handler */
        !          2338:                        .long   ignorerupt
        !          2339:                        .long   ignorerupt
        !          2340:                        .long   ignorerupt
        !          2341:                        .long   ignorerupt
        !          2342:                        .long   ignorerupt
        !          2343:                        .long   ignorerupt
        !          2344:                        .long   ignorerupt
        !          2345:                        .long   ignorerupt
        !          2346:                        .long   ignorerupt
        !          2347:                        .long   ignorerupt
        !          2348:                        .long   ignorerupt
        !          2349:                        .long   ignorerupt
        !          2350:                        .long   ignorerupt
        !          2351:                        .long   ignorerupt
        !          2352:                        .long   ignorerupt
        !          2353:                        .long   ignorerupt
        !          2354:                        .long   ignorerupt
        !          2355:                        .long   ignorerupt
        !          2356:                        .long   ignorerupt
        !          2357:                        .long   ignorerupt
        !          2358:                        .long   ignorerupt
        !          2359:                        .long   ignorerupt
        !          2360:                        .long   ignorerupt
        !          2361:                        .long   ignorerupt
        !          2362:                        .long   ignorerupt
        !          2363:                        .long   ignorerupt
        !          2364:                        .long   ignorerupt
        !          2365:                        .long   ignorerupt
        !          2366:                        .long   ignorerupt
        !          2367:                        .long   ignorerupt
        !          2368:                        .long   ignorerupt
        !          2369:                        .long   ignorerupt
        !          2370:                        .long   ignorerupt
        !          2371:                        .long   ignorerupt
        !          2372:                        .long   ignorerupt
        !          2373:                        .long   ignorerupt
        !          2374:                        .long   ignorerupt
        !          2375:                        .long   ignorerupt
        !          2376:                        .long   ignorerupt
        !          2377:                        .long   ignorerupt
        !          2378:                        .long   ignorerupt
        !          2379: rupttabend:    .long   ignorerupt
        !          2380: 
        !          2381: /*     (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG)  */
        !          2382: /* */
        !          2383: /*                     Here lies the end of the Phoney Firmware used to test SIGPs.  Take this out later. */
        !          2384: /* */
        !          2385: /*     (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG) (TEST/DEBUG)  */
        !          2386: 
        !          2387: 
        !          2388: /* */
        !          2389: /*                     Table of function offsets */
        !          2390: /* */
        !          2391: 
        !          2392: MPPIFuncOffs:
        !          2393: 
        !          2394:                        .long   CountProcessors-MPPIFunctions                                   /* Offset to routine */
        !          2395:                        .long   StartProcessor-MPPIFunctions                                    /* Offset to routine */
        !          2396:                        .long   ResumeProcessor-MPPIFunctions                                   /* Offset to routine */
        !          2397:                        .long   StopProcessor-MPPIFunctions                                             /* Offset to routine */
        !          2398:                        .long   ResetProcessor-MPPIFunctions                                    /* Offset to routine */
        !          2399:                        .long   SignalProcessor-MPPIFunctions                                   /* Offset to routine */
        !          2400:                        .long   StoreProcessorStatus-MPPIFunctions                              /* Offset to routine */
        !          2401:                        .long   SynchClock-MPPIFunctions                                                /* Offset to routine */
        !          2402:                        .long   GetExtHandlerAddress-MPPIFunctions                              /* Offset to routine */
        !          2403:                        .long   GotSignal-MPPIFunctions                                                 /* Offset to routine */
        !          2404:                        .long   ProcessorState-MPPIFunctions                                    /* Offset to routine */
        !          2405:                        .long   RunSIGPRun-MPPIFunctions                                                /* Offset to routine */
        !          2406:                        .long   mp_PhoneyFirmware-MPPIFunctions                                 /* (TEST/DEBUG) */
        !          2407: 
        !          2408: MPPISize:
        !          2409:        

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.