mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
Merge branch 'master' of https://github.com/SciresM/Atmosphere-NX
This commit is contained in:
commit
d4c1e0b982
16 changed files with 496 additions and 26 deletions
|
@ -4,7 +4,7 @@
|
||||||
#include "car.h"
|
#include "car.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
|
||||||
static inline uint32_t get_special_clk_reg(car_device_t dev) {
|
static inline uint32_t get_special_clk_reg(CarDevice dev) {
|
||||||
switch (dev) {
|
switch (dev) {
|
||||||
case CARDEVICE_UARTA: return 0x178;
|
case CARDEVICE_UARTA: return 0x178;
|
||||||
case CARDEVICE_UARTB: return 0x17C;
|
case CARDEVICE_UARTB: return 0x17C;
|
||||||
|
@ -15,7 +15,7 @@ static inline uint32_t get_special_clk_reg(car_device_t dev) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t get_special_clk_val(car_device_t dev) {
|
static inline uint32_t get_special_clk_val(CarDevice dev) {
|
||||||
switch (dev) {
|
switch (dev) {
|
||||||
case CARDEVICE_UARTA: return 0;
|
case CARDEVICE_UARTA: return 0;
|
||||||
case CARDEVICE_UARTB: return 0;
|
case CARDEVICE_UARTB: return 0;
|
||||||
|
@ -29,7 +29,7 @@ static inline uint32_t get_special_clk_val(car_device_t dev) {
|
||||||
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x320, 0x328, 0x330, 0x440, 0x448, 0x284, 0x29C};
|
static uint32_t g_clk_reg_offsets[NUM_CAR_BANKS] = {0x320, 0x328, 0x330, 0x440, 0x448, 0x284, 0x29C};
|
||||||
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x300, 0x308, 0x310, 0x430, 0x438, 0x290, 0x2A8};
|
static uint32_t g_rst_reg_offsets[NUM_CAR_BANKS] = {0x300, 0x308, 0x310, 0x430, 0x438, 0x290, 0x2A8};
|
||||||
|
|
||||||
void clk_enable(car_device_t dev) {
|
void clk_enable(CarDevice dev) {
|
||||||
uint32_t special_reg;
|
uint32_t special_reg;
|
||||||
if ((special_reg = get_special_clk_reg(dev))) {
|
if ((special_reg = get_special_clk_reg(dev))) {
|
||||||
MAKE_CAR_REG(special_reg) = get_special_clk_val(dev);
|
MAKE_CAR_REG(special_reg) = get_special_clk_val(dev);
|
||||||
|
@ -37,30 +37,30 @@ void clk_enable(car_device_t dev) {
|
||||||
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clk_disable(car_device_t dev) {
|
void clk_disable(CarDevice dev) {
|
||||||
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5] + 0x004) |= BIT(dev & 0x1F);
|
MAKE_CAR_REG(g_clk_reg_offsets[dev >> 5] + 0x004) |= BIT(dev & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rst_enable(car_device_t dev) {
|
void rst_enable(CarDevice dev) {
|
||||||
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5]) |= BIT(dev & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rst_disable(car_device_t dev) {
|
void rst_disable(CarDevice dev) {
|
||||||
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5] + 0x004) |= BIT(dev & 0x1F);
|
MAKE_CAR_REG(g_rst_reg_offsets[dev >> 5] + 0x004) |= BIT(dev & 0x1F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void clkrst_enable(car_device_t dev) {
|
void clkrst_enable(CarDevice dev) {
|
||||||
clk_enable(dev);
|
clk_enable(dev);
|
||||||
rst_disable(dev);
|
rst_disable(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clkrst_disable(car_device_t dev) {
|
void clkrst_disable(CarDevice dev) {
|
||||||
rst_enable(dev);
|
rst_enable(dev);
|
||||||
clk_disable(dev);
|
clk_disable(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clkrst_reboot(car_device_t dev) {
|
void clkrst_reboot(CarDevice dev) {
|
||||||
clkrst_disable(dev);
|
clkrst_disable(dev);
|
||||||
wait(100);
|
wait(100);
|
||||||
clkrst_enable(dev);
|
clkrst_enable(dev);
|
||||||
|
|
|
@ -23,16 +23,16 @@ typedef enum {
|
||||||
CARDEVICE_I2C1 = 12,
|
CARDEVICE_I2C1 = 12,
|
||||||
CARDEVICE_I2C5 = 47,
|
CARDEVICE_I2C5 = 47,
|
||||||
CARDEVICE_BPMP = 1
|
CARDEVICE_BPMP = 1
|
||||||
} car_device_t;
|
} CarDevice;
|
||||||
|
|
||||||
void clk_enable(car_device_t dev);
|
void clk_enable(CarDevice dev);
|
||||||
void clk_disable(car_device_t dev);
|
void clk_disable(CarDevice dev);
|
||||||
void rst_enable(car_device_t dev);
|
void rst_enable(CarDevice dev);
|
||||||
void rst_disable(car_device_t dev);
|
void rst_disable(CarDevice dev);
|
||||||
|
|
||||||
void clkrst_enable(car_device_t dev);
|
void clkrst_enable(CarDevice dev);
|
||||||
void clkrst_disable(car_device_t dev);
|
void clkrst_disable(CarDevice dev);
|
||||||
|
|
||||||
void clkrst_reboot(car_device_t dev);
|
void clkrst_reboot(CarDevice dev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
static bool g_battery_profile = false;
|
static bool g_battery_profile = false;
|
||||||
|
|
||||||
uint32_t configitem_set(enum ConfigItem item, uint64_t value) {
|
uint32_t configitem_set(ConfigItem item, uint64_t value) {
|
||||||
if (item != CONFIGITEM_BATTERYPROFILE) {
|
if (item != CONFIGITEM_BATTERYPROFILE) {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ uint64_t configitem_get_hardware_type(void) {
|
||||||
return hardware_type;
|
return hardware_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue) {
|
uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue) {
|
||||||
uint32_t result = 0;
|
uint32_t result = 0;
|
||||||
switch (item) {
|
switch (item) {
|
||||||
case CONFIGITEM_DISABLEPROGRAMVERIFICATION:
|
case CONFIGITEM_DISABLEPROGRAMVERIFICATION:
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
enum ConfigItem {
|
typedef enum {
|
||||||
CONFIGITEM_DISABLEPROGRAMVERIFICATION = 1,
|
CONFIGITEM_DISABLEPROGRAMVERIFICATION = 1,
|
||||||
CONFIGITEM_DRAMID = 2,
|
CONFIGITEM_DRAMID = 2,
|
||||||
CONFIGITEM_SECURITYENGINEIRQ = 3,
|
CONFIGITEM_SECURITYENGINEIRQ = 3,
|
||||||
|
@ -18,10 +18,10 @@ enum ConfigItem {
|
||||||
CONFIGITEM_ISDEBUGMODE = 11,
|
CONFIGITEM_ISDEBUGMODE = 11,
|
||||||
CONFIGITEM_KERNELMEMORYCONFIGURATION = 12,
|
CONFIGITEM_KERNELMEMORYCONFIGURATION = 12,
|
||||||
CONFIGITEM_BATTERYPROFILE = 13
|
CONFIGITEM_BATTERYPROFILE = 13
|
||||||
};
|
} ConfigItem;
|
||||||
|
|
||||||
uint32_t configitem_set(enum ConfigItem item, uint64_t value);
|
uint32_t configitem_set(ConfigItem item, uint64_t value);
|
||||||
uint32_t configitem_get(enum ConfigItem item, uint64_t *p_outvalue);
|
uint32_t configitem_get(ConfigItem item, uint64_t *p_outvalue);
|
||||||
|
|
||||||
bool configitem_is_recovery_boot(void);
|
bool configitem_is_recovery_boot(void);
|
||||||
bool configitem_is_retail(void);
|
bool configitem_is_retail(void);
|
||||||
|
|
291
exosphere/src/dbg/fmt.c
Normal file
291
exosphere/src/dbg/fmt.c
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
/* File : barebones/ee_printf.c
|
||||||
|
This file contains an implementation of ee_printf that only requires a method to output a char to a UART without pulling in library code.
|
||||||
|
This code is based on a file that contains the following:
|
||||||
|
Copyright (C) 2002 Michael Ringgaard. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the project nor the names of its contributors
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//TuxSH's changes: add support for 64-bit numbers, remove floating-point code
|
||||||
|
// (C) AuroraWright, TuxSH
|
||||||
|
|
||||||
|
#include "../utils.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "fmt.h"
|
||||||
|
|
||||||
|
#define ZEROPAD (1<<0) //Pad with zero
|
||||||
|
#define SIGN (1<<1) //Unsigned/signed long
|
||||||
|
#define PLUS (1<<2) //Show plus
|
||||||
|
#define SPACE (1<<3) //Spacer
|
||||||
|
#define LEFT (1<<4) //Left justified
|
||||||
|
#define HEX_PREP (1<<5) //0x
|
||||||
|
#define UPPERCASE (1<<6) //'ABCDEF'
|
||||||
|
|
||||||
|
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
|
||||||
|
|
||||||
|
static int32_t skipAtoi(const char **s)
|
||||||
|
{
|
||||||
|
int32_t i = 0;
|
||||||
|
|
||||||
|
while(IS_DIGIT(**s)) i = i * 10 + *((*s)++) - '0';
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *processNumber(char *str, int64_t num, bool isHex, int32_t size, int32_t precision, uint32_t type)
|
||||||
|
{
|
||||||
|
char sign = 0;
|
||||||
|
|
||||||
|
if(type & SIGN)
|
||||||
|
{
|
||||||
|
if(num < 0)
|
||||||
|
{
|
||||||
|
sign = '-';
|
||||||
|
num = -num;
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
else if(type & PLUS)
|
||||||
|
{
|
||||||
|
sign = '+';
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
else if(type & SPACE)
|
||||||
|
{
|
||||||
|
sign = ' ';
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *lowerDigits = "0123456789abcdef",
|
||||||
|
*upperDigits = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
int32_t i = 0;
|
||||||
|
char tmp[20];
|
||||||
|
const char *dig = (type & UPPERCASE) ? upperDigits : lowerDigits;
|
||||||
|
|
||||||
|
if(num == 0)
|
||||||
|
{
|
||||||
|
if(precision != 0) tmp[i++] = '0';
|
||||||
|
type &= ~HEX_PREP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while(num != 0)
|
||||||
|
{
|
||||||
|
uint64_t base = isHex ? 16ULL : 10ULL;
|
||||||
|
tmp[i++] = dig[(uint64_t)num % base];
|
||||||
|
num = (int64_t)((uint64_t)num / base);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & LEFT || precision != -1) type &= ~ZEROPAD;
|
||||||
|
if(type & HEX_PREP && isHex) size -= 2;
|
||||||
|
if(i > precision) precision = i;
|
||||||
|
size -= precision;
|
||||||
|
if(!(type & (ZEROPAD | LEFT))) while(size-- > 0) *str++ = ' ';
|
||||||
|
if(sign) *str++ = sign;
|
||||||
|
|
||||||
|
if(type & HEX_PREP && isHex)
|
||||||
|
{
|
||||||
|
*str++ = '0';
|
||||||
|
*str++ = 'x';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type & ZEROPAD) while(size-- > 0) *str++ = '0';
|
||||||
|
while(i < precision--) *str++ = '0';
|
||||||
|
while(i-- > 0) *str++ = tmp[i];
|
||||||
|
while(size-- > 0) *str++ = ' ';
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
int visprintf(char *buf, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
for(str = buf; *fmt; fmt++)
|
||||||
|
{
|
||||||
|
if(*fmt != '%')
|
||||||
|
{
|
||||||
|
*str++ = *fmt;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Process flags
|
||||||
|
uint32_t flags = 0; //Flags to number()
|
||||||
|
bool loop = true;
|
||||||
|
|
||||||
|
while(loop)
|
||||||
|
{
|
||||||
|
switch(*++fmt)
|
||||||
|
{
|
||||||
|
case '-': flags |= LEFT; break;
|
||||||
|
case '+': flags |= PLUS; break;
|
||||||
|
case ' ': flags |= SPACE; break;
|
||||||
|
case '#': flags |= HEX_PREP; break;
|
||||||
|
case '0': flags |= ZEROPAD; break;
|
||||||
|
default: loop = false; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get field width
|
||||||
|
int32_t fieldWidth = -1; //Width of output field
|
||||||
|
if(IS_DIGIT(*fmt)) fieldWidth = skipAtoi(&fmt);
|
||||||
|
else if(*fmt == '*')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
|
||||||
|
fieldWidth = va_arg(args, int32_t);
|
||||||
|
|
||||||
|
if(fieldWidth < 0)
|
||||||
|
{
|
||||||
|
fieldWidth = -fieldWidth;
|
||||||
|
flags |= LEFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the precision
|
||||||
|
int32_t precision = -1; //Min. # of digits for integers; max number of chars for from string
|
||||||
|
if(*fmt == '.')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
|
||||||
|
if(IS_DIGIT(*fmt)) precision = skipAtoi(&fmt);
|
||||||
|
else if(*fmt == '*')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
precision = va_arg(args, int32_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(precision < 0) precision = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the conversion qualifier
|
||||||
|
uint32_t integerType = 0;
|
||||||
|
if(*fmt == 'l')
|
||||||
|
{
|
||||||
|
if(*++fmt == 'l')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
integerType = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(*fmt == 'h')
|
||||||
|
{
|
||||||
|
if(*++fmt == 'h')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
integerType = 3;
|
||||||
|
}
|
||||||
|
else integerType = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHex;
|
||||||
|
|
||||||
|
switch(*fmt)
|
||||||
|
{
|
||||||
|
case 'c':
|
||||||
|
if(!(flags & LEFT)) while(--fieldWidth > 0) *str++ = ' ';
|
||||||
|
*str++ = (uint8_t)va_arg(args, int32_t);
|
||||||
|
while(--fieldWidth > 0) *str++ = ' ';
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
|
char *s = va_arg(args, char *);
|
||||||
|
if(!s) s = "<NULL>";
|
||||||
|
uint32_t len = (precision != -1) ? strnlen(s, precision) : strlen(s);
|
||||||
|
if(!(flags & LEFT)) while((int32_t)len < fieldWidth--) *str++ = ' ';
|
||||||
|
for(uint32_t i = 0; i < len; i++) *str++ = *s++;
|
||||||
|
while((int32_t)len < fieldWidth--) *str++ = ' ';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'p':
|
||||||
|
if(fieldWidth == -1)
|
||||||
|
{
|
||||||
|
fieldWidth = 8;
|
||||||
|
flags |= ZEROPAD;
|
||||||
|
}
|
||||||
|
str = processNumber(str, va_arg(args, uint32_t), true, fieldWidth, precision, flags);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//Integer number formats - set up the flags and "break"
|
||||||
|
case 'X':
|
||||||
|
flags |= UPPERCASE;
|
||||||
|
//Falls through
|
||||||
|
case 'x':
|
||||||
|
isHex = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
case 'i':
|
||||||
|
flags |= SIGN;
|
||||||
|
//Falls through
|
||||||
|
case 'u':
|
||||||
|
isHex = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if(*fmt != '%') *str++ = '%';
|
||||||
|
if(*fmt) *str++ = *fmt;
|
||||||
|
else fmt--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t num;
|
||||||
|
|
||||||
|
if(flags & SIGN)
|
||||||
|
{
|
||||||
|
if(integerType == 1) num = va_arg(args, int64_t);
|
||||||
|
else num = va_arg(args, int32_t);
|
||||||
|
|
||||||
|
if(integerType == 2) num = (int16_t)num;
|
||||||
|
else if(integerType == 3) num = (int8_t)num;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(integerType == 1) num = va_arg(args, uint64_t);
|
||||||
|
else num = va_arg(args, uint32_t);
|
||||||
|
|
||||||
|
if(integerType == 2) num = (uint16_t)num;
|
||||||
|
else if(integerType == 3) num = (uint8_t)num;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = processNumber(str, num, isHex, fieldWidth, precision, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
*str = 0;
|
||||||
|
return str - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int isprintf(char *buf, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
int res = visprintf(buf, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
return res;
|
||||||
|
}
|
9
exosphere/src/dbg/fmt.h
Normal file
9
exosphere/src/dbg/fmt.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef EXOSPHERE_DBG_FMT_H
|
||||||
|
#define EXOSPHERE_DBG_FMT_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
int visprintf(char *buf, const char *fmt, va_list args);
|
||||||
|
int isprintf(char *buf, const char *fmt, ...);
|
||||||
|
|
||||||
|
#endif
|
47
exosphere/src/dbg/log.c
Normal file
47
exosphere/src/dbg/log.c
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "log.h"
|
||||||
|
#include "log_device_null.h"
|
||||||
|
#include "log_device_uart.h"
|
||||||
|
#include "fmt.h"
|
||||||
|
#include "../synchronization.h"
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
static atomic_flag g_log_lock = ATOMIC_FLAG_INIT;
|
||||||
|
static debug_log_device_t *dev;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void dbg_log_initialize(DebugLogDevice device) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
static debug_log_device_t *const devs[] = {&g_debug_log_device_null.super, &g_debug_log_device_uart.super};
|
||||||
|
dev = device >= DEBUGLOGDEVICE_MAX ? &g_debug_log_device_null.super : devs[device];
|
||||||
|
#else
|
||||||
|
(void)device;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: no bound checks are done */
|
||||||
|
void dbg_log_write(const char *fmt, ...) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
char buf[DBG_LOG_BUF_SIZE];
|
||||||
|
int len;
|
||||||
|
va_list args;
|
||||||
|
lock_acquire(&g_log_lock);
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
len = visprintf(buf, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
dev->write_string(dev, buf, len);
|
||||||
|
lock_release(&g_log_lock);
|
||||||
|
#else
|
||||||
|
(void)fmt;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void dbg_log_finalize(void) {
|
||||||
|
#ifndef NDEBUG
|
||||||
|
dev->finalize(dev);
|
||||||
|
dev = NULL;
|
||||||
|
#endif
|
||||||
|
}
|
25
exosphere/src/dbg/log.h
Normal file
25
exosphere/src/dbg/log.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef EXOSPHERE_DBG_LOG_H
|
||||||
|
#define EXOSPHERE_DBG_LOG_H
|
||||||
|
|
||||||
|
#include "../utils.h"
|
||||||
|
|
||||||
|
#define DBG_LOG_BUF_SIZE 256
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DEBUGLOGDEVICE_NULL = 0,
|
||||||
|
DEBUGLOGDEVICE_UART = 1,
|
||||||
|
|
||||||
|
DEBUGLOGDEVICE_MAX = 2,
|
||||||
|
} DebugLogDevice;
|
||||||
|
|
||||||
|
typedef struct debug_log_device_t {
|
||||||
|
void (*initialize)(struct debug_log_device_t *this, ...);
|
||||||
|
void (*write_string)(struct debug_log_device_t *this, const char *str, size_t len);
|
||||||
|
void (*finalize)(struct debug_log_device_t *this);
|
||||||
|
} debug_log_device_t;
|
||||||
|
|
||||||
|
void dbg_log_initialize(DebugLogDevice device);
|
||||||
|
void dbg_log_write(const char *fmt, ...);
|
||||||
|
void dbg_log_finalize(void);
|
||||||
|
|
||||||
|
#endif
|
26
exosphere/src/dbg/log_device_null.c
Normal file
26
exosphere/src/dbg/log_device_null.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#include "log_device_null.h"
|
||||||
|
|
||||||
|
static void initialize(debug_log_device_null_t *this) {
|
||||||
|
(void)this;
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_string(debug_log_device_null_t *this, const char *str, size_t len) {
|
||||||
|
(void)this;
|
||||||
|
(void)str;
|
||||||
|
(void)len;
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void finalize(debug_log_device_null_t *this) {
|
||||||
|
(void)this;
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_log_device_null_t g_debug_log_device_null = {
|
||||||
|
.super = {
|
||||||
|
.initialize = (void (*)(debug_log_device_t *, ...))initialize,
|
||||||
|
.write_string = (void (*)(debug_log_device_t *, const char *, size_t))write_string,
|
||||||
|
.finalize = (void (*)(debug_log_device_t *))finalize,
|
||||||
|
},
|
||||||
|
};
|
13
exosphere/src/dbg/log_device_null.h
Normal file
13
exosphere/src/dbg/log_device_null.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef EXOSPHERE_DBG_LOG_DEVICE_NULL_H
|
||||||
|
#define EXOSPHERE_DBG_LOG_DEVICE_NULL_H
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
debug_log_device_t super;
|
||||||
|
/* Additonnal attributes go here */
|
||||||
|
} debug_log_device_null_t;
|
||||||
|
|
||||||
|
extern debug_log_device_null_t g_debug_log_device_null;
|
||||||
|
|
||||||
|
#endif
|
30
exosphere/src/dbg/log_device_uart.c
Normal file
30
exosphere/src/dbg/log_device_uart.c
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#include "log_device_uart.h"
|
||||||
|
#include "../car.h"
|
||||||
|
#include "../uart.h"
|
||||||
|
|
||||||
|
static void initialize(debug_log_device_uart_t *this) {
|
||||||
|
if (!this->is_initialized) {
|
||||||
|
uart_select(0); /* UART-A */
|
||||||
|
clkrst_enable(CARDEVICE_UARTA);
|
||||||
|
uart_initialize(0 /* I don't know */);
|
||||||
|
this->is_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_string(debug_log_device_uart_t *this, const char *str, size_t len) {
|
||||||
|
(void)this;
|
||||||
|
(void)len;
|
||||||
|
uart_transmit_str(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void finalize(debug_log_device_uart_t *this) {
|
||||||
|
clkrst_disable(CARDEVICE_UARTA);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_log_device_uart_t g_debug_log_device_uart = {
|
||||||
|
.super = {
|
||||||
|
.initialize = (void (*)(debug_log_device_t *, ...))initialize,
|
||||||
|
.write_string = (void (*)(debug_log_device_t *, const char *, size_t))write_string,
|
||||||
|
.finalize = (void (*)(debug_log_device_t *))finalize,
|
||||||
|
},
|
||||||
|
};
|
13
exosphere/src/dbg/log_device_uart.h
Normal file
13
exosphere/src/dbg/log_device_uart.h
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef EXOSPHERE_DBG_LOG_DEVICE_UART_H
|
||||||
|
#define EXOSPHERE_DBG_LOG_DEVICE_UART_H
|
||||||
|
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
debug_log_device_t super;
|
||||||
|
bool is_initialized;
|
||||||
|
} debug_log_device_uart_t;
|
||||||
|
|
||||||
|
extern debug_log_device_uart_t g_debug_log_device_uart;
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,4 +19,9 @@
|
||||||
#define PINMUX_AUX_GEN1_I2C_SCL_0 MAKE_MISC_REG(0x30BC)
|
#define PINMUX_AUX_GEN1_I2C_SCL_0 MAKE_MISC_REG(0x30BC)
|
||||||
#define PINMUX_AUX_GEN1_I2C_SDA_0 MAKE_MISC_REG(0x30C0)
|
#define PINMUX_AUX_GEN1_I2C_SDA_0 MAKE_MISC_REG(0x30C0)
|
||||||
|
|
||||||
|
#define PINMUX_AUX_UARTn_TX_0(n) MAKE_MISC_REG(0x30E4 + 0x10 * (n))
|
||||||
|
#define PINMUX_AUX_UARTn_RX_0(n) MAKE_MISC_REG(0x30E8 + 0x10 * (n))
|
||||||
|
#define PINMUX_AUX_UARTn_RTS_0(n) MAKE_MISC_REG(0x30EC + 0x10 * (n))
|
||||||
|
#define PINMUX_AUX_UARTn_CTS_0(n) MAKE_MISC_REG(0x30F0 + 0x10 * (n))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -241,13 +241,13 @@ uint32_t smc_wrapper_async(smc_args_t *args, uint32_t (*handler)(smc_args_t *),
|
||||||
|
|
||||||
uint32_t smc_set_config(smc_args_t *args) {
|
uint32_t smc_set_config(smc_args_t *args) {
|
||||||
/* Actual value presumed in X3 on hardware. */
|
/* Actual value presumed in X3 on hardware. */
|
||||||
return configitem_set((enum ConfigItem)args->X[1], args->X[3]);
|
return configitem_set((ConfigItem)args->X[1], args->X[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t smc_get_config(smc_args_t *args) {
|
uint32_t smc_get_config(smc_args_t *args) {
|
||||||
uint64_t out_item = 0;
|
uint64_t out_item = 0;
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
result = configitem_get((enum ConfigItem)args->X[1], &out_item);
|
result = configitem_get((ConfigItem)args->X[1], &out_item);
|
||||||
args->X[1] = out_item;
|
args->X[1] = out_item;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,14 @@
|
||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
|
void uart_select(unsigned int id) {
|
||||||
|
/* This confirmation is valid for UART-A, I don't know about the other UARTs. */
|
||||||
|
/* Official Nintendo code (for UART-A, at least) */
|
||||||
|
PINMUX_AUX_UARTn_TX_0(id) = 0; /* UART */
|
||||||
|
PINMUX_AUX_UARTn_RX_0(id) = 0x48; /* UART, enable, pull up */
|
||||||
|
PINMUX_AUX_UARTn_RTS_0(id) = 0; /* UART */
|
||||||
|
PINMUX_AUX_UARTn_CTS_0(id) = 0x44; /* UART, enable, pull down */
|
||||||
|
}
|
||||||
|
|
||||||
void uart_initialize(uint16_t divider) {
|
void uart_initialize(uint16_t divider) {
|
||||||
/* Setup UART in 16450 mode. We assume the relevant UART clock has been enabled. */
|
/* Setup UART in 16450 mode. We assume the relevant UART clock has been enabled. */
|
||||||
|
|
|
@ -20,6 +20,7 @@ static inline uintptr_t get_uarta_base(void) {
|
||||||
#define UART_LCR_0 MAKE_REG32(UARTA_BASE + 0xC)
|
#define UART_LCR_0 MAKE_REG32(UARTA_BASE + 0xC)
|
||||||
#define UART_LSR_0 MAKE_REG32(UARTA_BASE + 0x14)
|
#define UART_LSR_0 MAKE_REG32(UARTA_BASE + 0x14)
|
||||||
|
|
||||||
|
void uart_select(unsigned int id);
|
||||||
void uart_initialize(uint16_t divider);
|
void uart_initialize(uint16_t divider);
|
||||||
void uart_transmit_char(char ch);
|
void uart_transmit_char(char ch);
|
||||||
void uart_transmit_str(const char *str);
|
void uart_transmit_str(const char *str);
|
||||||
|
|
Loading…
Reference in a new issue