diff options
| author | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-07 13:22:53 +0200 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi92@disroot.org> | 2025-07-25 14:16:41 +0200 |
| commit | 14f60e4fd65c42f126eaee7e09cb4251c167c6ed (patch) | |
| tree | 313b5e16d7d99cf1518c953e2efe5e5fc920dfbf /src/drv/ps1/cd | |
| parent | 48a61c16eaa6dcfc75d00dba302537ce1492db98 (diff) | |
| download | wnix-tty.tar.gz | |
wiptty
Diffstat (limited to 'src/drv/ps1/cd')
| -rw-r--r-- | src/drv/ps1/cd/CMakeLists.txt | 20 | ||||
| -rw-r--r-- | src/drv/ps1/cd/include/drv/ps1/cd.h | 28 | ||||
| -rw-r--r-- | src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h | 66 | ||||
| -rw-r--r-- | src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h | 37 | ||||
| -rw-r--r-- | src/drv/ps1/cd/private_include/drv/ps1/cd/types.h | 122 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/CMakeLists.txt | 29 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/ensure_event.c | 40 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/free.c | 23 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/getstat.c | 65 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/init.c | 42 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/next.c | 38 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/prv.c | 22 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/read.c | 155 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/seek.c | 118 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/send.c | 100 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/toseekl.c | 54 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/update.c | 46 | ||||
| -rw-r--r-- | src/drv/ps1/cd/src/write.c | 31 |
18 files changed, 1036 insertions, 0 deletions
diff --git a/src/drv/ps1/cd/CMakeLists.txt b/src/drv/ps1/cd/CMakeLists.txt new file mode 100644 index 0000000..7459bc6 --- /dev/null +++ b/src/drv/ps1/cd/CMakeLists.txt @@ -0,0 +1,20 @@ +# wanix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +add_library(drv_ps1_cd) +add_subdirectory(src) +target_include_directories(drv_ps1_cd PUBLIC include PRIVATE private_include) +target_link_libraries(drv_ps1_cd PUBLIC c drv_event PRIVATE drv_ps1_bios) diff --git a/src/drv/ps1/cd/include/drv/ps1/cd.h b/src/drv/ps1/cd/include/drv/ps1/cd.h new file mode 100644 index 0000000..6bb48f1 --- /dev/null +++ b/src/drv/ps1/cd/include/drv/ps1/cd.h @@ -0,0 +1,28 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_H +#define DRV_PS1_CD_H + +#include <drv/event.h> + +struct drv_ps1_cd *drv_ps1_cd_init(const struct drv_event *ev); +int drv_ps1_cd_update(struct drv_ps1_cd *cd); +void drv_ps1_cd_free(struct drv_ps1_cd *cd); + +#endif diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h new file mode 100644 index 0000000..7d15f39 --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/regs.h @@ -0,0 +1,66 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_REGS_H +#define DRV_PS1_CD_REGS_H + +#include <stdint.h> + +struct cd_reg_status +{ + uint8_t index :2; + const uint8_t ADPBUSY :1, PRMEMPT :1, PRMWRDY :1, RSLRRDY :1, DRQSTS :1, + BUSYSTS :1; +}; + +struct cd_reg_cmd +{ + uint8_t cmd; +}; + +struct cd_reg_rsp +{ + uint8_t rsp; +}; + +struct cd_reg_param +{ + uint8_t param; +}; + +union cd_reg_if +{ + const struct + { + uint8_t response :3, :1, cmd_start :1, :3; + } r; + + struct + { + uint8_t ack: 5, :1, CLRPRM :1, :1; + } w; +}; + +#define CD_REG(x) (0x1f801800 + (x)) +#define CD_REG_STATUS ((volatile struct cd_reg_status *)CD_REG(0)) +#define CD_REG_CMD ((volatile struct cd_reg_cmd *)CD_REG(1)) +#define CD_REG_RSP ((const volatile struct cd_reg_rsp *)CD_REG(1)) +#define CD_REG_PARAM ((volatile struct cd_reg_param *)CD_REG(2)) +#define CD_REG_IF ((volatile union cd_reg_if *)CD_REG(3)) + +#endif diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h new file mode 100644 index 0000000..0fce7dd --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/routines.h @@ -0,0 +1,37 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_ROUTINES_H +#define DRV_PS1_CD_ROUTINES_H + +#include <drv/ps1/cd/types.h> +#include <drv/ps1/bios.h> +#include <stddef.h> + +int drv_ps1_cd_send(const struct cmd *cmd); +int drv_ps1_cd_getstat(void); +int drv_ps1_cd_read(void *buf, size_t n, const struct drv_event_done *done, + void *args); +int drv_ps1_cd_seek(long offset, const struct drv_event_done *done, + void *args); +int drv_ps1_cd_write(const void *buf, size_t n, + const struct drv_event_done *done, void *args); +int drv_ps1_cd_next(void); +struct CdAsyncSeekL drv_ps1_cd_toseekl(unsigned i); + +#endif diff --git a/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h b/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h new file mode 100644 index 0000000..4446305 --- /dev/null +++ b/src/drv/ps1/cd/private_include/drv/ps1/cd/types.h @@ -0,0 +1,122 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#ifndef DRV_PS1_CD_TYPES_H +#define DRV_PS1_CD_TYPES_H + +#include <drv/event.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> + +struct drv_ps1_cd +{ + bool available; + struct drv_event ev; +}; + +struct cmd +{ + enum + { + CMD_SYNC, + CMD_GETSTAT, + CMD_SETLOC, + } cmd; + + union cmd_param + { + struct cmd_setloc + { + uint8_t min, sec, sect; + } setloc; + } params; +}; + +struct cd_prv_getstat +{ + int event; + + union + { + struct + { + uint8_t invalid :1, motor :1, seek_error :1, id_error :1, + shell_open :1, reading :1, seeking :1, playing_cdda :1; + } bits; + + uint8_t byte; + } status; +}; + +struct cd_prv_read +{ + int event, endevent, errevent; +}; + +struct cd_prv_seek +{ + int event, errevent; +}; + +struct cd_req_read +{ + void *buf; + size_t n; +}; + +struct cd_req_seek +{ + long offset; +}; + +struct cd_req +{ + union + { + struct cd_req_read read; + struct cd_req_seek seek; + } u; + + int (*f)(void); + struct drv_event_done done; + struct cd_req *next; +}; + +enum {CD_SECTOR_SZ = 2048}; + +struct cd_prv +{ + bool available, has_cache; + int (*next)(void); + struct cmd cmd; + struct cd_req *head, *tail; + char sector[CD_SECTOR_SZ]; + unsigned offset; + + union + { + struct cd_prv_getstat getstat; + struct cd_prv_read read; + struct cd_prv_seek seek; + } u; +}; + +extern struct cd_prv drv_ps1_cd_prv; + +#endif diff --git a/src/drv/ps1/cd/src/CMakeLists.txt b/src/drv/ps1/cd/src/CMakeLists.txt new file mode 100644 index 0000000..074671d --- /dev/null +++ b/src/drv/ps1/cd/src/CMakeLists.txt @@ -0,0 +1,29 @@ +# wanix, a Unix-like operating system for WebAssembly applications. +# Copyright (C) 2025 Xavier Del Campo Romero +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +target_sources(drv_ps1_cd PRIVATE + free.c + getstat.c + init.c + next.c + prv.c + # send.c + read.c + seek.c + toseekl.c + update.c + write.c +) diff --git a/src/drv/ps1/cd/src/ensure_event.c b/src/drv/ps1/cd/src/ensure_event.c new file mode 100644 index 0000000..5e2f3a0 --- /dev/null +++ b/src/drv/ps1/cd/src/ensure_event.c @@ -0,0 +1,40 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/bios.h> +#include <drv/ps1/cd/types.h> +#include <stddef.h> + +int drv_ps1_cd_ensure_event(struct cd_prv *const p) +{ + if (p->event) + return 0; + + EnterCriticalSection(); + + const int event = OpenEvent(CLASS_CDROM, SPEC_COMMAND_COMPLETE, MODE_READY, + NULL); + + ExitCriticalSection(); + + if (event == -1) + return -1; + + EnableEvent(p->event = event); + return 0; +} diff --git a/src/drv/ps1/cd/src/free.c b/src/drv/ps1/cd/src/free.c new file mode 100644 index 0000000..44704d7 --- /dev/null +++ b/src/drv/ps1/cd/src/free.c @@ -0,0 +1,23 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> + +void drv_ps1_cd_free(struct drv_ps1_cd *const cd) +{ +} diff --git a/src/drv/ps1/cd/src/getstat.c b/src/drv/ps1/cd/src/getstat.c new file mode 100644 index 0000000..6268f37 --- /dev/null +++ b/src/drv/ps1/cd/src/getstat.c @@ -0,0 +1,65 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/bios.h> + +static int wait_event(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_getstat *const g = &p->u.getstat; + + if (TestEvent(g->event)) + { + p->available = !g->status.bits.shell_open; + DisableEvent(g->event); + CloseEvent(g->event); + + if (!p->head) + return drv_ps1_cd_getstat(); + + return p->head->f(); + } + + return 0; +} + +int drv_ps1_cd_getstat(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_getstat *const g = &p->u.getstat; + + EnterCriticalSection(); + + const int event = OpenEvent(CLASS_CDROM, SPEC_COMMAND_COMPLETE, + MODE_READY, NULL); + + ExitCriticalSection(); + + if (event == -1) + return -1; + + *g = (const struct cd_prv_getstat){.event = event}; + EnableEvent(event); + + if (!CdAsyncGetStatus(&g->status.byte)) + return -1; + + p->next = wait_event; + return 0; +} diff --git a/src/drv/ps1/cd/src/init.c b/src/drv/ps1/cd/src/init.c new file mode 100644 index 0000000..896e330 --- /dev/null +++ b/src/drv/ps1/cd/src/init.c @@ -0,0 +1,42 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/event.h> +#include <stddef.h> +#include <stdlib.h> + +struct drv_ps1_cd *drv_ps1_cd_init(const struct drv_event *const ev) +{ + struct drv_ps1_cd *const ret = malloc(sizeof *ret); + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (!ret) + return NULL; + else if (!p->next && drv_ps1_cd_getstat()) + goto failure; + + *ret = (const struct drv_ps1_cd){.ev = *ev}; + return ret; + +failure: + free(ret); + return NULL; +} diff --git a/src/drv/ps1/cd/src/next.c b/src/drv/ps1/cd/src/next.c new file mode 100644 index 0000000..0923be9 --- /dev/null +++ b/src/drv/ps1/cd/src/next.c @@ -0,0 +1,38 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <stdlib.h> + +int drv_ps1_cd_next(void) +{ + int ret = 0; + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_req *const next = p->head->next; + + free(p->head); + + if (next && (ret = next->f())) + return -1; + else if (!(p->head = next)) + return drv_ps1_cd_getstat(); + + return ret; +} diff --git a/src/drv/ps1/cd/src/prv.c b/src/drv/ps1/cd/src/prv.c new file mode 100644 index 0000000..dd70709 --- /dev/null +++ b/src/drv/ps1/cd/src/prv.c @@ -0,0 +1,22 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/types.h> + +struct cd_prv drv_ps1_cd_prv; diff --git a/src/drv/ps1/cd/src/read.c b/src/drv/ps1/cd/src/read.c new file mode 100644 index 0000000..251481e --- /dev/null +++ b/src/drv/ps1/cd/src/read.c @@ -0,0 +1,155 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/event.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +static int deliver_event(struct cd_prv *const p, const int error) +{ + const struct cd_prv_read *const read = &p->u.read; + const struct cd_req *const req = p->head; + const struct drv_event_done *const d = &req->done; + + if (!error) + { + const struct cd_req_read *const rr = &req->u.read; + const long offset = p->offset % CD_SECTOR_SZ; + + memcpy(rr->buf, p->sector + offset, rr->n); + p->has_cache = true; + p->offset += rr->n; + } + + if (d->f(error, d->args) || drv_ps1_cd_next()) + return -1; + + return 0; +} + +static int wait_event(void) +{ + int ret = 0; + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_prv_read *const read = &p->u.read; + + if (TestEvent(read->event)) + return deliver_event(p, SUCCESS); + else if (TestEvent(read->errevent) || TestEvent(read->endevent)) + return deliver_event(p, EIO); + + return 0; +} + +static int start_read(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_read *const r = &p->u.read; + const struct cd_req_read *req = &p->head->u.read; + const struct CdAsyncReadSector_mode mode = + { + .mode.bits.speed = 1, + }; + + EnterCriticalSection(); + + const int + event = OpenEvent(CLASS_CDROM, SPEC_COMMAND_COMPLETE, MODE_READY, NULL), + endevent = OpenEvent(CLASS_CDROM, SPEC_DATA_END, MODE_READY, NULL), + errevent = OpenEvent(CLASS_CDROM, SPEC_ERROR, MODE_READY, NULL); + + ExitCriticalSection(); + + if (event == -1 || endevent == -1 || errevent == -1) + goto failure; + + *r = (const struct cd_prv_read) + { + .event = event, + .endevent = endevent, + .errevent = errevent + }; + + EnableEvent(event); + EnableEvent(endevent); + EnableEvent(errevent); + + if (!CdAsyncReadSector(1, p->sector, mode)) + goto failure; + + p->next = wait_event; + return 0; + +failure: + if (event != -1) + CloseEvent(event); + + if (endevent != -1) + CloseEvent(endevent); + + if (errevent != -1) + CloseEvent(errevent); + + return -1; +} + +static int read_cache(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_req *const req = p->head; + const struct cd_req_read *const rr = &req->u.read; + const long offset = p->offset % CD_SECTOR_SZ; + + memcpy(rr->buf, p->sector + offset, rr->n); + p->offset += rr->n; + return deliver_event(p, SUCCESS); +} + +int drv_ps1_cd_read(void *const buf, const size_t n, + const struct drv_event_done *const done, void *const args) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_req *const r = malloc(sizeof *r); + + if (!r) + return -1; + + *r = (const struct cd_req) + { + .done = *done, + /* TODO: multi-sector reads, make sure cache can really be used */ + .f = p->has_cache ? read_cache : start_read, + .u.read = + { + .buf = buf, + .n = n + } + }; + + if (!p->head) + p->head = r; + else + p->tail->next = r; + + p->tail = r; + return 0; +} diff --git a/src/drv/ps1/cd/src/seek.c b/src/drv/ps1/cd/src/seek.c new file mode 100644 index 0000000..e26a684 --- /dev/null +++ b/src/drv/ps1/cd/src/seek.c @@ -0,0 +1,118 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/bios.h> +#include <drv/event.h> +#include <errno.h> +#include <stdlib.h> + +static int wait_event(void) +{ + int ret = 0; + struct cd_prv *const p = &drv_ps1_cd_prv; + const struct cd_prv_seek *const s = &p->u.seek; + const struct cd_req *const r = p->head; + const struct drv_event_done *const d = &r->done; + + if (TestEvent(s->event)) + { + p->offset = r->u.seek.offset; + + if (d->f(0, d->args) || drv_ps1_cd_next()) + return -1; + } + else if (TestEvent(s->errevent)) + { + if (d->f(EIO, d->args) || drv_ps1_cd_next()) + return -1; + } + + return 0; +} + +static int seek(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_prv_seek *const s = &p->u.seek; + const struct cd_req_seek *req = &p->head->u.seek; + const unsigned sector = req->offset / CD_SECTOR_SZ; + const struct CdAsyncSeekL seekl = drv_ps1_cd_toseekl(sector); + + EnterCriticalSection(); + + const int + event = OpenEvent(CLASS_CDROM, SPEC_COMMAND_COMPLETE, MODE_READY, NULL), + errevent = OpenEvent(CLASS_CDROM, SPEC_ERROR, MODE_READY, NULL); + + ExitCriticalSection(); + + if (event == -1 || errevent == -1) + goto failure; + + *s = (const struct cd_prv_seek) + { + .event = event, + .errevent = errevent + }; + + EnableEvent(event); + EnableEvent(errevent); + + if (!CdAsyncSeekL(&seekl)) + goto failure; + + p->next = wait_event; + return 0; + +failure: + if (event != -1) + CloseEvent(event); + + if (errevent != -1) + CloseEvent(errevent); + + return -1; +} + +int drv_ps1_cd_seek(const long offset, const struct drv_event_done *const done, + void *const args) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + struct cd_req *const r = malloc(sizeof *r); + + if (!r) + return -1; + + *r = (const struct cd_req) + { + .done = *done, + .u.seek = offset, + .f = seek + }; + + if (!p->head) + p->head = r; + else + p->tail->next = r; + + p->tail = r; + return 0; +} diff --git a/src/drv/ps1/cd/src/send.c b/src/drv/ps1/cd/src/send.c new file mode 100644 index 0000000..76b9730 --- /dev/null +++ b/src/drv/ps1/cd/src/send.c @@ -0,0 +1,100 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/bios.h> +#include <drv/ps1/cd/regs.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <stdint.h> + +static int wait_event(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (TestEvent(p->event)) + { + const union cd_prv_getstat g = {.status = CD_REG_RSP->rsp}; + + p->available = !g.bits.shell_open; + } + + return 0; +} + +static void send_params(const struct cd_prv *const p) +{ + static const size_t n[] = + { + [CMD_SETLOC] = sizeof (struct cmd_setloc) + }; + + const uint8_t cmd = p->cmd.cmd, index = CD_REG_STATUS->index; + + if (cmd < sizeof n / sizeof *n) + { + const void *const vbuf = &p->cmd.params; + const uint8_t *buf = vbuf; + + CD_REG_STATUS->index = 0; + + for (size_t i = 0; i < n[cmd]; i++) + CD_REG_PARAM->param = *buf++; + + CD_REG_STATUS->index = index; + } +} + +static int send_data(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (CD_REG_STATUS->BUSYSTS) + return 0; + + send_params(p); + CD_REG_CMD->cmd = p->cmd.cmd; + p->next = wait_event; + return 0; +} + +static int reset_param_fifo(void) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (CD_REG_STATUS->BUSYSTS) + return 0; + + CD_REG_IF->w.ack = 0x1f; + CD_REG_STATUS->index = 1; + CD_REG_IF->w.CLRPRM = 1; + p->next = send_data; + return 0; +} + +int drv_ps1_cd_send(const struct cmd *const cmd) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (drv_ps1_cd_ensure_event(p)) + return -1; + + p->cmd = *cmd; + p->next = reset_param_fifo; + return 0; +} diff --git a/src/drv/ps1/cd/src/toseekl.c b/src/drv/ps1/cd/src/toseekl.c new file mode 100644 index 0000000..df35ff1 --- /dev/null +++ b/src/drv/ps1/cd/src/toseekl.c @@ -0,0 +1,54 @@ +/* Original functions from psn00bsdk, commit 5d9aa2d3 + * + * itob extracted from libpsn00b/include/psxcd.h + * CdIntToPos (here renamed to drv_ps1_cd_toseekl) extracted from + * libpsn00b/psxcd/misc.c + * + * Original copyright notice: + * + * PSn00bSDK CD-ROM library + * (C) 2020-2023 Lameguy64, spicyjpeg - MPL licensed + */ + +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/bios.h> + +/** + * @brief Translates a decimal value to BCD. + * + * @details Translates a decimal integer in 0-99 range into a BCD format value. + */ +static int itob(const int i) +{ + return (i / 10 * 16) | (i % 10); +} + +struct CdAsyncSeekL drv_ps1_cd_toseekl(unsigned i) +{ + i += 150; + + return (const struct CdAsyncSeekL) + { + .minutes = itob(i / (75 * 60)), + .seconds = itob((i / 75) % 60), + .frames = itob(i % 75) + }; +} diff --git a/src/drv/ps1/cd/src/update.c b/src/drv/ps1/cd/src/update.c new file mode 100644 index 0000000..2c3d2ff --- /dev/null +++ b/src/drv/ps1/cd/src/update.c @@ -0,0 +1,46 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/types.h> +#include <drv/ps1/cd/routines.h> +#include <drv/event.h> +#include <stdbool.h> + +int drv_ps1_cd_update(struct drv_ps1_cd *const cd) +{ + struct cd_prv *const p = &drv_ps1_cd_prv; + + if (p->next()) + return -1; + else if (p->available ^ cd->available) + { + const struct drv_event *const ev = &cd->ev; + static const struct drv_event_ops ops = + { + .read = drv_ps1_cd_read, + .write = drv_ps1_cd_write, + .seek = drv_ps1_cd_seek + }; + + ev->status("cd0", &ops, p->available, ev->args); + cd->available = p->available; + } + + return 0; +} diff --git a/src/drv/ps1/cd/src/write.c b/src/drv/ps1/cd/src/write.c new file mode 100644 index 0000000..008a13d --- /dev/null +++ b/src/drv/ps1/cd/src/write.c @@ -0,0 +1,31 @@ +/* + * wanix, a Unix-like operating system for WebAssembly applications. + * Copyright (C) 2025 Xavier Del Campo Romero + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +#include <drv/ps1/cd.h> +#include <drv/ps1/cd/routines.h> +#include <drv/ps1/cd/types.h> +#include <drv/event.h> +#include <errno.h> + +int drv_ps1_cd_write(const void *const buf, const size_t n, + const struct drv_event_done *const done, void *const args) +{ + /* TODO: write event callback returning EROFS */ + errno = EROFS; + return -1; +} |
