void ivor_setup(void) { mtspr(SPR_IVPR, ((uintptr_t)&interrupt_vector_base) & 0xffff0000); SET_TRAP(SPR_IVOR0, int_critical_input); SET_TRAP(SPR_IVOR1, int_machine_check); SET_TRAP(SPR_IVOR2, int_data_storage); SET_TRAP(SPR_IVOR3, int_instr_storage); SET_TRAP(SPR_IVOR4, int_external_input); SET_TRAP(SPR_IVOR5, int_alignment); SET_TRAP(SPR_IVOR6, int_program); SET_TRAP(SPR_IVOR8, int_syscall); SET_TRAP(SPR_IVOR10, int_decrementer); SET_TRAP(SPR_IVOR11, int_fixed_interval_timer); SET_TRAP(SPR_IVOR12, int_watchdog); SET_TRAP(SPR_IVOR13, int_data_tlb_error); SET_TRAP(SPR_IVOR14, int_inst_tlb_error); SET_TRAP(SPR_IVOR15, int_debug); #ifdef HWPMC_HOOKS SET_TRAP(SPR_IVOR35, int_performance_counter); #endif switch ((mfpvr() >> 16) & 0xffff) { case FSL_E6500: SET_TRAP(SPR_IVOR32, int_vec); SET_TRAP(SPR_IVOR33, int_vecast); /* FALLTHROUGH */ case FSL_E500mc: case FSL_E5500: SET_TRAP(SPR_IVOR7, int_fpu); } }
/* * Attach the on-chip peripheral bus. */ static void opb_attach(struct device *parent, struct device *self, void *aux) { struct plb_attach_args *paa = aux; struct opb_attach_args oaa; bus_space_tag_t tag; int i, pvr; printf("\n"); pvr = mfpvr() >> 16; tag = opb_get_bus_space_tag(); for (i = 0; opb_devs[i].name != NULL; i++) { if (opb_devs[i].pvr != pvr) continue; oaa.opb_name = opb_devs[i].name; oaa.opb_addr = opb_devs[i].addr; oaa.opb_instance = opb_devs[i].instance; oaa.opb_irq = opb_devs[i].irq; oaa.opb_bt = tag; oaa.opb_dmat = paa->plb_dmat; (void) config_found_sm_loc(self, "opb", NULL, &oaa, opb_print, opb_submatch); } }
static void dfs_identify(driver_t *driver, device_t parent) { uint16_t vers; vers = mfpvr() >> 16; /* Check for an MPC 7447A or 7448 CPU */ switch (vers) { case MPC7447A: case MPC7448: break; default: return; } /* Make sure we're not being doubly invoked. */ if (device_find_child(parent, "dfs", -1) != NULL) return; /* * We attach a child for every CPU since settings need to * be performed on every CPU in the SMP case. */ if (BUS_ADD_CHILD(parent, 10, "dfs", -1) == NULL) device_printf(parent, "add dfs child failed\n"); }
uintptr_t powerpc_init(vm_offset_t startkernel, vm_offset_t endkernel, vm_offset_t basekernel, void *mdp) { struct pcpu *pc; void *generictrap; size_t trap_offset; void *kmdp; char *env; register_t msr, scratch; #ifdef WII register_t vers; #endif uint8_t *cache_check; int cacheline_warn; #ifndef __powerpc64__ int ppc64; #endif kmdp = NULL; trap_offset = 0; cacheline_warn = 0; /* Save trap vectors. */ ofw_save_trap_vec(save_trap_init); #ifdef WII /* * The Wii loader doesn't pass us any environment so, mdp * points to garbage at this point. The Wii CPU is a 750CL. */ vers = mfpvr(); if ((vers & 0xfffff0e0) == (MPC750 << 16 | MPC750CL)) mdp = NULL; #endif /* * Parse metadata if present and fetch parameters. Must be done * before console is inited so cninit gets the right value of * boothowto. */ if (mdp != NULL) { preload_metadata = mdp; kmdp = preload_search_by_type("elf kernel"); if (kmdp != NULL) { boothowto = MD_FETCH(kmdp, MODINFOMD_HOWTO, int); kern_envp = MD_FETCH(kmdp, MODINFOMD_ENVP, char *); endkernel = ulmax(endkernel, MD_FETCH(kmdp, MODINFOMD_KERNEND, vm_offset_t)); #ifdef DDB ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t); ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t); #endif }
int init_dvd() { // Gamecube Mode #ifdef HW_DOL if(mfpvr()!=GC_CPU_VERSION) //GC mode on Wii, modchip required { DVD_Reset(DVD_RESETHARD); dvd_read_id(); if(!dvd_get_error()) { return 0; //we're ok } } else //GC, no modchip even required :) { DVD_Reset(DVD_RESETHARD); DVD_Mount (); if(!dvd_get_error()) { return 0; //we're ok } } if(dvd_get_error()>>24) { return NO_DISC; } return -1; #endif // Wii (Wii mode) #ifdef HW_RVL if(!have_hw_access()) { return NO_HW_ACCESS; } if((dvd_get_error()>>24) == 1) { return NO_DISC; } if((!dvd_hard_init) || (dvd_get_error())) { DI_Mount(); while(DI_GetStatus() & DVD_INIT) usleep(20000); dvd_hard_init=1; } if((dvd_get_error()&0xFFFFFF)==0x053000) { read_cmd = DVDR; } else { read_cmd = NORMAL; } return 0; #endif }
static int wii_probe(platform_t plat) { register_t vers = mfpvr(); /* * The Wii includes a PowerPC 750CL with custom modifications * ("Broadway"). * For now, we just assume that if we are running on a * PowerPC 750CL, then this platform is a Nintendo Wii. */ if ((vers & 0xfffff0e0) == (MPC750 << 16 | MPC750CL)) return (BUS_PROBE_SPECIFIC); return (ENXIO); }
struct pmc_mdep * pmc_md_initialize() { struct pmc_mdep *pmc_mdep; int error; uint16_t vers; /* * Allocate space for pointers to PMC HW descriptors and for * the MDEP structure used by MI code. */ powerpc_pcpu = malloc(sizeof(struct powerpc_cpu *) * pmc_cpu_max(), M_PMC, M_WAITOK|M_ZERO); /* Just one class */ pmc_mdep = pmc_mdep_alloc(1); vers = mfpvr() >> 16; pmc_mdep->pmd_switch_in = powerpc_switch_in; pmc_mdep->pmd_switch_out = powerpc_switch_out; switch (vers) { case MPC7447A: case MPC7448: case MPC7450: case MPC7455: case MPC7457: error = pmc_mpc7xxx_initialize(pmc_mdep); break; case IBM970: case IBM970FX: case IBM970MP: error = pmc_ppc970_initialize(pmc_mdep); break; default: error = -1; break; } if (error != 0) { pmc_mdep_free(pmc_mdep); pmc_mdep = NULL; } return (pmc_mdep); }
/* * Attach the on-chip peripheral bus. */ static void opb_attach(device_t parent, device_t self, void *aux) { struct opb_softc *sc = device_private(self); struct plb_attach_args *paa = aux; struct opb_attach_args oaa; int i, pvr; aprint_naive("\n"); aprint_normal("\n"); pvr = mfpvr() >> 16; sc->sc_dev = self; sc->sc_iot = opb_get_bus_space_tag(); for (i = 0; opb_params[i].pvr != 0 && opb_params[i].pvr != pvr; i++) ; if (opb_params[i].pvr == 0) panic("opb_get_bus_space_tag: no params for this CPU!"); opb_get_frequency = opb_params[i].opb_get_frequency; #ifdef EMAC_ZMII_PHY if (opb_params[i].zmii_base != 0) bus_space_map(sc->sc_iot, opb_params[i].zmii_base, ZMII0_SIZE, 0, &sc->sc_zmiih); #endif #ifdef EMAC_RGMII_PHY if (opb_params[i].rgmii_base != 0) bus_space_map(sc->sc_iot, opb_params[i].rgmii_base, RGMII0_SIZE, 0, &sc->sc_rgmiih); #endif for (i = 0; opb_devs[i].name != NULL; i++) { if (opb_devs[i].pvr != pvr) continue; oaa.opb_name = opb_devs[i].name; oaa.opb_addr = opb_devs[i].addr; oaa.opb_instance = opb_devs[i].instance; oaa.opb_irq = opb_devs[i].irq; oaa.opb_bt = sc->sc_iot; oaa.opb_dmat = paa->plb_dmat; oaa.opb_flags = opb_devs[i].flags; (void) config_found_sm_loc(self, "opb", NULL, &oaa, opb_print, opb_submatch); } }
static int dfs_attach(device_t dev) { struct dfs_softc *sc; uint16_t vers; sc = device_get_softc(dev); sc->dev = dev; sc->dfs4 = 0; vers = mfpvr() >> 16; /* The 7448 supports divide-by-four as well */ if (vers == MPC7448) sc->dfs4 = 1; cpufreq_register(dev); return (0); }
static void cpuattach(struct device *parent, struct device *self, void *aux) { struct cputab *cp = models; u_int pvr; u_int processor_freq; prop_number_t freq; freq = prop_dictionary_get(board_properties, "processor-frequency"); KASSERT(freq != NULL); processor_freq = (unsigned int) prop_number_integer_value(freq); cpufound++; ncpus++; pvr = mfpvr(); while (cp->name) { if ((pvr & cp->mask) == cp->version) break; cp++; } if (cp->name) strcpy(cpu_model, cp->name); else sprintf(cpu_model, "Version 0x%x", pvr); printf(": %dMHz %s (PVR 0x%x)\n", processor_freq / 1000 / 1000, cp->name ? cp->name : "unknown model", pvr); cpu_probe_cache(); /* We would crash later on anyway so just make the reason obvious */ if (curcpu()->ci_ci.icache_size == 0 && curcpu()->ci_ci.dcache_size == 0) panic("%s could not detect cache size", device_xname(self)); printf("%s: Instruction cache size %d line size %d\n", device_xname(self), curcpu()->ci_ci.icache_size, curcpu()->ci_ci.icache_line_size); printf("%s: Data cache size %d line size %d\n", device_xname(self), curcpu()->ci_ci.dcache_size, curcpu()->ci_ci.dcache_line_size); }
bus_space_tag_t opb_get_bus_space_tag(void) { int i, pvr; if (!opb_tag_init_done) { pvr = mfpvr() >> 16; for (i = 0; opb_limits[i].pvr && opb_limits[i].pvr != pvr; i++) ; if (opb_limits[i].pvr == 0) panic("opb_get_bus_space_tag: no limits for this CPU!"); opb_tag.pbs_base = opb_limits[i].base; opb_tag.pbs_limit = opb_limits[i].limit; if (bus_space_init(&opb_tag, "opbtag", ex_storage, sizeof(ex_storage))) panic("opb_attach: Failed to initialise opb_tag"); opb_tag_init_done = 1; }
static sval decode_spr_ins(struct cpu_thread* thr, uval addr, uval32 ins) { struct thread_control_area *tca = get_tca(); uval id = thr->vregs->active_vsave; struct vexc_save_regs *vr = &thr->vregs->vexc_save[id]; sval ret = -1; uval opcode = extract_bits(ins, 0, 6); uval type = extract_bits(ins, 21, 10); uval spr_0_4 = extract_bits(ins, 16, 5); uval spr_5_9 = extract_bits(ins, 11, 5); uval gpr = extract_bits(ins, 6, 5); uval spr = (spr_0_4 << 5) | spr_5_9; /* mfmsr */ if (opcode == 31 && type == 83) { //hprintf("mfmsr r%ld at 0x%lx\n",gpr, addr); mtgpr(thr, gpr, thr->vregs->v_msr); tca->srr0 += sizeof(uval32); return 0; } /* mtmsrd */ if (opcode == 31 && (type == 178 || type == 146)) { uval64 val = mfgpr(thr, gpr); //hprintf("mtmsrd r%ld <- 0x%llx at 0x%lx\n", gpr, val, addr); uval64 chg_mask = ~0ULL; uval l = extract_bits(ins, 15, 1); if (type == 146) { // mtmsr , 32-bits chg_mask = 0xffffffff; } if (l == 1) { chg_mask = (MSR_EE | MSR_RI); } /* These are the only bits we can change here */ val = (val & chg_mask) | (thr->vregs->v_msr & ~chg_mask); set_v_msr(thr, val); val = thr->vregs->v_msr; val |= V_LPAR_MSR_ON; val &= ~V_LPAR_MSR_OFF; tca->srr1 = val; tca->srr0 += sizeof(uval32); return 0; } /* mfspr */ #define SET_GPR(label, src) \ case label: mtgpr(thr, gpr, src); break; if (opcode == 31 && type == 339) { ret = 0; switch (spr) { SET_GPR(SPRN_SRR0, vr->v_srr0); SET_GPR(SPRN_SRR1, vr->v_srr1); SET_GPR(SPRN_PVR, mfpvr()); SET_GPR(SPRN_PIR, mfpir()); case SPRN_DSISR: case SPRN_DAR: mtgpr(thr, gpr, 0); break; case SPRN_HID0: case SPRN_HID1: case SPRN_HID4: case SPRN_HID5: mtgpr(thr, gpr, 0xdeadbeeffeedfaceULL); break; default: ret = -1; break; } if (ret != -1) { tca->srr0 += sizeof(uval32); return ret; } } #define SET_VREG(label, field) \ case label: thr->vregs->field = mfgpr(thr, gpr); break; /* mtspr */ if (opcode == 31 && type == 467) { ret = 0; switch (spr) { SET_VREG(SPRN_SPRG0, v_sprg0); SET_VREG(SPRN_SPRG1, v_sprg1); SET_VREG(SPRN_SPRG2, v_sprg2); SET_VREG(SPRN_SPRG3, v_sprg3); case SPRN_DEC: partition_set_dec(thr, mfgpr(thr, gpr)); thr->vregs->v_dec = mfgpr(thr, gpr); break; case SPRN_SRR0: vr->v_srr0 = mfgpr(thr, gpr); break; case SPRN_SRR1: vr->v_srr1 = mfgpr(thr, gpr); break; case SPRN_DSISR: case SPRN_DAR: break; default: ret = -1; break; } if (ret != -1) { tca->srr0 += sizeof(uval32); return ret; } } /* rfid */ if (opcode == 19 && type == 18) { uval val = vr->v_srr1; set_v_msr(thr, val); val |= V_LPAR_MSR_ON; val &= ~V_LPAR_MSR_OFF; tca->srr1 = val; tca->srr0 = vr->v_srr0; hprintf("rfid: %lx -> %lx\n",addr, vr->v_srr0); return 0; } if (ret == -1) { hprintf("Decode instruction: %ld %ld %ld %ld\n", opcode, type, spr, gpr); } return ret; }
uintptr_t booke_init(u_long arg1, u_long arg2) { uintptr_t ret; void *mdp; vm_offset_t dtbp, end; end = (uintptr_t)_end; dtbp = (vm_offset_t)NULL; /* Set up TLB initially */ bootinfo = NULL; bzero(__sbss_start, __sbss_end - __sbss_start); bzero(__bss_start, _end - __bss_start); tlb1_init(); /* * Handle the various ways we can get loaded and started: * - FreeBSD's loader passes the pointer to the metadata * in arg1, with arg2 undefined. arg1 has a value that's * relative to the kernel's link address (i.e. larger * than 0xc0000000). * - Juniper's loader passes the metadata pointer in arg2 * and sets arg1 to zero. This is to signal that the * loader maps the kernel and starts it at its link * address (unlike the FreeBSD loader). * - U-Boot passes the standard argc and argv parameters * in arg1 and arg2 (resp). arg1 is between 1 and some * relatively small number, such as 64K. arg2 is the * physical address of the argv vector. * - ePAPR loaders pass an FDT blob in r3 (arg1) and the magic hex * string 0x45504150 ('EPAP') in r6 (which has been lost by now). * r4 (arg2) is supposed to be set to zero, but is not always. */ if (arg1 == 0) /* Juniper loader */ mdp = (void *)arg2; else if (booke_check_for_fdt(arg1, &dtbp) == 0) { /* ePAPR */ end = roundup(end, 8); memmove((void *)end, (void *)dtbp, fdt_totalsize((void *)dtbp)); dtbp = end; end += fdt_totalsize((void *)dtbp); __endkernel = end; mdp = NULL; } else if (arg1 > (uintptr_t)kernel_text) /* FreeBSD loader */ mdp = (void *)arg1; else /* U-Boot */ mdp = NULL; /* Default to 32 byte cache line size. */ switch ((mfpvr()) >> 16) { case FSL_E500mc: case FSL_E5500: case FSL_E6500: cacheline_size = 64; break; } ret = powerpc_init(dtbp, 0, 0, mdp); /* Enable caches */ booke_enable_l1_cache(); booke_enable_l2_cache(); booke_enable_bpred(); return (ret); }
/* * This routine must be explicitly called to initialize the * CPU cache information so cache flushe and memcpy operation * work. */ void cpu_probe_cache() { /* * First we need to identify the CPU and determine the * cache line size, or things like memset/memcpy may lose * badly. */ switch (mfpvr() & 0xffff0000) { case PVR_401A1: curcpu()->ci_ci.dcache_size = 1024; curcpu()->ci_ci.dcache_line_size = 16; curcpu()->ci_ci.icache_size = 2848; curcpu()->ci_ci.icache_line_size = 16; break; case PVR_401B2: curcpu()->ci_ci.dcache_size = 8192; curcpu()->ci_ci.dcache_line_size = 16; curcpu()->ci_ci.icache_size = 16384; curcpu()->ci_ci.icache_line_size = 16; break; case PVR_401C2: curcpu()->ci_ci.dcache_size = 8192; curcpu()->ci_ci.dcache_line_size = 16; curcpu()->ci_ci.icache_size = 0; curcpu()->ci_ci.icache_line_size = 16; break; case PVR_401D2: curcpu()->ci_ci.dcache_size = 2848; curcpu()->ci_ci.dcache_line_size = 16; curcpu()->ci_ci.icache_size = 4096; curcpu()->ci_ci.icache_line_size = 16; break; case PVR_401E2: curcpu()->ci_ci.dcache_size = 0; curcpu()->ci_ci.dcache_line_size = 16; curcpu()->ci_ci.icache_size = 0; curcpu()->ci_ci.icache_line_size = 16; break; case PVR_401F2: curcpu()->ci_ci.dcache_size = 2048; curcpu()->ci_ci.dcache_line_size = 16; curcpu()->ci_ci.icache_size = 2848; curcpu()->ci_ci.icache_line_size = 16; break; case PVR_401G2: curcpu()->ci_ci.dcache_size = 2848; curcpu()->ci_ci.dcache_line_size = 16; curcpu()->ci_ci.icache_size = 8192; curcpu()->ci_ci.icache_line_size = 16; break; case PVR_403: curcpu()->ci_ci.dcache_size = 8192; curcpu()->ci_ci.dcache_line_size = 16; curcpu()->ci_ci.icache_size = 16384; curcpu()->ci_ci.icache_line_size = 16; break; case PVR_405GP: curcpu()->ci_ci.dcache_size = 8192; curcpu()->ci_ci.dcache_line_size = 32; curcpu()->ci_ci.icache_size = 8192; curcpu()->ci_ci.icache_line_size = 32; break; case PVR_405GPR: case PVR_405D5X1: case PVR_405D5X2: curcpu()->ci_ci.dcache_size = 16384; curcpu()->ci_ci.dcache_line_size = 32; curcpu()->ci_ci.icache_size = 16384; curcpu()->ci_ci.icache_line_size = 32; break; default: /* * Unknown CPU type. For safety we'll specify a * cache with a 4-byte line size. That way cache * flush routines won't miss any lines. */ curcpu()->ci_ci.dcache_line_size = 4; curcpu()->ci_ci.icache_line_size = 4; break; } }
void aim_cpu_init(vm_offset_t toc) { size_t trap_offset, trapsize; vm_offset_t trap; register_t msr, scratch; uint8_t *cache_check; int cacheline_warn; #ifndef __powerpc64__ int ppc64; #endif trap_offset = 0; cacheline_warn = 0; /* Various very early CPU fix ups */ switch (mfpvr() >> 16) { /* * PowerPC 970 CPUs have a misfeature requested by Apple that * makes them pretend they have a 32-byte cacheline. Turn this * off before we measure the cacheline size. */ case IBM970: case IBM970FX: case IBM970MP: case IBM970GX: scratch = mfspr(SPR_HID5); scratch &= ~HID5_970_DCBZ_SIZE_HI; mtspr(SPR_HID5, scratch); break; #ifdef __powerpc64__ case IBMPOWER7: case IBMPOWER7PLUS: case IBMPOWER8: case IBMPOWER8E: /* XXX: get from ibm,slb-size in device tree */ n_slbs = 32; break; #endif } /* * Initialize the interrupt tables and figure out our cache line * size and whether or not we need the 64-bit bridge code. */ /* * Disable translation in case the vector area hasn't been * mapped (G5). Note that no OFW calls can be made until * translation is re-enabled. */ msr = mfmsr(); mtmsr((msr & ~(PSL_IR | PSL_DR)) | PSL_RI); /* * Measure the cacheline size using dcbz * * Use EXC_PGM as a playground. We are about to overwrite it * anyway, we know it exists, and we know it is cache-aligned. */ cache_check = (void *)EXC_PGM; for (cacheline_size = 0; cacheline_size < 0x100; cacheline_size++) cache_check[cacheline_size] = 0xff; __asm __volatile("dcbz 0,%0":: "r" (cache_check) : "memory"); /* Find the first byte dcbz did not zero to get the cache line size */ for (cacheline_size = 0; cacheline_size < 0x100 && cache_check[cacheline_size] == 0; cacheline_size++); /* Work around psim bug */ if (cacheline_size == 0) { cacheline_warn = 1; cacheline_size = 32; } #ifndef __powerpc64__ /* * Figure out whether we need to use the 64 bit PMAP. This works by * executing an instruction that is only legal on 64-bit PPC (mtmsrd), * and setting ppc64 = 0 if that causes a trap. */ ppc64 = 1; bcopy(&testppc64, (void *)EXC_PGM, (size_t)&testppc64size); __syncicache((void *)EXC_PGM, (size_t)&testppc64size); __asm __volatile("\ mfmsr %0; \ mtsprg2 %1; \ \ mtmsrd %0; \ mfsprg2 %1;" : "=r"(scratch), "=r"(ppc64));
PLATFORMMETHOD(platform_reset, mpc85xx_reset), PLATFORMMETHOD(platform_idle, mpc85xx_idle), PLATFORMMETHOD(platform_idle_wakeup, mpc85xx_idle_wakeup), PLATFORMMETHOD_END }; DEFINE_CLASS_0(mpc85xx, mpc85xx_platform, mpc85xx_methods, 0); PLATFORM_DEF(mpc85xx_platform); static int mpc85xx_probe(platform_t plat) { u_int pvr = mfpvr() >> 16; if ((pvr & 0xfff0) == FSL_E500v1) return (BUS_PROBE_DEFAULT); return (ENXIO); } int mpc85xx_attach(platform_t plat) { phandle_t cpus, child, ccsr; const char *soc_name_guesses[] = {"/soc", "soc", NULL}; const char **name; pcell_t ranges[6], acells, pacells, scells; uint32_t sr;
void info_draw_page(int page_num) { doBackdrop(); DrawEmptyBox(20,60, vmode->fbWidth-20, 420, COLOR_BLACK); syssram* sram = __SYS_LockSram(); __SYS_UnlockSram(0); // System Info (Page 1/3) if(!page_num) { WriteFont(30, 65, "System Info (1/3):"); // Model if(is_gamecube()) { if(*(u32*)&driveVersion[0] == 0x20010831) { sprintf(topStr, "Panasonic Q SL-GC10-S"); } else if(IPLInfo[0x55]=='M') { // MPAL 1.1 (Brazil) sprintf(topStr, "Nintendo GameCube DOL-002 (BRA)"); } else if((!IPLInfo[0x55]) // NTSC 1.0 || (IPLInfo[0x55] == 'P' && IPLInfo[0x65]=='0') // PAL 1.0 || (IPLInfo[0x55] != 'P' && IPLInfo[0x65]=='1')) { // NTSC 1.1 sprintf(topStr, "Nintendo GameCube DOL-001"); } else if((IPLInfo[0x55] == 'P' && IPLInfo[0x65]=='0') // PAL 1.1 || IPLInfo[0x65]=='2') { // NTSC 1.2 sprintf(topStr, "Nintendo GameCube DOL-101"); } } else { sprintf(topStr, "Nintendo Wii"); } WriteFontStyled(640/2, 110, topStr, 1.0f, true, defaultColor); // IPL version string if(is_gamecube()) { if(!IPLInfo[0x55]) { sprintf(topStr, "NTSC Revision 1.0"); } else { sprintf(topStr, "%s", &IPLInfo[0x55]); } } else { sprintf(topStr, "Wii IPL"); } WriteFontStyled(640/2, 140, topStr, 1.0f, true, defaultColor); if(swissSettings.hasDVDDrive) { if((!__wkfSpiReadId() || (__wkfSpiReadId() == 0xFFFFFFFF))) { sprintf(topStr, "DVD Drive %02X %02X%02X/%02X (%02X)",driveVersion[2],driveVersion[0],driveVersion[1],driveVersion[3],driveVersion[4]); } else { sprintf(topStr, "WKF Serial %s",wkfGetSerial()); } } else sprintf(topStr, "No DVD Drive present"); WriteFontStyled(640/2, 170, topStr, 1.0f, true, defaultColor); sprintf(topStr, "%s",videoStr); WriteFontStyled(640/2, 200, topStr, 1.0f, true, defaultColor); sprintf(topStr,"%s / %s",getSramLang(sram->lang), sram->flags&4 ? "Stereo":"Mono"); WriteFontStyled(640/2, 230, topStr, 1.0f, true, defaultColor); sprintf(topStr,"PVR %08X ECID %08X:%08X:%08X",mfpvr(),mfspr(0x39C),mfspr(0x39D),mfspr(0x39E)); WriteFontStyled(640/2, 260, topStr, 0.75f, true, defaultColor); } else if(page_num == 1) { WriteFont(30, 65, "Device Info (2/3):"); sprintf(topStr,"BBA: %s", bba_exists ? "Installed":"Not Present"); WriteFont(30, 110, topStr); if(exi_bba_exists()) { sprintf(topStr,"IP: %s", net_initialized ? bba_ip:"Not Available"); } else { sprintf(topStr,"IP: Not Available"); } WriteFont(270, 110, topStr); sprintf(topStr,"Component Cable Plugged in: %s",VIDEO_HaveComponentCable()?"Yes":"No"); WriteFont(30, 140, topStr); if(usb_isgeckoalive(0)||usb_isgeckoalive(1)) { sprintf(topStr,"USB Gecko: Installed in %s",usb_isgeckoalive(0)?"Slot A":"Slot B"); } else { sprintf(topStr,"USB Gecko: Not Present"); } WriteFont(30, 170, topStr); if (!deviceHandler_initial) { sprintf(topStr, "Current Device: No Device Selected"); } else if(deviceHandler_initial == &initial_SD0 || deviceHandler_initial == &initial_SD1) { int slot = (deviceHandler_initial->name[2] == 'b'); sprintf(topStr, "Current Device: %s Card in %s @ %s",!SDHCCard?"SDHC":"SD",!slot?"Slot A":"Slot B",!swissSettings.exiSpeed?"16Mhz":"32Mhz"); } else if(deviceHandler_initial == &initial_DVD) { sprintf(topStr, "Current Device: %s DVD Disc",dvdDiscTypeStr); } else if(deviceHandler_initial == &initial_IDE0 || deviceHandler_initial == &initial_IDE1) { int slot = (deviceHandler_initial->name[3] == 'b'); sprintf(topStr, "Current Device: %d GB HDD in %s",ataDriveInfo.sizeInGigaBytes,!slot?"Slot A":"Slot B"); } else if(deviceHandler_initial == &initial_Qoob) { sprintf(topStr, "Current Device: Qoob IPL Replacement"); } else if(deviceHandler_initial == &initial_WODE) { sprintf(topStr, "Current Device: Wode Jukebox"); } else if(deviceHandler_initial == &initial_CARDA || deviceHandler_initial == &initial_CARDB) { sprintf(topStr, "Current Device: Memory Card in %s",!deviceHandler_initial->fileBase?"Slot A":"Slot B"); } else if(deviceHandler_initial == &initial_USBGecko) { sprintf(topStr, "Current Device: USB Gecko"); } else if(deviceHandler_initial == &initial_WKF) { sprintf(topStr, "Current Device: Wiikey Fusion"); } else if(deviceHandler_initial == &initial_SYS) { sprintf(topStr, "Current Device: System"); } WriteFont(30, 200, topStr); } else if(page_num == 2) { WriteFont(30, 65, "Credits (3/3):"); WriteFontStyled(640/2, 115, "Swiss ver 0.4", 1.0f, true, defaultColor); WriteFontStyled(640/2, 140, "by emu_kidid 2015", 0.75f, true, defaultColor); sprintf(txtbuffer, "Commit %s Revision %s SD Gecko Slot B Cheats Mod", GITREVISION, GITVERSION); WriteFontStyled(640/2, 165, txtbuffer, 0.75f, true, defaultColor); WriteFontStyled(640/2, 210, "Thanks to", 0.75f, true, defaultColor); WriteFontStyled(640/2, 228, "Testers & libOGC/dkPPC authors", 0.75f, true, defaultColor); WriteFontStyled(640/2, 246, "sepp256 for GX / FIX94 for Audio Streaming", 0.75f, true, defaultColor); WriteFontStyled(640/2, 264, "Extrems for video patches / Megalomaniac for builds", 0.75f, true, defaultColor); WriteFontStyled(640/2, 282, "Fishaman P for cheats support with all devices", 0.75f, true, defaultColor); WriteFontStyled(640/2, 318, "Web/Support http://www.gc-forever.com/", 0.75f, true, defaultColor); WriteFontStyled(640/2, 336, "Source at https://github.com/emukidid/swiss-gc", 0.75f, true, defaultColor); WriteFontStyled(640/2, 354, "Visit us at #gc-forever on EFNet", 0.75f, true, defaultColor); } if(page_num != 2) { WriteFont(520, 390, "->"); } if(page_num != 0) { WriteFont(100, 390, "<-"); } WriteFontStyled(640/2, 400, "Press A to return", 1.0f, true, defaultColor); DrawFrameFinish(); }