1 /*
2  * Copyright (c) 2022, Commonwealth Scientific and Industrial Research
3  * Organisation (CSIRO) ABN 41 687 119 230.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <string.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/arch/common/semihost.h>
11 
12 struct semihost_poll_in_args {
13 	long zero;
14 } __packed;
15 
16 struct semihost_open_args {
17 	const char *path;
18 	long mode;
19 	long path_len;
20 } __packed;
21 
22 struct semihost_close_args {
23 	long fd;
24 } __packed;
25 
26 struct semihost_flen_args {
27 	long fd;
28 } __packed;
29 
30 struct semihost_seek_args {
31 	long fd;
32 	long offset;
33 } __packed;
34 
35 struct semihost_read_args {
36 	long fd;
37 	char *buf;
38 	long len;
39 } __packed;
40 
41 struct semihost_write_args {
42 	long fd;
43 	const char *buf;
44 	long len;
45 } __packed;
46 
semihost_poll_in(void)47 char semihost_poll_in(void)
48 {
49 	struct semihost_poll_in_args args = {
50 		.zero = 0
51 	};
52 
53 	return (char)semihost_exec(SEMIHOST_READC, &args);
54 }
55 
semihost_poll_out(char c)56 void semihost_poll_out(char c)
57 {
58 	/* WRITEC takes a pointer directly to the character */
59 	(void)semihost_exec(SEMIHOST_WRITEC, &c);
60 }
61 
semihost_open(const char * path,long mode)62 long semihost_open(const char *path, long mode)
63 {
64 	struct semihost_open_args args = {
65 		.path = path,
66 		.mode = mode,
67 		.path_len = strlen(path)
68 	};
69 
70 	return semihost_exec(SEMIHOST_OPEN, &args);
71 }
72 
semihost_close(long fd)73 long semihost_close(long fd)
74 {
75 	struct semihost_close_args args = {
76 		.fd = fd
77 	};
78 
79 	return semihost_exec(SEMIHOST_CLOSE, &args);
80 }
81 
semihost_flen(long fd)82 long semihost_flen(long fd)
83 {
84 	struct semihost_flen_args args = {
85 		.fd = fd
86 	};
87 
88 	return semihost_exec(SEMIHOST_FLEN, &args);
89 }
90 
semihost_seek(long fd,long offset)91 long semihost_seek(long fd, long offset)
92 {
93 	struct semihost_seek_args args = {
94 		.fd = fd,
95 		.offset = offset
96 	};
97 
98 	return semihost_exec(SEMIHOST_SEEK, &args);
99 }
100 
semihost_read(long fd,void * buf,long len)101 long semihost_read(long fd, void *buf, long len)
102 {
103 	struct semihost_read_args args = {
104 		.fd = fd,
105 		.buf = buf,
106 		.len = len
107 	};
108 	long ret;
109 
110 	ret = semihost_exec(SEMIHOST_READ, &args);
111 	/* EOF condition */
112 	if (ret == len) {
113 		ret = -EIO;
114 	}
115 	/* All bytes read */
116 	else if (ret == 0) {
117 		ret = len;
118 	}
119 	return ret;
120 }
121 
semihost_write(long fd,const void * buf,long len)122 long semihost_write(long fd, const void *buf, long len)
123 {
124 	struct semihost_write_args args = {
125 		.fd = fd,
126 		.buf = buf,
127 		.len = len
128 	};
129 
130 	return semihost_exec(SEMIHOST_WRITE, &args);
131 }
132