• Hello Guest! We're hosting a challenge to welcome vintage Intel macs to the MLA during the month of July! See this thread for more information.
  • We've made some quality of life improvements to the Trading Post. More info here.

NuCF development (aka, the IIfx is a quirky sod)

zigzagjoe

68060
As I don't have a worklog thread for the NuCF, I suppose it's time to start one. I've finally revisited the NuCF and issue it has on the IIfx; recap is around a year ago I suspected something screwy is going on with the /AS strobe seen by the IO bus and PDS slot. It's generated in a PAL in the 20mhz clock domain used for those subsystems, rather than coming out of the 030. Unfortunately, I was not able to capture the *what* as even putting a scope or LA probe on /AS would suddenly cause it to start working. Hacky fixes like adding some resistance or capacitance would help, but that's ultimately a wretched hack and is just reducing the probability rather than removing the cause.

For that among other reasons the NuCF project went on the shelf for the past year.

I *finally* captured the smoking gun, though. While I still haven't captured /AS directly for lack of an active scope probe, I was instead able to find an indirect and damning symptom. I started from square 1 and started building the logic up from scratch again, and found even the well-tested writing to the flash wasn't working correctly. That's a pretty fundamental issue!

Below is a strobe to the DeclROM on the card. By process of elimination if I swapped it to be a product of /DS instead of /AS, my prior inability to write to flash would clear up. Easy enough to capture on the scope, and would you look at that glitch. It can be inferred that it's worse in actuality since there's propogation delays/hysteresis in the CPLD generating this strobe. My assumption is the actual root cause is likely ringing.

I suppose that's the peril of working with high speed CMOS logic (flash, CPLD, and CF cards) - where the geriatric IO devices on the logic board are too slow to react in time or be disrupted by it, the modern stuff I'm using is fast enough. Remains to be seen how I'll choose to address this, but there's options, at least the cause is *confirmed*, finally.

fuckin ifx shit.png

Some incidental tidbits about bare metal code on IIfx:

Disable ROM overlay, stolen directly from SuperMario source

Code:
#define OSSRomCntl    0x204                    //offset to ROM control register.  Bits are:
#define OSSRomInit    0xD                      // initial value for ROM control register<3.5>

// overlay off, 2 ROM wait states
move.b  #OSSRomInit,(OSSRomCntl+ADDR_OSS)

How to put the SCC IOP into bypass mode for direct access. Also stolen directly from SuperMario. Looks like they tell the IOP to set a couple of its private registers then hang it.

Code:
#define ADDR_SCC_IOP    0x50F04000
#define ADDR_SCC    (ADDR_SCC_IOP+32) /* actual SCC address, in passthrough mode */

#define iopRamAddrH              (0x0000-0x20)               // high byte of shared RAM address register
#define iopRamAddrL              (0x0002-0x20)               // low byte of shared RAM address register
#define iopRamAddr               (iopRamAddrL-1)           // WORD access to shared RAM address register

#define iopRamData               (0x0008-0x20)               // shared RAM data register (byte, word, or long)
#define iopStatCtl               (0x0004-0x20)               // IOP Status and Control register

//   bit numbers within the iopStatCtl register
#define iopInBypassMode          0                       // IOP is in BYPASS mode
#define iopIncEnable             1                       // enable addr pointer increment
#define iopRun                   2                       // 0 -> reset IOP, 1 -> run IOP
#define iopGenInterrupt          3                       // interrupt the IOP
#define iopInt0Active            4                       // interrupt 0 active
#define iopInt1Active            5                       // interrupt 1 active
#define iopBypassIntReq          6                       // peripheral chip interrupt request in bypass mode
#define iopSCCWrReq              7                       // 0 -> SCC REQ active, 1 -> inactive

//   commands bytes to write to the iopStatCtl register
#define resetIopRun              ((0<<iopRun)+(1<<iopInt0Active)+(1<<iopInt1Active)+(1<<iopIncEnable)) 
#define setIopRun                ((1<<iopRun)+(1<<iopInt0Active)+(1<<iopInt1Active)+(1<<iopIncEnable))

SetSCCIOPBypass:                    
    movea.l #ADDR_SCC_IOP,%a3    
    move.b    #resetIopRun,iopStatCtl(%a3) | init the Status/Ctl reg, hold IOP reset

    | Download the IOP code
    lea     SCCIOPInitCode,%a0        | a0 <- start of IOP code (in this ROM)
    
    move.w    (%a0)+,%d0                | get the size code (-1 for DBRA)
    move.w    (%a0)+,iopRamAddr(%a3)    | setup the code load address
LoadLoop:        
    move.b    (%a0)+,iopRamData(%a3)    | download a byte
    dbra    %d0,LoadLoop            | load all of the bytes

| Start IOP execution
    move.b    #setIopRun,iopStatCtl(%a3) | release IOP reset (let it rip!)
    lsr.w    #6,%d0                    | 0xFFFF -> 0x03FF -> loop 1024 times
wait:    
    dbra    %d0,wait                | delay a bit while IOP initializes

    rts                                | return to caller
|----------------------------------------------------------------------------            
                                    | 6502 code to throw SCC IOP into bypass mode
SCCIOPInitCode:
    dc.w    (2f-1f)-1                 |    (byte) size of the code
    dc.w    0x8000-(2f-1f)             |    (word) load address
1:                                    |    code starts here
    dc.b    0xA9,0x81                 | 7FEE: lda     #1*DEBUG+0*SCCISM+1*BYPASS
    dc.b    0x8D,0x30,0xF0             | 7FF0: sta     SCCControlReg
    dc.b    0xA9,0x44                 | 7FF3: lda     #SccIOCtlReg
    dc.b    0x8D,0x31,0xF0             | 7FF5: sta     IOControlReg
    dc.b    0x80,0xFE                 | 7FF8: bra     0x7FF8

    dc.b    0xEE,0x7F                 | 7FFA    7FEE    Non-Maskable Interrupt vector
    dc.b    0xEE,0x7F                 | 7FFA    7FEE    Processor reset vector
    dc.b    0xEE,0x7F                 | 7FFA    7FEE    Interrupt Request vector
2:                                    |    code ends here
 
Back
Top