implemented ultracic detection code
This commit is contained in:
parent
b7dd066fa0
commit
2034bedc1a
166
inc/regsinternal.h
Normal file
166
inc/regsinternal.h
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
//TODO: this file is actually part of the libdragon source and should be included from there!!!
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file regsinternal.h
|
||||||
|
* @brief Register definitions for various hardware in the N64
|
||||||
|
* @ingroup lowlevel
|
||||||
|
*/
|
||||||
|
#ifndef __LIBDRAGON_REGSINTERNAL_H
|
||||||
|
#define __LIBDRAGON_REGSINTERNAL_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup lowlevel Low Level Hardware Interfaces
|
||||||
|
* @ingroup libdragon
|
||||||
|
* @brief Low level hardware interface descriptions and functionality
|
||||||
|
*
|
||||||
|
* The low level hardware interfaces handle several functions in the N64 that
|
||||||
|
* would otherwise be handled by a kernel or RTOS. This includes the @ref dma,
|
||||||
|
* the @ref exceptions, the @ref interrupt and the @ref n64sys. The DMA controller
|
||||||
|
* handles DMA requests between the cartridge and the N64 RDRAM. Other systems
|
||||||
|
* in the N64 have their own DMA controllers that are handled in the relevant
|
||||||
|
* subsystems. The exception handler traps any exceptions raised by the N64,
|
||||||
|
* including the reset exception. The interrupt handler sets up the MIPS
|
||||||
|
* interface (MI) which handles low level interrupt functionality for all other
|
||||||
|
* systems in the N64. The N64 system interface provides the ability for code to
|
||||||
|
* manipulate cache and boot options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register definition for the AI interface
|
||||||
|
* @ingroup lowlevel
|
||||||
|
*/
|
||||||
|
typedef struct AI_regs_s {
|
||||||
|
/** @brief Pointer to uncached memory buffer of samples to play */
|
||||||
|
volatile void * address;
|
||||||
|
/** @brief Size in bytes of the buffer to be played. Should be
|
||||||
|
* number of stereo samples * 2 * sizeof( uint16_t )
|
||||||
|
*/
|
||||||
|
uint32_t length;
|
||||||
|
/** @brief DMA start register. Write a 1 to this register to start
|
||||||
|
* playing back an audio sample. */
|
||||||
|
uint32_t control;
|
||||||
|
/** @brief AI status register. Bit 31 is the full bit, bit 30 is the busy bit. */
|
||||||
|
uint32_t status;
|
||||||
|
/** @brief Rate at which the buffer should be played.
|
||||||
|
*
|
||||||
|
* Use the following formula to calculate the value: ((2 * clockrate / frequency) + 1) / 2 - 1
|
||||||
|
*/
|
||||||
|
uint32_t dacrate;
|
||||||
|
/** @brief The size of a single sample in bits. */
|
||||||
|
uint32_t samplesize;
|
||||||
|
} AI_regs_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register definition for the MI interface
|
||||||
|
* @ingroup lowlevel
|
||||||
|
*/
|
||||||
|
typedef struct MI_regs_s {
|
||||||
|
/** @brief Mode register */
|
||||||
|
uint32_t mode;
|
||||||
|
/** @brief Version register */
|
||||||
|
uint32_t version;
|
||||||
|
/** @brief Current interrupts on the system */
|
||||||
|
uint32_t intr;
|
||||||
|
/** @brief Interrupt mask */
|
||||||
|
uint32_t mask;
|
||||||
|
} MI_regs_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register definition for the VI interface
|
||||||
|
* @ingroup lowlevel
|
||||||
|
*/
|
||||||
|
typedef struct VI_regs_s {
|
||||||
|
/** @brief VI control register. Sets up various rasterization modes */
|
||||||
|
uint32_t control;
|
||||||
|
/** @brief Pointer to uncached buffer in memory to rasterize */
|
||||||
|
void * framebuffer;
|
||||||
|
/** @brief Width of the buffer in pixels */
|
||||||
|
uint32_t width;
|
||||||
|
/** @brief Vertical interrupt control register. Controls which horizontal
|
||||||
|
* line must be hit to generate a VI interrupt
|
||||||
|
*/
|
||||||
|
uint32_t v_int;
|
||||||
|
/** @brief Current vertical line counter. */
|
||||||
|
uint32_t cur_line;
|
||||||
|
/** @brief Timing generation register for PAL/NTSC signals */
|
||||||
|
uint32_t timing;
|
||||||
|
/** @brief Number of lines per frame */
|
||||||
|
uint32_t v_sync;
|
||||||
|
/** @brief Number of pixels in line and leap pattern */
|
||||||
|
uint32_t h_sync;
|
||||||
|
/** @brief Number of pixels in line, set identically to h_sync */
|
||||||
|
uint32_t h_sync2;
|
||||||
|
/** @brief Beginning and end of video horizontally */
|
||||||
|
uint32_t h_limits;
|
||||||
|
/** @brief Beginning and end of video vertically */
|
||||||
|
uint32_t v_limits;
|
||||||
|
/** @brief Beginning and end of color burst in vertical lines */
|
||||||
|
uint32_t color_burst;
|
||||||
|
/** @brief Horizontal scaling factor from buffer to screen */
|
||||||
|
uint32_t h_scale;
|
||||||
|
/** @brief Vertical scaling factor from buffer to screen */
|
||||||
|
uint32_t v_scale;
|
||||||
|
} VI_regs_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register definition for the PI interface
|
||||||
|
* @ingroup lowlevel
|
||||||
|
*/
|
||||||
|
typedef struct PI_regs_s {
|
||||||
|
/** @brief Uncached address in RAM where data should be found */
|
||||||
|
volatile void * ram_address;
|
||||||
|
/** @brief Address of data on peripheral */
|
||||||
|
uint32_t pi_address;
|
||||||
|
/** @brief How much data to read from RAM into the peripheral */
|
||||||
|
uint32_t read_length;
|
||||||
|
/** @brief How much data to write to RAM from the peripheral */
|
||||||
|
uint32_t write_length;
|
||||||
|
/** @brief Status of the PI, including DMA busy */
|
||||||
|
uint32_t status;
|
||||||
|
} PI_regs_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register definition for the SI interface
|
||||||
|
* @ingroup lowlevel
|
||||||
|
*/
|
||||||
|
typedef struct SI_regs_s {
|
||||||
|
/** @brief Uncached address in RAM where data should be found */
|
||||||
|
volatile void * DRAM_addr;
|
||||||
|
/** @brief Address to read when copying from PIF RAM */
|
||||||
|
volatile void * PIF_addr_read;
|
||||||
|
/** @brief Reserved word */
|
||||||
|
uint32_t reserved1;
|
||||||
|
/** @brief Reserved word */
|
||||||
|
uint32_t reserved2;
|
||||||
|
/** @brief Address to write when copying to PIF RAM */
|
||||||
|
volatile void * PIF_addr_write;
|
||||||
|
/** @brief Reserved word */
|
||||||
|
uint32_t reserved3;
|
||||||
|
/** @brief SI status, including DMA busy and IO busy */
|
||||||
|
uint32_t status;
|
||||||
|
} SI_regs_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register definition for the SP interface
|
||||||
|
* @ingroup lowlevel
|
||||||
|
*/
|
||||||
|
typedef struct SP_regs_s {
|
||||||
|
/** @brief RSP memory address (IMEM/DMEM) */
|
||||||
|
volatile void * RSP_addr;
|
||||||
|
/** @brief RDRAM memory address */
|
||||||
|
volatile void * RDAM_addr;
|
||||||
|
/** @brief RDRAM->RSP DMA length */
|
||||||
|
uint32_t rsp_read_length;
|
||||||
|
/** @brief RDP->RDRAM DMA length */
|
||||||
|
uint32_t rsp_write_length;
|
||||||
|
/** @brief RSP status */
|
||||||
|
uint32_t status;
|
||||||
|
/** @brief RSP DMA full */
|
||||||
|
uint32_t rsp_dma_full;
|
||||||
|
/** @brief RSP DMA busy */
|
||||||
|
uint32_t rsp_dma_busy;
|
||||||
|
/** @brief RSP Semaphore */
|
||||||
|
uint32_t rsp_semaphore;
|
||||||
|
} SP_regs_t;
|
||||||
|
|
||||||
|
#endif
|
97
src/cic.c
97
src/cic.c
@ -12,7 +12,13 @@
|
|||||||
//#include "si/cic.h"
|
//#include "si/cic.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libdragon.h>
|
||||||
|
#include "regsinternal.h"
|
||||||
#include "cic.h"
|
#include "cic.h"
|
||||||
|
#include "types.h"
|
||||||
|
#include "rom.h" //TODO: perhaps the pifram defines should be global
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// CIC seeds and status bits passed from PIF to IPL through PIF RAM
|
// CIC seeds and status bits passed from PIF to IPL through PIF RAM
|
||||||
@ -115,3 +121,94 @@ uint32_t si_crc32(const uint8_t *data, size_t size) {
|
|||||||
|
|
||||||
return c ^ 0xFFFFFFFF;
|
return c ^ 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static volatile struct SI_regs_s * const SI_regs = (struct SI_regs_s *) 0xa4800000;
|
||||||
|
static void * const PIF_RAM = (void *) 0x1fc007c0;
|
||||||
|
|
||||||
|
/** @brief SI DMA busy */
|
||||||
|
#define SI_STATUS_DMA_BUSY ( 1 << 0 )
|
||||||
|
/** @brief SI IO busy */
|
||||||
|
#define SI_STATUS_IO_BUSY ( 1 << 1 )
|
||||||
|
|
||||||
|
static void __SI_DMA_wait(void) {
|
||||||
|
while (SI_regs->status & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __controller_exec_PIF(void *inblock, void *outblock) {
|
||||||
|
volatile uint64_t inblock_temp[8];
|
||||||
|
volatile uint64_t outblock_temp[8];
|
||||||
|
|
||||||
|
data_cache_hit_writeback_invalidate(inblock_temp, 64);
|
||||||
|
memcpy(UncachedAddr(inblock_temp), inblock, 64);
|
||||||
|
|
||||||
|
/* Be sure another thread doesn't get into a resource fight */
|
||||||
|
disable_interrupts();
|
||||||
|
|
||||||
|
__SI_DMA_wait();
|
||||||
|
|
||||||
|
SI_regs->DRAM_addr = inblock_temp; // only cares about 23:0
|
||||||
|
MEMORY_BARRIER();
|
||||||
|
SI_regs->PIF_addr_write = PIF_RAM; // is it really ever anything else?
|
||||||
|
MEMORY_BARRIER();
|
||||||
|
|
||||||
|
__SI_DMA_wait();
|
||||||
|
|
||||||
|
data_cache_hit_writeback_invalidate(outblock_temp, 64);
|
||||||
|
|
||||||
|
SI_regs->DRAM_addr = outblock_temp;
|
||||||
|
MEMORY_BARRIER();
|
||||||
|
SI_regs->PIF_addr_read = PIF_RAM;
|
||||||
|
MEMORY_BARRIER();
|
||||||
|
|
||||||
|
__SI_DMA_wait();
|
||||||
|
|
||||||
|
/* Now that we've copied, its safe to let other threads go */
|
||||||
|
enable_interrupts();
|
||||||
|
|
||||||
|
memcpy(outblock, UncachedAddr(outblock_temp), 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pifram_x105_response_test() {
|
||||||
|
|
||||||
|
static unsigned long long SI_eeprom_read_block[8] = {
|
||||||
|
0xFFFFFFFFFFFFFFFF,
|
||||||
|
0xFFFFFFFFFFFFFFFF,
|
||||||
|
0xFFFFFFFFFFFFFFFF,
|
||||||
|
0xFFFFFFFFFFFFFFFF,
|
||||||
|
0xFFFFFFFFFFFFFFFF,
|
||||||
|
0xFFFFFFFFFFFF0F0F,
|
||||||
|
0x8B00620018000600,
|
||||||
|
0x0100C000B0000002 //0x3f=02
|
||||||
|
|
||||||
|
};
|
||||||
|
static unsigned long long output[8];
|
||||||
|
|
||||||
|
__controller_exec_PIF(SI_eeprom_read_block,output);
|
||||||
|
|
||||||
|
/*
|
||||||
|
expected result
|
||||||
|
FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FF FF FF FF FF FF
|
||||||
|
FF FF FF FF FF FF 00 00
|
||||||
|
3E C6 C0 4E BD 37 15 55
|
||||||
|
5A 8C 2A 8C D3 71 71 00
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We are looking for 0x55 in [6], which
|
||||||
|
* signifies that there is an x105 present.*/
|
||||||
|
|
||||||
|
if( (output[6] & 0xFF) == 0x55 )
|
||||||
|
{
|
||||||
|
//x105 found!
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//x105 not found!
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user