aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/psxsio/tty.c
blob: a88af85b00422027cdaaf932cdff9b3242bcd5a2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/*
 * PSn00bSDK serial port BIOS TTY driver
 * (C) 2019-2022 Lameguy64, spicyjpeg - MPL licensed
 *
 * This driver is designed to be as simple and reliable as possible: as such it
 * only relies on the SIO_*() API for receiving and sends data synchronously.
 * This allows printf() to work without issues, albeit slowly, if called from a
 * critical section or even from an interrupt handler.
 */

#include <sys/ioctl.h>
#include <psxapi.h>
#include <psxsio.h>
#include <hwregs_c.h>

/* TTY device control block */

static int _sio_open(FCB *fcb, const char* file, int mode) {
	fcb->diskid = 1;
	return 0;
}

static int _sio_inout(FCB *fcb, int cmd) {
	char *ptr = (char*) fcb->trns_addr;

	switch (cmd) {
		case 1: // read
			for (int i = 0; i < fcb->trns_len; i++)
				*(ptr++) = (char) SIO_ReadByte();

			return fcb->trns_len;

		case 2: // write
			for (int i = 0; i < fcb->trns_len; i++) {
				while (!(SIO_STAT(1) & (SR_TXRDY | SR_TXU)))
					__asm__ volatile("");

				SIO_DATA(1) = *(ptr++);
			}

			return fcb->trns_len;

		default:
			return 0;
	}
}

static int _sio_close(FCB *fcb) {
	return 0;
}

static int _sio_ioctl(FCB *fcb, int cmd, int arg) {
	switch (cmd) {
		case FIOCSCAN:
			return SIO_ReadSync(1) ? 0 : -1;

		default:
			return -1;
	}
}

static int _sio_dummy(void) {
	return -1;
}

static DCB _sio_dcb = {
	.name			= "tty",
	.flags			= 3,
	.ssize			= 1,
	.desc			= "PSXSIO SERIAL CONSOLE",
	.f_init			= &_sio_dummy,
	.f_open			= &_sio_open,
	.f_inout		= &_sio_inout,
	.f_close		= &_sio_close,
	.f_ioctl		= &_sio_ioctl,
	.f_read			= &_sio_dummy,
	.f_write		= &_sio_dummy,
	.f_erase		= &_sio_dummy,
	.f_undelete		= &_sio_dummy,
	.f_firstfile	= &_sio_dummy,
	.f_nextfile		= &_sio_dummy,
	.f_format		= &_sio_dummy,
	.f_chdir		= &_sio_dummy,
	.f_rename		= &_sio_dummy,
	.f_remove		= &_sio_dummy,
	.f_testdevice	= &_sio_dummy
};

/* Public API */

void AddSIO(int baud) {
	SIO_Init(baud, MR_SB_01 | MR_CHLEN_8);

	close(0);
	close(1);
	DelDrv(_sio_dcb.name);
	AddDrv(&_sio_dcb);
	open(_sio_dcb.name, 2);
	open(_sio_dcb.name, 1);
}

void DelSIO(void) {
	SIO_Quit();

	DelDrv(_sio_dcb.name);
	add_nullcon_driver();
}