1 /* Copyright (c) 2010 CodeSourcery, Inc.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright
7 notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright
9 notice, this list of conditions and the following disclaimer in the
10 documentation and/or other materials provided with the distribution.
11 * Neither the name of CodeSourcery nor the
12 names of its contributors may be used to endorse or promote products
13 derived from this software without specific prior written permission.
15 THIS SOFTWARE IS PROVIDED BY CODESOURCERY, INC. ``AS IS'' AND ANY
16 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CODESOURCERY BE LIABLE
19 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
40 #define _DTUNLINK 0xf5
41 #define _DTGETENV 0xf6
42 #define _DTRENAME 0xf7
43 #define _DTGETTIME 0xf8
44 #define _DTGETCLK 0xf9
47 #define CIOBUFSIZ (BUFSIZ + 32)
49 struct __attribute__((packed
)) cio_open_to_host
51 /* Suggested file descriptor (little endian). */
53 /* Flags (little endian). */
57 struct __attribute__((packed
)) cio_open_from_host
59 /* File descriptor (little endian). */
63 struct __attribute__((packed
)) cio_close_to_host
65 /* File descriptor (little endian). */
69 struct __attribute__((packed
)) cio_close_from_host
71 /* Result (little endian). */
75 struct __attribute__((packed
)) cio_read_to_host
77 /* File descriptor (little endian). */
79 /* Length (little endian). */
83 struct __attribute__((packed
)) cio_read_from_host
85 /* Result (little endian). */
89 struct __attribute__((packed
)) cio_write_to_host
91 /* File descriptor (little endian). */
93 /* Length (little endian). */
97 struct __attribute__((packed
)) cio_write_from_host
99 /* Result (little endian). */
103 struct __attribute__((packed
)) cio_lseek_to_host
105 /* File descriptor (little endian). */
107 /* Offset (little endian). */
109 /* Whence (little endian). */
113 struct __attribute__((packed
)) cio_lseek_from_host
115 /* Result (little endian). */
119 struct __attribute__((packed
)) cio_unlink_to_host
124 struct __attribute__((packed
)) cio_unlink_from_host
126 /* Result (little endian). */
130 struct __attribute__((packed
)) cio_rename_to_host
135 struct __attribute__((packed
)) cio_rename_from_host
137 /* Result (little endian). */
141 struct __attribute__((packed
)) cio_gettime_to_host
146 struct __attribute__((packed
)) cio_gettime_from_host
148 /* Time (little endian). */
152 struct __attribute__((packed
)) cio_getclk_to_host
157 struct __attribute__((packed
)) cio_getclk_from_host
159 /* Clock cycles (little endian). */
163 struct __attribute__((packed
)) cio_to_host
165 /* Data length (target endian). */
168 unsigned char command
;
172 unsigned char buf
[8];
173 struct cio_open_to_host open
;
174 struct cio_close_to_host close
;
175 struct cio_read_to_host read
;
176 struct cio_write_to_host write
;
177 struct cio_lseek_to_host lseek
;
178 struct cio_unlink_to_host unlink
;
179 struct cio_rename_to_host rename
;
180 struct cio_gettime_to_host gettime
;
181 struct cio_getclk_to_host getclk
;
183 /* Variable-length data. */
184 unsigned char data
[];
187 struct __attribute__((packed
)) cio_from_host
189 /* Length (target endian). */
194 unsigned char buf
[8];
195 struct cio_open_from_host open
;
196 struct cio_close_from_host close
;
197 struct cio_read_from_host read
;
198 struct cio_write_from_host write
;
199 struct cio_lseek_from_host lseek
;
200 struct cio_unlink_from_host unlink
;
201 struct cio_rename_from_host rename
;
202 struct cio_gettime_from_host gettime
;
203 struct cio_getclk_from_host getclk
;
206 unsigned char data
[];
211 unsigned char buf
[CIOBUFSIZ
];
215 struct cio_to_host to_host
;
216 struct cio_from_host from_host
;
218 } _CIOBUF_
__attribute__((section(".cio")));
221 #define SWAPSHORT(s) ((short)((((s) & 0xff) << 8) | (((s) & 0xff00) >> 8)))
222 #define SWAPINT(i) (__builtin_bswap32 (i))
224 #define SWAPSHORT(s) (s)
225 #define SWAPINT(i) (i)
228 static void __attribute__((noinline
))
231 asm volatile (".globl C$$IO$$\nnop\nC$$IO$$:nop" : "+m" (_CIOBUF_
));
235 semi_call_wrapper (unsigned char command
, const char *data
,
238 _CIOBUF_
.u
.to_host
.length
= length
;
239 _CIOBUF_
.u
.to_host
.command
= command
;
241 memcpy (_CIOBUF_
.u
.to_host
.data
, data
, length
);
246 semi_call_wrapper2 (unsigned char command
, const char *data1
,
247 unsigned int length1
, const char *data2
,
248 unsigned int length2
)
250 _CIOBUF_
.u
.to_host
.length
= length1
+ length2
;
251 _CIOBUF_
.u
.to_host
.command
= command
;
253 memcpy (_CIOBUF_
.u
.to_host
.data
, data1
, length1
);
255 memcpy (_CIOBUF_
.u
.to_host
.data
+ length1
, data2
, length2
);
262 /* The semihosting interface appears to provide no way to return an
264 asm volatile (".globl C$$EXIT\nnop\nC$$EXIT:nop");
268 open (const char *path
, int flags
, ...)
270 /* ??? It's not clear what the suggested fd is for. */
271 static short suggest_fd
= 3;
274 _CIOBUF_
.u
.to_host
.parms
.open
.fd
= SWAPSHORT (suggest_fd
);
275 _CIOBUF_
.u
.to_host
.parms
.open
.flags
= SWAPSHORT (flags
);
276 semi_call_wrapper (_DTOPEN
, path
, strlen (path
) + 1);
277 ret_fd
= SWAPSHORT (_CIOBUF_
.u
.from_host
.parms
.open
.fd
);
286 _CIOBUF_
.u
.to_host
.parms
.close
.fd
= SWAPSHORT (fd
);
287 semi_call_wrapper (_DTCLOSE
, NULL
, 0);
288 return SWAPSHORT (_CIOBUF_
.u
.from_host
.parms
.close
.result
);
292 read (int fd
, char *ptr
, int len
)
296 _CIOBUF_
.u
.to_host
.parms
.read
.fd
= SWAPSHORT (fd
);
297 _CIOBUF_
.u
.to_host
.parms
.read
.length
= SWAPSHORT (len
);
298 semi_call_wrapper (_DTREAD
, NULL
, 0);
299 memcpy (ptr
, _CIOBUF_
.u
.from_host
.data
, _CIOBUF_
.u
.from_host
.length
);
300 return SWAPSHORT (_CIOBUF_
.u
.from_host
.parms
.read
.result
);
304 write (int fd
, char *ptr
, int len
)
308 _CIOBUF_
.u
.to_host
.parms
.write
.fd
= SWAPSHORT (fd
);
309 _CIOBUF_
.u
.to_host
.parms
.write
.length
= SWAPSHORT (len
);
310 semi_call_wrapper (_DTWRITE
, ptr
, len
);
311 return SWAPSHORT (_CIOBUF_
.u
.from_host
.parms
.write
.result
);
315 lseek (int fd
, int offset
, int whence
)
317 _CIOBUF_
.u
.to_host
.parms
.lseek
.fd
= SWAPSHORT (fd
);
318 _CIOBUF_
.u
.to_host
.parms
.lseek
.offset
= SWAPINT (offset
);
319 _CIOBUF_
.u
.to_host
.parms
.lseek
.whence
= SWAPSHORT (whence
);
320 semi_call_wrapper (_DTLSEEK
, NULL
, 0);
321 return SWAPINT (_CIOBUF_
.u
.from_host
.parms
.lseek
.result
);
325 unlink (const char *path
)
327 semi_call_wrapper (_DTUNLINK
, path
, strlen (path
) + 1);
328 return SWAPSHORT (_CIOBUF_
.u
.from_host
.parms
.unlink
.result
);
332 rename (const char *oldpath
, const char *newpath
)
334 semi_call_wrapper2 (_DTRENAME
, oldpath
, strlen (oldpath
) + 1,
335 newpath
, strlen (newpath
) + 1);
336 return SWAPSHORT (_CIOBUF_
.u
.from_host
.parms
.rename
.result
);
340 gettimeofday (struct timeval
*tp
, void *tzvp
)
342 struct timezone
*tzp
= tzvp
;
346 semi_call_wrapper (_DTGETTIME
, NULL
, 0);
347 tp
->tv_sec
= SWAPINT (_CIOBUF_
.u
.from_host
.parms
.gettime
.time
);
353 tzp
->tz_minuteswest
= 0;
363 semi_call_wrapper (_DTGETCLK
, NULL
, 0);
364 return SWAPINT (_CIOBUF_
.u
.from_host
.parms
.getclk
.result
);
369 isatty (int file
__attribute__((unused
)))
376 fstat (int fd
, struct stat
*buf
)
378 buf
->st_mode
= S_IFCHR
; /* Always pretend to be a tty */