(*) O_APPEND is *not* functional yet, this is just a hack for write-only
streams. Currently O_APPEND does not reposition the cursor at the end of
the file before every write.
There is no evidence that BFile_Create() keeps the address and writes
to it later on, but I'd rather be overly careful than have to debug a
stack corruption problem in half a year :)
I'm pretty sure it makes no difference because the OS does not rely on
interrupts for most (if not all) of its DMA operations, but it's better
to keep it clean anyway.
This helped locate some bugs:
* read() could read past EOF due to BFile_Read() allowing you to read up
until the end of the last sector, beyond the file size
* pread() did not restore the file offset because the negative seek at
the end is not relative (that was the CASIOWIN fs API), so pread()
could not actually be written without knowing the current position
* lseek() would clamp you to EOF but still return its out-of-bounds
arguments, as a direct result of BFile_Seek() doing that
Benefits:
* Made pread() a generic function
I saw a crash with the 12 kB stack. Added an error message to diagnose
further similar issues, and bumbed the stack to 14 kB. That's a lot of
space just for BFile but stability is queen... :x
* Mark SPU memory as sleep-blocking.
* Perform 4-byte accesses only in dma_memset() and dma_memcpy() (32-byte
accesses freeze as one would expect).
This change does *NOT* implement support for SPU's integrated DMAC.
The checks for VRAM access account for image columns intersecting the
longword before the start of a VRAM line, but not the longword after the
start of a VRAM line. This is now fixed.
Nothing particular to change, simply make sure that the DMA channels
have higher priority than the USB module, otherwise the BEMP interrupt
might be executed before the DMA frees the channel, resulting in the
transfer failing because the channel is still busy.
Also reduce BUSWAIT since it works even on high overclock levels, and
keeping it high won't help increase performance.
This changes fixes the way gint uses the FIFO controllers D0F and D1F
to access the FIFO. It previously used D0F in the main thread and D1F
during interrupt handling, but this is incorrect for several reasons,
mainly the possible change of controllers between a write and a commit,
and numerous instances of two FIFOs managing the same pipe caused by
the constant switching.
gint now treats FIFO controllers as resources allocated to pipes for
the duration of a commit-terminated sequence of writes. The same
controller is used for a single pipe in both normal and interrupt
modes, and released when the pipe is committed. If no controller is
available, asynchronous writes fail and synchronous ones wait.
The fxlink API is also added with a small amount of functions, namely
to transfer screenshots and raw text. Currently these are synchronous
and do not use the DMA, this will be improved later.
Finally:
* Removed pipe logic from src/usb/setup.c, instead letting pipes.c
handle the special case of the DCP (which might be regularized later)
* Removed the usb_pipe_mode_{read,write} functions as they're actually
about FIFo controllers and it's not clear yet how a pipe with both
read and write should be handled. This is left for the future.
* Clarified end-of-sequence semantics after a successful commit.
The function was designed with multi-threaded concurrency in mind,
where threads can take over while the lock is held and simply block
trying to acquire it, which allows the lock holder to proceed.
However interrupt handlers are different; they have priority, so once
they start they must complete immediately. The cannot afford to block
on the lock as the program would simply freeze. In exchange, they clean
up before they leave, so there are some guarantees on the execution
state even when interrupted.
The correct protection is therefore not a lock but a temporary block on
interrupts. There is no data race on the value of the saved IMASK
because it is preserved during interrupt handling.