Giter VIP home page Giter VIP logo

ps2sdk's Introduction

ps2dev

GitHub Workflow StatusGitHub Workflow StatusDocker Pulls

Main PS2 Repo for building the whole PS2 Development environment in your local machine.

This program will automatically build and install the whole compiler and other tools used in the creation of homebrew software for the Sony PlayStation® 2 videogame system.

What these scripts do

These scripts download (git clone) and install:

Requirements

  1. Install gcc/clang, make, cmake, patch, git, texinfo, flex, bison, gettext, wget, gsl, gmp, zlib, mpfr and mpc if you don't have those packages.
  • Ubuntu
sudo apt -y install gcc g++ make cmake patch git texinfo flex bison gettext libgsl-dev libgmp3-dev libmpfr-dev libmpc-dev zlib1g-dev
  • Fedora/CentOS
sudo dnf -y install gcc make cmake patch git texinfo flex bison gettext gmp-devel mpfr-devel libmpc-devel zlib-devel
  • Alpine
apk add build-base cmake git texinfo flex bison gettext gmp-dev mpfr-dev mpc1-dev zlib-dev
  1. Optional. If you are upgrading from the previous version of the PS2DEV environment, it is highly recommended to remove the content of the PS2DEV folder before upgrade. This is a necessary step after the major toolchain upgrade.
sudo rm -rf $PS2DEV
  1. Ensure that you have enough permissions for managing PS2DEV location (which defaults to /usr/local/ps2dev, but you can use a different path). PS2DEV location MUST NOT have spaces or special characters in its path! PS2DEV should be an absolute path. On Unix systems, if the command mkdir -p $PS2DEV fails for you, you can set access for the current user by running commands:
export PS2DEV=/usr/local/ps2dev
sudo mkdir -p $PS2DEV
sudo chown -R $USER: $PS2DEV
  1. Add this to your login script (example: ~/.bash_profile) Note: Ensure that you have full access to the PS2DEV path. You can change the PS2DEV path with the following requirements: only use absolute paths, don't use spaces, only use Latin characters.
export PS2DEV=/usr/local/ps2dev
export PS2SDK=$PS2DEV/ps2sdk
export GSKIT=$PS2DEV/gsKit
export PATH=$PATH:$PS2DEV/bin:$PS2DEV/ee/bin:$PS2DEV/iop/bin:$PS2DEV/dvp/bin:$PS2SDK/bin
  1. Run build-all.sh
./build-all.sh

Docker generation

This repo also uses CI/CD to create a docker image called ps2dev/ps2dev:latest per change. This is useful if you're a developer that wants to create/port an application to the PS2. You can compile your project using this docker image.

Extra steps

If you want, you can JUST install the extra dependencies ps2client and ps2-packer. To achieve this, execute the following:

./build-extra.sh

macOS

If you download the pre-built macOS binaries and get a security error such as "ps2client" cannot be opened because the developer cannot be verified., you can remove the quarantine attribute by running:

xattr -dr com.apple.quarantine path/to/prebuilt/ps2toolchain

Thanks

ps2sdk's People

Contributors

ajenbo avatar akuhak avatar asmblur avatar boganon avatar drakonite avatar emoon avatar f0bes avatar fjtrujy avatar gmegidish avatar h4570 avatar israpps avatar jbit avatar jimmikaelkael avatar joseaaronlopezgarcia avatar kdaham avatar lukaszdk avatar marcusrbrown avatar mlafeldt avatar nicolasnoble avatar oobles avatar oopo avatar qnox32 avatar rickgaiser avatar sp193 avatar t0mb0la avatar tyranid avatar uyjulian avatar x0rloser avatar zappepappe avatar ziemas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ps2sdk's Issues

ee/mpeg broken since gcc10

ee/mpeg last compiled with the gcc 3.2.3 toolchain. The assembly files are problematic and have not been ported to gcc10. Decompressing mpeg2 streams is one of the great features the ps2 hardware has to offer, so it would be great if this could be ported or re-written to be compatible with the new toolchain.

sio_printf broken since newlib

The old sio_printf function depends on vsnprintf from libc/newlib, making it too big to use for ELF's that need to be small. For this reason, sio_printf has been removed in a744144.

A more flexible solution would be to redirect the output of printf to different 'write' functions, to be called from here:

int _write(int fd, const void *buf, size_t nbytes) {
// HACK: stdout and strerr to serial
//if ((fd==1) || (fd==2))
// return sio_write((void *)buf, nbytes);
return _ps2sdk_write(fd, buf, nbytes);
}

An interface could look like:

libc_set_stdout(sio_write); // output redirected to EE SIO
libc_set_stdout(_ps2sdk_write); // output redirected to IOP (default)
libc_set_stdout(custom_stdout); // custom function that redirects to a file, or something else...

The idea is to give an application control over where the stdout will go to.

Smap needs memcpy on modern toolchains

It seems the modern gcc is optimising stuff on its own so smap needs memcpy to be included. Referring to this commit 4c19331 it seems that it is safe to remove -Os flag, but i am not sure.

mipsel-ps2-irx-gcc -D_IOP -fno-builtin -Os -G0 -Wall -I/work/iop/dev9/dev9/include -Isrc/ -Isrc/include -Iinclude/ -I/work/iop/kernel/include -I/work/common/include -mgpopt -G16384 -mno-check-zero-division -DLWIP_DHCP=1 -msoft-float -mno-explicit-relocs -o irx/smap.irx obj/main.o obj/smap.o obj/xfer.o obj/imports.o obj/exports.o -nostdlib -s  
/usr/local/ps2dev/iop/lib/gcc/mipsel-ps2-irx/8.2.0/../../../../mipsel-ps2-irx/bin/ld: obj/smap.o: in function `SMAPIoctl':
(.text+0x1a3c): undefined reference to `memcpy'

UDP does not work from PS2IP-EE when MEM_ALIGNMENT = 64

I think this is an old issue, just that I never encountered it on the EE-side port in a while due to not ever having the projects that use UDP.

As of now, sending UDP datagrams will result in some garbled output or not output at all, across the wire. I've seen a garbled frame get parsed by Wireshark as only having a valid Ethernet II component.

This seems to go away if MEM_ALIGNMENT is set to 4 (as on the IOP), but with the usual performance penalties.

Request for tutorials, how-to's, IDE's/Engines and simple projects for start developing

I told on the on the ps2dev/ps2dev repo:

There is a VERY HUGE LACK of tutorials and HOWTO's in the internet about how to develop even a simple "hello world" program/elf for PS2.
We need to change that too.
We also need Graphic/Programming Engines such as RenderWare for helping develop PS2 Homebrews. I saw someone created an open source reimplementation of renderware engine btw (https://github.com/aap/librw).

Can this issue be open for links, PDF's, docs, tutorials and projects links?

Strange behavior in remove() and unlink()

Hi,

I am having a strange behavior when deleting a file from memory card. I open, create files, read and write them, etc... But when i try to delete any file, the file is deleted but a folder with same name is created (!).

In my code:

    remove("mc0:BARULAND/08040336.PNG");

In PCSX2 log, i get:

    remove file mc0:BARULAND/08040336.PNG
    mkdir name mc0:BARULAND/08040336.PNG 

It happen both in a real PS2 and in PCSX2, both using unlink() and remove(), what make me believe is a problem in stdlib. I looked in ps2dev/libs/ps2sdk/iop/system/iomanx/src/iomanX.c, trying to find a missing break in a switch/case or the like, but found nothing.

Anybody had noticed anything similar?

Handling interface selection within USBHDFSD correctly

As of commit d443c15 on June 8th, some devices have become incompatible with USBHDFSD due to usb_set_interface becoming a mandatory step. This also implies that the Set Interface step never succeeds on some devices. Rolling back is the easy way out, but it seems like calling Set Interface was not even the correct thing to do in the first place.

By following the Linux source code, the USB Mass Storage class specification and the USB 2.0 specification (The related clauses should be similar), I have arrived at these conclusions:

  • By 9.4.10 of the USB 2.0 spec, a device may STALL if only one configuration is supported.
  • By 9.6.5 of the USB 2.0 spec and 4.3 of the USB Mass Storage class spec documents, a device may implement multiple interfaces, of which there may be multiple alternate configurations. Alternate interface 0 is the default. The driver is supposed to iterate through all interface descriptors and pick the best fit.
  • There was nothing that stated that the bulk-only data interface (used for the USB Mass Storage class) will be the first in a composite device.
  • If the device stalls the pipe when Set Interface is done, then Linux will issue CLEAR HALT on the pipes of the alternate interface.
  • By the USB Mass Storage class spec, there seems to not be a case where there will be alternate interfaces, so we can avoid calling Set Interface entirely. Linux does not seem to use Set Interface on USB Mass Storage devices.

Since USBHDFSD does not actually scan through all interface descriptors, it does not actually support composite devices. The only composite devices that will work with this, will be those that have the bulk-only data interface as the first interface.

So I see that we have two choices:

  • Complete support for composite devices. This means adding code that will scan through all the interface descriptors. Select the appropriate interface during the connect() step.
  • Officially drop support for composite devices. Assume that only USB Mass Storage devices will be used, whereby they only have one interface.

As I have no composite devices, I plan to just cut off the broken support for them.
Also in case I am wrong about any of the points I have gathered so far, I have opened this issue ticket for discussion.

SMB Version 1 deprecation / upgrade to SMB Version 2

Hey, figured I ought to get into PS2 development after using homebrew for quite some time and developing for other stuff but not PlayStation 2. I've noticed many threads and questions floating about the internet regarding Open PS2 Loader and other PS2 homebrew applications that are still dependent on SMB version 1, which has been phased out and removed from operating systems such as new builds of Windows 10, Windows Server, and various *nix OSes.

These OSes are using implementations of SMB versions 2/3, so I'm wondering how difficult it would be to get at least SMB v2 working on the PS2, in terms of both coding difficulty, compatibility with the IOP and what performance cost (if any) there would be

I don't mind helping out where I can, I'm new to PS2 development but not new to programming (C++, C# and others) :)

CEX/DEX Alarm Functions are not fully functional

The alarm-managment functions on the CEX/DEX PlayStation 2 are not totally functional. The largest problem seems to be with ReleaseAlarm being unable to correctly release the right alarm.

SCEI appears to have made a patch that totally replaces the 5 syscalls (05, SetAlarm, iSetAlarm, ReleaseAlarm, iReleaseAlarm) involved, but leaves the original implementation behind for backward-compatibility with old programs that use them.

USBHDFSD - potential cache coherency bug when adding/renaming files

USBHDFSD has a sector cache, which covers the whole disk in units of 4096-byte blocks. This is aligned with the start of the disk and has no relationship with any filesystem on the disk.

As such, if the code allocates a block before writing without reading the old content, it is perhaps possible for the remainder of the block to become lost.

For example:
| CLUSTER 1 | CLUSTER 2|...
..| BLK1 | BLK2 | BLK3 |....

Where CLUSTER 1 and CLUSTER 2 are logical clusters in a filesystem, while BLK1, BLK2 and BLK3 are the blocks within the cache. The clusters are larger (for example, 32KB each) than the blocks (4KB each). The blocks are not aligned with the clusters (perhaps because there is 1KB alignment).

The software decides to allocate cluster 2, whose corresponding cache block contains some sectors that belongs to cluster 1. As the block is allocated and the old data being totally discarded, some of the sectors that belong to cluster 1 are lost.

The affected lines within fat_write.c concern direntry manipulation, so the user may observe corruption of FAT when:

  • The cluster size is not a multiple of the block size. Or the clusters are not aligned with the blocks.
  • Files or directories are added or renamed.
  • The cluster that the direntry being updated exists in the middle of a cache block, which is shared with the adjacent cluster.

Line 1274: https://github.com/ps2dev/ps2sdk/blob/master/iop/usb/usbhdfsd/src/fat_write.c#L1274
Line 1308: https://github.com/ps2dev/ps2sdk/blob/master/iop/usb/usbhdfsd/src/fat_write.c#L1308

Personally, I have made a similar mistake before in 2014, which occasionally resulted in corruption when data is written: a9494c2#diff-ba7f9373100b558565bd2d05edac0ee8
So I do think it is a plausible design flaw within the FAT driver.

I shall make a branch and offer a prototype, for more individuals to test with.

EDIT:
Custom USBHDFSD module that does not use scache_allocSector in fat_write.c: https://www.sendspace.com/file/blz5os
Branch: https://github.com/sp193/ps2sdk/tree/usbhdfsd-scache-noalloc

One can test whether it is an improvement, by copying usbhdfsd-noscachealloc.irx as USBHDFSD.IRX, and to get LaunchELF to use it.

Cannot build

I get this message right after libkernel is built:

make[2]: Leaving directory '/run/media/hgdagon/Gateway/ps2toolchain/build/ps2sdk/ee/libc'
make[2]: Leaving directory '/run/media/hgdagon/Gateway/ps2toolchain/build/ps2sdk/ee/kernel'
make[2]: Leaving directory '/run/media/hgdagon/Gateway/ps2toolchain/build/ps2sdk/ee/kernel-nopatch'
make[1]: Leaving directory '/run/media/hgdagon/Gateway/ps2toolchain/build/ps2sdk/ee'
make: *** [Makefile:31: all-ee] Error 2
../scripts/005-ps2sdk.sh: Failed.
ERROR: Could not run the toolchain script.

The problem is I don't even know what failed. I'm running latest Manjaro.

I'm newbie on PS2 SDK, please just one help to install it.

Hello everyone, I need to ask you one boring question for you :), but I'm new on PS2 SDK; so to install/prepare this SDK I need to download the main git source files and then into the main source folder to use make and make install ? Or this SDK to working I need to set in different way?

Heap allocation functions - are they really thread-safe as documented?

Hi all,

For a really long time, I have been asking myself this question: are the heap allocation functions (AllocSysMemory and FreeSysMemory) thread-safe?

As of the Sony SDK v3.0.2, the documentation for AllocSysMemory states that it is multi-thread safe, does not depend on whether interrupts are disabled or enabled. However, it was documented to not support being called from the interrupt context.

But from disassembling these functions myself and referring to the code from the FPS2BIOS project, it appears that the AllocSysMemory and FreeSysMemory functions have no inter-task protection. This design seemed to be the same, from the old SDK 1.3.4 release (i.e. our boot ROM's version of SYSMEM) to the one from IOPRP310 (SDK 3.1.0).

The Sony developers didn't seem to all agree with each other too. Some of them just called AllocSysMemory() and FreeSysMemory() without suspending interrupts, while some others suspend interrupts before calling these functions.
Early versions of USBD do not suspend interrupts before calling these functions, but interrupts are first suspended in later versions.
In the HDD modules (HDD.IRX and PFS.IRX), interrupts were always suspended before calling these functions.
In modules like FILEIO, AllocSysMemory is always called without suspending interrupts.

I've long forgotten if I ever got any issues from using these functions without suspending interrupts, but I have been suspending interrupts in my code before I use any of them.

Fixing static declaration error

Modern toolchain produces this error - it seems that both declarations should be static or vice-versa - both non-static.

make -C tcpips
make[3]: Entering directory '/work/ee/rpc/tcpips'
mkdir -p obj/
mips64r5900el-ps2-elf-gcc -D_EE -G0 -O2 -Wall  -Isrc/ -Isrc/include -Iinclude/ -I/work/ee/kernel/include -I/work/common/include -I/work/ee/libc/include -I/work/ee/erl/include -DPS2IP_DNS -c src/ps2ipc.c -o obj/ps2ipc.o
src/ps2ipc.c:58:24: error: static declaration of 'ip_addr_any' follows non-static declaration
 static const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY);
                        ^~~~~~~~~~~
In file included from include/ps2ips.h:19,
                 from src/ps2ipc.c:21:
/work/common/include/tcpip.h:834:24: note: previous declaration of 'ip_addr_any' was here
 extern const ip_addr_t ip_addr_any;
                        ^~~~~~~~~~~

IOP export table declaration causes relocation truncated warning when mgpopt is enabled

As of commit 587cad4, these macros have been added to defs.h, to allow the programmer to manipulate the $gp register when required:

  • SetGP
    -GetGP
    -ReplaceGP
    -SetModuleGP

USBD will now use $gp, and also supports restoring the driver & caller's $gp. This was a documented function of USBD, which our homebrew module was lacking.

However, the G parameter is currently set to 19. I found that I couldn't increase it, as with the SMAP module.
Going beyond 19 would result in a linker error like this:

obj/usbd.o(.text+0x700): In function `_start':
src/usbd.c: relocation truncated to fit: R_MIPS_GPREL16 _exp_usbd
collect2: ld returned 1 exit status

I think it might have something to do with the definition of the export table, which has the fptrs field defined as an zero-length array at +0x14 (20th byte mark).
Removing the declaration of the _exp_usbd structure and its corresponding call to RegisterLibraryEntries will inhibit the warning, even if I increased the G-parameter to as high as 8192.

And so I think it might have got to do with the undefined size of fptrs, but I am not well-versed with the GCC/LD internals.

For now, I have a patch that replaces the use of struct irx_export_table with iop_libhead_t, which represents the export table after linking: https://github.com/sp193/ps2sdk/tree/libhead
Since it does not define the export table body (fptrs), it results in no linker error.
Other than solving this problem, it also represents the import and export tables after linking (rather than their forms before linking). So these new structures can be used together with the ones in irx.h for complete representation of the import and export tables.

The only bad thing about doing this, is that there will be warnings in older projects, but I guess that is a small price to pay.

Does anybody have any comments or a better way to solve this?

mcRead() gives me sceMcResDeniedPermit

Whenever I try to read anything from a file I've successfully opened as read only with mcOpen() I always get -5 (sceMcResDeniedPermit). I'm not even quite sure what this error means let alone what causes it so I'd appreciate any pointers.

chdir() is broken

When the change was made for newlib to replace the existing libc implementation, it looks like the logic to use the current working directory set by chdir() has been lost. Previously if you called fopen("abc", "r") it would automatically set this to an absolute path based in wherever the current working directory is (which is the directory where the ELF was launched from by default, thanks to _ps2sdk_args_parse()). Now this function will try to open abc as if it were an absolute path, which isn't correct.

Observe the old fopen() function here where it uses __direct_pwd to create an absolute path if a relative path is provided. __direct_pwd still exists in ps2sdkapi.c but it doesn't seem to be used anywhere else.

I suspect the path-building logic will need to be copied from the old fopen() function into a new function, then ps2sdkapi.c and fileXio_rpc.c will need to be updated to call this function before calling fioOpen() and fileXioOpen(), respectively.

Built-in compatibility with loader-like/resident projects - do we want it?

Sometime ago, I copied and implemented a version of the SCE alarm functions patch, as well as completed the patch for the TLB functions.
This brings us to having the following EE kernel patches:

  • alarm (SetAlarm, ReleaseAlarm, iSetAlarm, iReleaseAlarm)

  • thread (iWakeupThread, iSuspendThread, iRotateThreadReadyQueue)

  • TLB (All TLB functions + ExecPS2, LoadExecPS2, Exit, ExecOSD)

  • libosd (ExecPS2 and OSD config functions), for the SCPH-10000 and SCPH-15000.

However, I realize that the TLB patches and thread function patches in particular do make the building and maintenance of loader-like/resident projects difficult (other than some problems with linking, the thread patch is always linked to because of SIFRPC). Right now, my solution for OPL and FMCB is:

  1. Use a custom crt0 module that does not apply any of the patches and calls _Exit instead of Exit (to avoid linking to the dysfunctional patch).
  2. Do not call any of the patched functions, but use their originals (i.e. instead of ExecPS2, call _ExecPS2).
  3. Provide a iWakeupThread object that defines the original iWakeupThread syscall as an object, to override the one that is supplied by thread.o.
  4. For (3), provide a part of kernel.S.

So it feels rather hackish and I am not sure whether things are getting too confusing for other developers who don't dive as deep as I do into the bowels of the EE kernel...

I believe that SCEI kept things working by using specific SDKs for their patches. For example, the SDK for our browsers has always maintained the old module design, so it should technically be SDK v1.x.

Most EELOAD programs (includes the ones from the system driver update) do not have signs of being compiled with a late SDK version.
Only the HDD MBR programs seem to be compiled with a later version, which already has a version of the TLB function patches.

So what I am proposing to do (which is also already in the works) is:

  • Modify kernel.S to allow a syscall to be optionally defined to have a different symbol name from its definition (so I can define ExecPS2.o to use __NR__ExecPS2, for example).
  • Create a compile-time Makefile option (KERNEL_NO_PATCHES) that will define KERNEL_NO_PATCHES = 1, which defines that all patches will not be linked to, and the _InitSys (called by crt0 before main is invoked) and TerminateLibrary (called by crt0 when main returns) functions do not link to the patch either.

If anyone has any objections or a better suggestion, please feel free to write about it here!

This will still mean that the syscall number definitions will not be backward-compatible, but at least the objects will be backward-compatible if libkernel-nopatch is used. As the unpatched EE syscalls will be used, the developer will also have to be mindful of their problems.


The TLB function patch may not be only for the sake of allowing the developer to manipulate the TLB. I believe that it's also for supporting the PSX, if/when the kernel's memory mode is switched. Otherwise, the kernel will fault within ExecPS2 when it tries to copy arguments.

Documenting the SDK and updating the readme

PS2SDK has so many awesome features and modules. But rarely any module contains a short description on what it even does or how to use it.
So please currently active devs, add a small description to the module you are working on and it will be much easier for people interest in using it to actually understand what it does.
In addition it would be awesome if the Readme could hold a list of all available modules right now.

But none the less, thank you so much for all the effort you have put into the project over the past 15 years!

I found out how to do the socket programming where should I put the PR for an example

/*
# _____     ___ ____     ___ ____
#  ____|   |    ____|   |        | |____|
# |     ___|   |____ ___|    ____| |    \    PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
#
*/

#include <stdio.h>
#include <kernel.h>
#include <iopcontrol.h>
#include <iopheap.h>
#include <debug.h>
#include <netman.h>
#include <ps2ip.h>
#include <sifrpc.h>
#include <loadfile.h>
#include <sbv_patches.h>
#include <string.h>

extern unsigned char DEV9_irx[];
extern unsigned int size_DEV9_irx;

extern unsigned char SMAP_irx[];
extern unsigned int size_SMAP_irx;

extern unsigned char NETMAN_irx[];
extern unsigned int size_NETMAN_irx;

static int ethApplyNetIFConfig(int mode)
{
	int result;
	//By default, auto-negotiation is used.
	static int CurrentMode = NETMAN_NETIF_ETH_LINK_MODE_AUTO;

	if(CurrentMode != mode)
	{	//Change the setting, only if different.
		if((result = NetManSetLinkMode(mode)) == 0)
			CurrentMode = mode;
	}else
		result = 0;

	return result;
}

static void EthStatusCheckCb(s32 alarm_id, u16 time, void *common)
{
	iWakeupThread(*(int*)common);
}

static int WaitValidNetState(int (*checkingFunction)(void))
{
	int ThreadID, retry_cycles;

	// Wait for a valid network status;
	ThreadID = GetThreadId();
	for(retry_cycles = 0; checkingFunction() == 0; retry_cycles++)
	{	//Sleep for 1000ms.
		SetAlarm(1000 * 16, &EthStatusCheckCb, &ThreadID);
		SleepThread();

		if(retry_cycles >= 10)	//10s = 10*1000ms
			return -1;
	}

	return 0;
}

static int ethGetNetIFLinkStatus(void)
{
	return(NetManIoctl(NETMAN_NETIF_IOCTL_GET_LINK_STATUS, NULL, 0, NULL, 0) == NETMAN_NETIF_ETH_LINK_STATE_UP);
}

static int ethWaitValidNetIFLinkState(void)
{
	return WaitValidNetState(&ethGetNetIFLinkStatus);
}

static int ethApplyIPConfig(int use_dhcp, const struct ip4_addr *ip, const struct ip4_addr *netmask, const struct ip4_addr *gateway, const struct ip4_addr *dns)
{
	t_ip_info ip_info;
	const ip_addr_t *dns_curr;
	int result;

	//SMAP is registered as the "sm0" device to the TCP/IP stack.
	if ((result = ps2ip_getconfig("sm0", &ip_info)) >= 0)
	{
		//Obtain the current DNS server settings.
		dns_curr = dns_getserver(0);

		//Check if it's the same. Otherwise, apply the new configuration.
		if ((use_dhcp != ip_info.dhcp_enabled)
		    ||	(!use_dhcp &&
			 (!ip_addr_cmp(ip, (struct ip4_addr *)&ip_info.ipaddr) ||
			 !ip_addr_cmp(netmask, (struct ip4_addr *)&ip_info.netmask) ||
			 !ip_addr_cmp(gateway, (struct ip4_addr *)&ip_info.gw) ||
			 !ip_addr_cmp(dns, dns_curr))))
		{
			if (use_dhcp)
			{
				ip_info.dhcp_enabled = 1;
			}
			else
			{	//Copy over new settings if DHCP is not used.
				ip_addr_set((struct ip4_addr *)&ip_info.ipaddr, ip);
				ip_addr_set((struct ip4_addr *)&ip_info.netmask, netmask);
				ip_addr_set((struct ip4_addr *)&ip_info.gw, gateway);

				ip_info.dhcp_enabled = 0;
			}

			//Update settings.
			result = ps2ip_setconfig(&ip_info);
			if (!use_dhcp)
				dns_setserver(0, dns);
		}
		else
			result = 0;
	}

	return result;
}

static void ethPrintIPConfig(void)
{
	t_ip_info ip_info;
	const ip_addr_t *dns_curr;
	u8 ip_address[4], netmask[4], gateway[4], dns[4];

	//SMAP is registered as the "sm0" device to the TCP/IP stack.
	if (ps2ip_getconfig("sm0", &ip_info) >= 0)
	{
		//Obtain the current DNS server settings.
		dns_curr = dns_getserver(0);

		ip_address[0] = ip4_addr1((struct ip4_addr *)&ip_info.ipaddr);
		ip_address[1] = ip4_addr2((struct ip4_addr *)&ip_info.ipaddr);
		ip_address[2] = ip4_addr3((struct ip4_addr *)&ip_info.ipaddr);
		ip_address[3] = ip4_addr4((struct ip4_addr *)&ip_info.ipaddr);

		netmask[0] = ip4_addr1((struct ip4_addr *)&ip_info.netmask);
		netmask[1] = ip4_addr2((struct ip4_addr *)&ip_info.netmask);
		netmask[2] = ip4_addr3((struct ip4_addr *)&ip_info.netmask);
		netmask[3] = ip4_addr4((struct ip4_addr *)&ip_info.netmask);

		gateway[0] = ip4_addr1((struct ip4_addr *)&ip_info.gw);
		gateway[1] = ip4_addr2((struct ip4_addr *)&ip_info.gw);
		gateway[2] = ip4_addr3((struct ip4_addr *)&ip_info.gw);
		gateway[3] = ip4_addr4((struct ip4_addr *)&ip_info.gw);

		dns[0] = ip4_addr1(dns_curr);
		dns[1] = ip4_addr2(dns_curr);
		dns[2] = ip4_addr3(dns_curr);
		dns[3] = ip4_addr4(dns_curr);

		scr_printf(	"IP:\t%d.%d.%d.%d\n"
				"NM:\t%d.%d.%d.%d\n"
				"GW:\t%d.%d.%d.%d\n"
				"DNS:\t%d.%d.%d.%d\n",
					ip_address[0], ip_address[1], ip_address[2], ip_address[3],
					netmask[0], netmask[1], netmask[2], netmask[3],
					gateway[0], gateway[1], gateway[2], gateway[3],
					dns[0], dns[1], dns[2], dns[3]);

		scr_printf("I ran!\n");
	}
	else
	{
		scr_printf("Unable to read IP address.\n");
	}
}

static void ethPrintLinkStatus(void)
{
	int mode, baseMode;

	//SMAP is registered as the "sm0" device to the TCP/IP stack.
	scr_printf("Link:\t");
	if (NetManIoctl(NETMAN_NETIF_IOCTL_GET_LINK_STATUS, NULL, 0, NULL, 0) == NETMAN_NETIF_ETH_LINK_STATE_UP)
		scr_printf("Up\n");
	else
		scr_printf("Down\n");

	scr_printf("Mode:\t");
	mode = NetManIoctl(NETMAN_NETIF_IOCTL_ETH_GET_LINK_MODE, NULL, 0, NULL, 0);

	//NETMAN_NETIF_ETH_LINK_MODE_PAUSE is a flag, so file it off first.
	baseMode = mode & (~NETMAN_NETIF_ETH_LINK_DISABLE_PAUSE);
	switch(baseMode)
	{
		case NETMAN_NETIF_ETH_LINK_MODE_10M_HDX:
			scr_printf("10M HDX");
			break;
		case NETMAN_NETIF_ETH_LINK_MODE_10M_FDX:
			scr_printf("10M FDX");
			break;
		case NETMAN_NETIF_ETH_LINK_MODE_100M_HDX:
			scr_printf("100M HDX");
			break;
		case NETMAN_NETIF_ETH_LINK_MODE_100M_FDX:
			scr_printf("100M FDX");
			break;
		default:
			scr_printf("Unknown");
	}
	if(!(mode & NETMAN_NETIF_ETH_LINK_DISABLE_PAUSE))
		scr_printf(" with ");
	else
		scr_printf(" without ");
	scr_printf("Flow Control\n");
}

void resolveAddress( struct sockaddr_in *server, int w, int x, int y, int z)
{
	char port[6] = "10000"; // default port of 80(HTTP)
	int i = 0;

	scr_printf("octets %d %d %d %d\n",w,x,y,z);
	IP4_ADDR( (struct ip4_addr *)&(server->sin_addr) ,w,x,y,z );
	scr_printf("%X\n",server->sin_addr);

    i = (int) strtol(port, NULL, 10); // set the port
	server->sin_port = htons(i);
	scr_printf("port %d\n", i);

	server->sin_family = AF_INET;
}

int main(int argc, char *argv[])
{
	struct ip4_addr IP, NM, GW, DNS;
	struct sockaddr_in * server = malloc(sizeof *server);
	int rc;
	int EthernetLinkMode;
	int sockHandle;

	//Reboot IOP
	SifInitRpc(0);
	while(!SifIopReset("", 0)){};
	while(!SifIopSync()){};

	//Initialize SIF services
	SifInitRpc(0);
	SifLoadFileInit();
	SifInitIopHeap();
	sbv_patch_enable_lmb();

	//Load modules
	SifExecModuleBuffer(DEV9_irx, size_DEV9_irx, 0, NULL, NULL);
	SifExecModuleBuffer(NETMAN_irx, size_NETMAN_irx, 0, NULL, NULL);
	SifExecModuleBuffer(SMAP_irx, size_SMAP_irx, 0, NULL, NULL);

	//Initialize NETMAN
	NetManInit();

	init_scr();

	//The network interface link mode/duplex can be set.
	EthernetLinkMode = NETMAN_NETIF_ETH_LINK_MODE_AUTO;

	//Attempt to apply the new link setting.
	if(ethApplyNetIFConfig(EthernetLinkMode) != 0) {
		scr_printf("Error: failed to set link mode.\n");
		goto end;
	}

	//Initialize IP address.
	IP4_ADDR(&IP, 192, 168, 0, 200);
	IP4_ADDR(&NM, 255, 255, 255, 0);
	IP4_ADDR(&GW, 192, 168, 0, 1);
	//DNS is not required if the DNS service is not used, but this demo will show how it is done.
	IP4_ADDR(&DNS, 192, 168, 0, 1);

	//Initialize the TCP/IP protocol stack.
	ps2ipInit(&IP, &NM, &GW);
	dns_setserver(0, &DNS);	//Set DNS server

	//Change IP address
	ethApplyIPConfig(0, &IP, &NM, &GW, &DNS);

	//Wait for the link to become ready.
	scr_printf("Waiting for connection...\n");
	if(ethWaitValidNetIFLinkState() != 0) {
		scr_printf("Error: failed to get valid link status.\n");
		goto end;
	}

	scr_printf("Initialized:\n");
	ethPrintLinkStatus();
	ethPrintIPConfig();

	//At this point, network support has been initialized and the PS2 can be pinged.
	scr_printf("I ran!\n");

	resolveAddress( server, 192, 168, 0, 132);
	if((sockHandle = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) < 0)
	{
		scr_printf("socket failed");
	}
	rc = connect( sockHandle, (struct sockaddr *) server, sizeof(*server));
	scr_printf("connect %d\n", rc);
	rc = send( sockHandle , "test",  sizeof("test"), 0 );	
	scr_printf("test sent");

	SleepThread();

end:
	//To cleanup, just call these functions.
	ps2ipDeinit();
	NetManDeinit();

	//Deinitialize SIF services
	SifExitRpc();

	return 0;
}

Fixing -Wnonnull-compare

I am not completely sure for this one warning:

src/freemtap.c: In function 'update_slot_numbers_thread':
src/freemtap.c:158:33: warning: bitwise comparison always evaluates to false [-Wtautological-compare]
   if((resbits & EF_EXIT_THREAD) == 1)
                                 ^~
/ps2sdk/iop/system/mtapman/src/freemtap.c: In function 'update_slot_numbers_thread':
/ps2sdk/iop/system/mtapman/src/freemtap.c:158:33: warning: bitwise comparison always evaluates to false [-Wtautological-compare]
   if((resbits & EF_EXIT_THREAD) == 1)
                                 ^~

Maybe this should be fixed as descibed here?:

if((resbits & EF_EXIT_THREAD) == EF_EXIT_THREAD)

Cannot find file "ps2.h"

I try build it from source, but when i build it compiler gets a fatal error in file ps2_dbg.c . Compiler cannot find a file with name — ps2.h . I can’t find it in source code too. Can you explain me,please, where i can find this file?

Possible bug in ps2_sbrk due to size_t parameter

I'm encountering a few cases where malloc is returning NULL with roughly ~14MB of system memory allocated. At first I was suspecting the issue was with heap fragmentation from previous free()s but looking at the implementation in the libc dir, I noticed that free might call ps2_sbrk with a negative value. Excerpt from alloc.c:

/* We need to free (heap top) - (prev->ptr + prev->size), or else
we'll end up with an unallocatable block of heap.  */
heap_top = ps2_sbrk(0);
size = (u32)heap_top - (u32)(cur->prev->ptr + cur->prev->size);
ps2_sbrk(-size);

There's another negated parameter case above that section too.

However when looking at the implementation of ps2_sbrk I was surprised to find the increment parameter declared as size_t, which is unsigned.

sbrk.c:

void *ps2_sbrk(size_t increment)
{
    static void * _heap_ptr = &_end;
    void *mp, *ret = (void *)-1;

    if (increment == 0)
        return _heap_ptr;

    /* If the area we want to allocated is past the end of our heap, we have a problem. */
    mp = _heap_ptr + increment;
    if (mp <= EndOfHeap()) {
        ret = _heap_ptr;
        _heap_ptr = mp;
    }

    return ret;
}

So when free tries to roll back the heap, it will actually just add more to the already allocated region, due to signed => unsigned promotion! To match the signature of Unix sbrk, ps2_sbrk should be taking a signed type.

Please advise if you agree that this is a bug in the code and I'll promptly create a pull request with the fix.

Thanks.

Q. -DF_ idiom

The makefiles in ps2sdk use a curious idiom I hadn't seen before, which I will call the -DF_ idiom

So apparently there are .c files from which many .o files get produced.

The c files are organized as so:

lib.c:

/* <bunch of stuff>*/
#ifdef F_Foo
int Foo(Arg1, Arg2)
{
}
#endif

#ifdef F_Bar
int Bar(Arg1, Arg2)
{
}
#endif

Then the makefiles are structured so that:

Makefile

LIB_OBJS=Foo.o Bar.o

$(LIB_OBJS:%=$(EE_OBJS_DIR)%): $(EE_SRC_DIR)lib.c
	$(EE_C_COMPILE) -DF_$(*:$(EE_OBJS_DIR)%=%) $< -c -o $@

Effectively this means that n calls to the compiler will be made:

cc -DF_Foo -c -o Output/Foo.o
cc -DF_Bar -c -o Output/Bar.o

Now that I described the setup.. What is the purpose of that idiom? It comes from way back and I
don't see an explanation there about what it accomplishes.

Was it originally introduced to allow compiling lib.c with -DF_Foo and -DF_Bar as one or as separate objs if one wishes to? Was it to control exactly which symbols get compiled?

Compatibility with GameStar compatible network adaptors - do we want it?

Some clone/compatible adaptors are no longer compatible with our late designs of ATAD and DEV9. Due to the likelihood of there actually being a multitude of models out there by various manufacturers, the model in question here is a 2015-edition of the GameStar adaptor.

We're in 2017 and the PlayStation 2 is no longer a mainstream console. Since the genuine network adaptor was only released in the US and Japan (and in Europe as only part of the PS2Linux kit), the majority of the world did not see releases. There is possibly a group of users around who may end up with some of the poorly-made adaptors, but may not have the means/do not want to replace them.
It is evident that at least GameStar used the (then) sources of ATAD and DEV9 to write the logic for their adaptors, changing how our modules worked has caused such adaptors to become incompatible.

Some of the changes in recent years to ATAD and DEV9 (since 2015) include:
-Additional check on the ICRC error state.
-Moving the enabling/disabling of DMA (on the ATA interface) into the DEV9 callbacks.
-Moving the setting up of DMA direction from before the call to ata_io_start to after the call to ata_io_start.
-Correction of the ATA device probing code - our homebrew version worked slightly differently from the original, for one reason or another. For example, devices are assumed to be packet devices unless the ATA LCYL and HCYL are both 0. However, our driver used to assume that the connected device is not a packet device by default.
-There was a new check on whether the LCYL and HCYL registers would retain values written. I don't know why this was done, but it may be there to prevent false positives.
-There is now an additional operation to disable DMA on the SPEED interface, after the call to ata_io_finish.
-As with the newer DEV9 modules, DEV9 now has some code to initialize the SMAP to a known state.
-LBA is now set in ata_io_start, causing all operations to always have the LBA bit set to 1.

It appears that the 2015 edition of GameStar expects at least the following:
-DMA (ATA) must be enabled with the setting of direction (0x86 must be written). Therefore, the DEV9 DMA callbacks cannot be used.
-DMA direction must be set up (ata_set_dir) before the call to ata_io_start.
-The "SMAP" cannot be initialized correctly with the initialization code within DEV9.

As for the write to HCYL and LCYL, I haven't really figured out why SCEI added it. Perhaps it's there to detect if the device was incorrectly connected (i.e. floating bus).

As for the DEV9 DMA callbacks, I do not really know why they had to implement them because the SMAP and ATA do not share the same registers for DMA. I guess this means that they want to ensure that DMA will be strictly enabled only before the DEV9 DMA channel is activated, and disabled after the DEV9 DMA channel is deactivated.
Right now, the compile-time options that I added to ATAD (see the bottom of this post) will only switch between the two designs for enabling/disabling DMA (pre and post 2015). For the earlier design, there is no code for disabling DMA on the ATA device because the original (earlier design) did not have such a thing... but I cannot tell if I should add it or not.

DEV9 now has some code for initializing the SMAP interface to a known state. Perhaps this is a sign that the SMAP interface can be left in an undesirable state.

That being said, is it worth reaching a compromise? We will be letting go of the changes mentioned above.
Personally, I wish to make an accurate copy of the SONY module, but that will prevent owners of clone adaptors from using new software. However, it is worth noting that not all clone adaptors may be made compatible again with such changes. Personally, I own a compatible adaptor, which was already incompatible with our ATAD module in 2013 (before any of my changes were made).

If not, then do we want to make another optional variation of ATAD, for projects like OPL to optionally use? That will allow the effects of the compromise to be confined to only such software, but it also means that owners of such adaptors can only use selected pieces of software, like HDPro users.

The changes can be previewed here, from commit 7faf72a4.

SMAP Rx FIFO becomes unresponsive or loses frames when under load

With the increase in performance, we have noticed that the Rx FIFO of the SMAP MAL seems to become unresponsive or suffers packet losses, when under load.

When it happens, the Rx frame count will remain at 0, even if the Rx octlet counter continues running. All of the Rx BDs will also remain marked as empty. The only known way to break the hardware out of that state, is to reset the Rx FIFO by writing to the reset bit of the Rx FIFO control register.

Other things noted:

  • The RXDNV interrupt (frame overrun condition) was tested to be working, by deliberately slowing down the receive process and sending a lot of frames to the PS2.
  • The fault does occur when there are nearly no frames in the Rx FIFO too, so it is not a frame overrun problem.
  • Changing the order of the frame counter getting decremented and the processed Rx BD being marked as empty, does not do anything to help with this problem.
  • It is possible to cause the Rx frame counter to wrap around, by just writing to the frame count decrement register.
  • Checking the frame count before decrementing does not help with the problem.
  • According to @rickgaiser, slowing down the frame Rx-handling code also seems to inhibit the problem, so it does seem to be a race condition within the hardware. Blocking off Tx-handling does not result in a difference.
  • On the CXD9624GG, the Rx FIFO becomes entirely responsive. Other models may simply result in frame losses.
  • I have also attempted to disable DMA, but the bug also occurs when DMA is disabled.
  • Even by manually overriding automatic negotiation and using 100Mbit FDX and 100Mbit HDX, the bug also occurs.
  • Increasing the lo Rx watermark level seems to delay the onset of the bug.

For now, a known workaround for this is to check the Rx frame counter to ensure that there are frames to process, before reading the status field of the next Rx BD.

i got ths error

-smb_cdvdman
-hdd_cdvdman
-hdd_hdpro_cdvdman
-cdvdfsv
-in-game SMSTCPIP
-in-game SMAP
-smbinit
-ps2fs
-usbhdfsd
-usbhdfsdfsv
-ps2atad
ps2atad.c: In function ata_device_set_transfer_mode': ps2atad.c:748: ATAD_XFER_MODE_MDMA' undeclared (first use in this function)
ps2atad.c:748: (Each undeclared identifier is reported only once
ps2atad.c:748: for each function it appears in.)
ps2atad.c:751: ATAD_XFER_MODE_UDMA' undeclared (first use in this function) ps2atad.c:754: ATAD_XFER_MODE_PIO' undeclared (first use in this function)
ps2atad.c: In function ata_init_devices': ps2atad.c:974: ATAD_XFER_MODE_UDMA' undeclared (first use in this function)
make[2]: *** [ps2atad.o] Error 1
make[1]: *** [modules/hdd/atad/ps2atad.irx] Error 2
make: *** [all] Error 2

ali@W8 ~/open-ps2-loader
$

Fixing -Wunused-value

Modern toolchain produces 3 warnings regarding -Wunused-value:

src/ps2dev9.c: In function 'dev9_smap_read_phy':
/work/common/include/smapregs.h:87:67: warning: value computed is not used [-Wunused-value]
 #define SMAP_EMAC3_GET(offset)  ((SMAP_EMAC3_REG((offset)) << 16) | \
                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
      (SMAP_EMAC3_REG((offset)+2)))
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                                 
/work/common/include/smapregs.h:102:3: note: in expansion of macro 'SMAP_EMAC3_GET'
   SMAP_EMAC3_GET(offset)
   ^~~~~~~~~~~~~~

and

/work/common/include/smapregs.h:90:81: warning: value computed is not used [-Wunused-value]
 ine SMAP_EMAC3_GET32(offset) (((SMAP_EMAC3_REG32((offset)) >> 16) & 0xffff) | \
                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
  ((SMAP_EMAC3_REG32((offset)) & 0xffff) << 16))
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                              
/work/common/include/smapregs.h:106:3: note: in expansion of macro 'SMAP_EMAC3_GET32'
   SMAP_EMAC3_GET32(offset)
   ^~~~~~~~~~~~~~~~

and

src/smap.c:972:2: note: in expansion of macro 'mSMAP_EMAC3_SET32'
  SMAP_EMAC3_SET32(SMAP_R_EMAC3_INTER_FRAME_GAP, 4);
  ^~~~~~~~~~~~~~~~
/work/common/include/smapregs.h:90:81: warning: value computed is not used [-Wunused-value]
 ine SMAP_EMAC3_GET32(offset) (((SMAP_EMAC3_REG32((offset)) >> 16) & 0xffff) | \
                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
  ((SMAP_EMAC3_REG32((offset)) & 0xffff) << 16))
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                              
/work/common/include/smapregs.h:106:3: note: in expansion of macro 'SMAP_EMAC3_GET32'
   SMAP_EMAC3_GET32(offset)
   ^~~~~~~~~~~~~~~~

It seems that logic is too complex - but it is difficult for me to understand which part of expression can be avoid.

bin2c: Command not found

After osdsrc and tlbsrc are not precompiled we need already installed sdk to compile them :D
Here is example of error when you didnt have ps2sdk and want to setup it from scrach link
Possible solutions:
-revert these binaries in precompiled state
-fix make command to use PS2SDKSRC not PS2SDK

Fixing -Wmisleading-indentation

src/stdtrf.c:155:1: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
 if( t < 0 )
 ^~
src/stdtrf.c:158:2: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'if'
  p = 0.5 + 0.5 * p;
  ^

(from GCC 6.2.0)
Clang-format could be a solution to this warning...
Any other suggestions? If not, I'll create a PR later.

Missing O_ACCMODE macro and wrong O_RDWR

Hello,

Taking a look at the io_common.h, we have:

#define O_RDONLY	0x0001
#define O_WRONLY	0x0002
#define O_RDWR		0x0003
#define O_DIROPEN	0x0008	// Internal use for dopen
#define O_NBLOCK	0x0010
#define O_APPEND	0x0100
#define O_CREAT		0x0200
#define O_TRUNC		0x0400
#define	O_EXCL		0x0800
#define O_NOWAIT	0x8000

Following this doc, https://www.gnu.org/software/libc/manual/html_node/Access-Modes.html we have:

Macro: int O_ACCMODE
This macro stands for a mask that can be bitwise-ANDed with the file status flag value to produce a value representing the file access mode. The mode will be O_RDONLY, O_WRONLY, or O_RDWR. (On GNU/Hurd systems it could also be zero, and it never includes the O_EXEC bit.)

So, it would means that O_ACCMODE should be O_RDONLY | O_WRONLY | O_RDWR, however O_RDWR is already O_RDONLY | O_WRONLY

Should we modify some values here? I don't know if this could have additional issues, but can we have something like:

#define O_RDONLY	0x0001
#define O_WRONLY	0x0002
#define O_RDWR		0x0004
#define O_ACCMODE	0x0007
#define O_DIROPEN	0x0008	// Internal use for dopen
#define O_NBLOCK	0x0010
#define O_APPEND	0x0100
#define O_CREAT		0x0200
#define O_TRUNC		0x0400
#define	O_EXCL		0x0800
#define O_NOWAIT	0x8000

Thanks

Support for the IDLE IMMEDIATE with UNLOAD FEATURE command - mandatory or optional at shutdown?

Following this comment (and actually, a few over the years), it appears that some HDD manufacturers treat a simple cut to the HDD's power as an "emergency unload". However, it does not seem like ATA-4 (the ATA standard that the PS2 was originally designed for) describes a proper procedure for shutting down.

At ATA-7 (from 2005), the IDLE IMMEDIATE command with UNLOAD FEATURE was added. However, it is optional and there was still no description of whether HDDs really need this to be shut down correctly.

Technically, we can add some code that issues new commands from here, which is called when the programmer shuts off DEV9. But is there a proper procedure to add?

From the Fujistsu MHW2040AC HDD manual:

The Load/Unload function is a mechanism that loads the head on the disk and unloads the head from the disk. The product supports a minimum of 600,000 Load/Unload cycles. Unload is a normal head unloading operation and is executed by the operations below:
• Hard Reset
• STANDBY command issued
• STANDBY IMMEDIATE command issued
• SLEEP command issued
• IDLE IMMEDIATE command (with unload feature) issued
• Power Mode shifted with APM/APS feature

Emergency Unload other than Unload is performed when the power is shut down while the heads are still loaded on the disk. The product supports the Emergency Unload a minimum of 20,000 times. When the power is shut down, the controlled Unload cannot be executed. Therefore, the number of Emergency other than Unload is specified.

The manual for my Seagate ST3802110A has no such instruction. I have also taken a look at manuals from Maxtor, and never heard of such a thing either....
Not only that, but it does not seem that the STANDBY IMMEDIATE command has any clause mandating that HDDs shall park their heads.

So, what should be done? Do we have to take action for some of these HDDs that were made after 2005?

Deprecating the npmXXX callls

I'm the artist formerly known as Herben, one of the creators of Naplink. The only truly valid reason to maintain Naplink related API calls is for cases where people wish to work on PS2link and have no other way to communicate with the console other than Naplink during that process. I can't speak for my Napalm brethren but I, myself would be fine with deprecating anything Naplink specific. Note that I say: deprecating, not all out removing. As mentioned before, there still remain some use cases that necessitate having more than one method of communicating with the console while debugging another communication method(eg PS2link). Until we have a reliable alternative to Naplink as a backup, I would highly recommend maintaining support for Naplink, along with preprocessor warnings to remind users that support will eventually end.
Just my $0.02

fail build when use +12 threads

Hi

With -j13

mips64r5900el-ps2-elf-gcc -D_EE -G0 -O2 -Wall -Werror  -Isrc/ -Isrc/include -Iinclude/ -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/ee/kernel/include -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/common/include -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/ee/libc/include -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/ee/erl/include  -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/ee/sbv/include  -DF__iopcontrol_special_internals src/SifIopRebootBuffer.c -c -o obj/_iopcontrol_special_internals.o
/usr/ps2/dev/ee/lib/gcc/mips64r5900el-ps2-elf/11.2.0/../../../../mips64r5900el-ps2-elf/bin/ld: cannot find -lkernel
collect2: error: ld returned 1 exit status

in my test with 48 (my machine)

mips64r5900el-ps2-elf-gcc -D_EE -G0 -O2 -Wall -Werror  -Isrc/ -Isrc/include -Iinclude/ -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/ee/kernel/include -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/common/include -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/ee/libc/include -I/tmp/makepkg/ps2-sdk-git/src/ps2sdk/ee/erl/include  -DF_SetVCommonHandler src/kernel.S -c -o obj/SetVCommonHandler.o
/usr/ps2/dev/ee/lib/gcc/mips64r5900el-ps2-elf/11.2.0/../../../../mips64r5900el-ps2-elf/bin/ld: cannot find -lcdvd
/usr/ps2/dev/ee/lib/gcc/mips64r5900el-ps2-elf/11.2.0/../../../../mips64r5900el-ps2-elf/bin/ld: cannot find -lps2sdkc
/usr/ps2/dev/ee/lib/gcc/mips64r5900el-ps2-elf/11.2.0/../../../../mips64r5900el-ps2-elf/bin/ld: cannot find -lkernel
collect2: error: ld returned 1 exit status

with -j12 build ok

greetings

LOADADDR 0x90000 overlaps a chunk of the kernel

LOADADDR = 0x90000

krHACKen recently discovered that address 0x90000 overlaps a chunk of the kernel.

To reproduce it, dump the EE kernel while the console is in the OSD, look at offset 0x00090000, scroll down to see where it ends.
Then execute the wLE, run an ELF, and dump the kernel area again to see corruption starting from 0x00090000.
Also it'd be useful to dump the kernel $gp, $sp and $fp to have a better idea of where to load our apps.
moving the loader to 0x00092000 so it doesn't corrupt the kernel fixed the issues
Not sure that it's true for all bootroms, but the min load address I got from several kernel dump was 0x91630.

USBHDFSD does not mount unpartitioned disks

The current version of USBHDFSD module does not mount unpartitioned disks, even if they are formatted as FAT16/FAT32 using the whole disk.

The file in question is part_driver.c: the fact is that the code to mount the whole disk is there, but due to how part_getPartitionRecord and part_getPartitionTable are written, it gets never executed.

By making the following 3 changes to the file in question, the problem gets fixed and disks with both with and without a partition table get mounted correctly (tested by compiling uLaunchELF 4.43a)

/iop/usb/usbhdfsd/src/part_driver.c

static USBHD_INLINE int part_getPartitionRecord(mass_dev* dev, part_raw_record* raw, part_record* rec)
{
	rec->sid = raw->sid;
	rec->start = getI32(raw->startLBA);
	rec->count = getI32(raw->size);

	if(rec->sid != 0x00)
	{	/*	Windows appears to check if the start LBA is not 0 and whether the start LBA is within the disk.
			There may be checks against the size, but I didn't manage to identify a pattern.
			If the disk has no partition table (i.e. disks with "removable" media), then this check is also one safeguard. */
		if((rec->start == 0) || (rec->start >= dev->maxLBA))
			return 1;else return 0;//this change is to accomodate the following change
	}
	else return 1;//return 1 in case of invalid or non populated partition record
	//return 0;
}
static int part_getPartitionTable(mass_dev* dev, part_table* part)
{
	part_raw_record* part_raw;
	int ret;
	unsigned int i;
	unsigned char* sbuf;

	ret = READ_SECTOR(dev, 0, sbuf);  // read sector 0 - Disk MBR or boot sector
	if ( ret < 0 )
	{
		XPRINTF("USBHDFSD: part_getPartitionTable read failed %d!\n", ret);
		return -EIO;
	}

	printf("USBHDFSD: boot signature %X %X\n", sbuf[0x1FE], sbuf[0x1FF]);
	if (sbuf[0x1FE] == 0x55 && sbuf[0x1FF] == 0xAA)
	{
		for ( i = 0; i < 4; i++)
		{
			part_raw = ( part_raw_record* )(  sbuf + 0x01BE + ( i * 16 )  );
			if((part_getPartitionRecord(dev, part_raw, &part->record[i]) != 0) && (i==0))//if(part_getPartitionRecord(dev, part_raw, &part->record[i]) != 0) //return no partition only if the first record is invalid
				return 0;	//Invalid record encountered, so the table is probably invalid.
		}
		return 4;
	}
	else
	{
		for ( i = 0; i < 4; i++)
		{
			part->record[i].sid = 0;;
		}
		return 0;
	}
}

Because of how it was written, the only way to mount the disk as a whole was to have a partition table indeed with one of the records specifying the whole disk.

PFS has coherency problems when a file is opened for reading and writing

In PFS (v2.02?), there was a new change to PFS's fileTransfer, fileTransferRemainder and _sync functions, which allow PFS to correctly allow a file to be both opened for reading and writing simultaneously. In older versions, the PFS module would suffer from a coherency problem, leading to corruption.

Timeout values and some constants used in our USBD module are different

Hi all,

I have been checking through our USBD module, while implementing the missing functions (auto loader registration, unregistration and sceUsbdChangeThreadPriority).

I noticed that our module has got different values from the official USBD module, when it comes to timeouts. For example, the one in this line is 5 in the original, while ours is now 10. I saw that it was once 4 too, until commit 381ba62.
The value used for DEVICE_READY seems to be different too; ours is 5, while the Sony USBD used 7.

In 2010, I had a USB enclosure that would not be properly communicated with by USBD. Unfortunately, I wasn't that good with PS2 development yet and did not try to use the Sony module. I no longer have that enclosure either.
I wrote about it here, although I did not (and still don't) understand the logic behind the things I tried: http://psx-scene.com/forums/f19/usb-mass-device-driver-usbhdfsd-compatibility-fix-some-usb-devices-73420/

I suspect that our module was based on some really early version, but I don't seem to have a module that shares the same values.
The earliest module that I have is v0.13, from August 2000. Does anybody know where I can get an earlier module to check against? Or how these differences in values came about?

I also noticed this patch (a8c9a3a) by Radad in 2009. He added a connected device list.
I don't really understand what advantage this patch would give. If USB devices are connected in a tree, shouldn't the parse order be no different from when the device tree is traversed in prefix order from root?
I took a while to figure out why we had two tree-parsing functions until I realized that we're using an unofficial version. If it offers no advantage but actually increases the complexity of the code, I am in favour of rolling back that patch.

Fixing -Wmisleading-indentation

Just reopen #31 cause I fixed in #88 only part of warnings. There is still some of them:

src/callstack.c: In function 'ps2GetStackTrace':
src/callstack.c:200:14: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
         else if (inst == RETURN)
              ^~
src/callstack.c:202:11: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
           ra++;
           ^~
src/callstack.c:205:7: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
       if (sp_adjust == 0 && (found_const_upper || found_const_lower))
       ^~
src/callstack.c:207:9: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
         rc->raOffset = ra_offset;
         ^~
src/stdtrf.c: In function 'stdtrf':
src/stdtrf.c:155:1: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
 if( t < 0 )
 ^~
src/stdtrf.c:158:2: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
  p = 0.5 + 0.5 * p;
  ^

Im not completely sure if this is real missing brackets or just indentation problem. For example first warning can bi fixed in such way:

      while ((!found_ra_offset || !found_sp_adjust) && ra < ra_limit)
      {
        inst = *ra;
        /* look for the offset of the PC in the stack frame */
        if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL)
        {
          ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
          found_ra_offset = TRUE;
        }
        else if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL2)
        {
            ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
            found_ra_offset = TRUE;
        }
        else if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL3)
        {
            ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
            found_ra_offset = TRUE;
        }
        else if ((inst & ADJUST_STACKP_C_MASK) == ADJUST_STACKP_C)
        {
          sp_adjust = inst & ~ADJUST_STACKP_C_MASK;
          found_sp_adjust = TRUE;
        }
        else if ((inst & ADJUST_STACKP_V_MASK) == ADJUST_STACKP_V)
        {
          sp_adjust = 0;
          found_sp_adjust = TRUE;
        }
        else if ((inst & SET_UPPER_C_MASK) == SET_UPPER_C)
        {
          const_upper = inst & ~SET_UPPER_C_MASK;
          const_lower = 0;
          found_const_upper = TRUE;
        }
        else if ((inst & OR_LOWER_C_MASK) == OR_LOWER_C)
        {
          const_lower = inst & ~OR_LOWER_C_MASK;
          found_const_lower = TRUE;
        }
        else if ((inst & SET_LOWER_C_MASK) == SET_LOWER_C)
        {
          const_lower = inst & ~SET_LOWER_C_MASK;
          const_upper = 0;
          found_const_lower = TRUE;
        }
        else if (inst == RETURN)
        {
          ra_limit = ra + 2;
          ra++;
        }
      }

or in such way:

      while ((!found_ra_offset || !found_sp_adjust) && ra < ra_limit)
      {
        inst = *ra;
        /* look for the offset of the PC in the stack frame */
        if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL)
        {
          ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
          found_ra_offset = TRUE;
        }
        else if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL2)
        {
            ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
            found_ra_offset = TRUE;
        }
        else if ((inst & RESTORE_RETURNVAL_MASK) == RESTORE_RETURNVAL3)
        {
            ra_offset = inst & ~RESTORE_RETURNVAL_MASK;
            found_ra_offset = TRUE;
        }
        else if ((inst & ADJUST_STACKP_C_MASK) == ADJUST_STACKP_C)
        {
          sp_adjust = inst & ~ADJUST_STACKP_C_MASK;
          found_sp_adjust = TRUE;
        }
        else if ((inst & ADJUST_STACKP_V_MASK) == ADJUST_STACKP_V)
        {
          sp_adjust = 0;
          found_sp_adjust = TRUE;
        }
        else if ((inst & SET_UPPER_C_MASK) == SET_UPPER_C)
        {
          const_upper = inst & ~SET_UPPER_C_MASK;
          const_lower = 0;
          found_const_upper = TRUE;
        }
        else if ((inst & OR_LOWER_C_MASK) == OR_LOWER_C)
        {
          const_lower = inst & ~OR_LOWER_C_MASK;
          found_const_lower = TRUE;
        }
        else if ((inst & SET_LOWER_C_MASK) == SET_LOWER_C)
        {
          const_lower = inst & ~SET_LOWER_C_MASK;
          const_upper = 0;
          found_const_lower = TRUE;
        }
        else if (inst == RETURN)
          ra_limit = ra + 2;
        ra++;
      }

And this code isnt that easy so I will left it here - maybe somebody with better skills can dig in it.

fileXioGetStat not working for host

Hello,
The fileXioGetStat function always return -19 when I tried to access through host drive.

To give you more info, I'm using ps2-client to debug/run the .elf, so for instance if it tries to get stat for something like host:test giving that test is a folder, it always return -19

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.