1 /*
2 		    Language Independent Library
3 
4 	    Copyright 1983-2009 Green Hills Software,Inc.
5 
6  *  This program is the property of Green Hills Software, Inc,
7  *  its contents are proprietary information and no part of it
8  *  is to be disclosed to anyone except employees of Green Hills
9  *  Software, Inc., or as agreed in writing signed by the President
10  *  of Green Hills Software, Inc.
11 */
12 /* ind_io.c: core set of low-level I/O functions. Machine Independent. */
13 
14 /*
15  * This module, and ind_exit.c, contain the lowest level I/O functions in the
16  * Green Hills C library.  These functions provide a very simple UNIX-like
17  * system call interface.
18  *
19  * The default implementations provided here all call down to __ghs_syscall()
20  * in the ind_call.* assembly file. This expects the environment to trap calls
21  * to __dotsyscall in the ".syscall" section, which contains a NOP that may be
22  * patched by software debuggers or triggered by hardware debuggers. If nothing
23  * happens, __ghs_syscall() returns a generic -1 and sets the C "errno" to 0.
24  *
25  * Please see the Green Hills C Library Documentation for complete directions
26  * as to how to customize this module for your system.  The most essential
27  * group of functions appears in ind_exit.c (for size reasons), with more
28  * optional groups of functions appearing later in this file.
29  *
30  * All functions have been have are weak symbols.  This is done so that any
31  * or all of the functions can be redefined by the user from a separate
32  * object file, and not result in multiply-defined symbol problems from the
33  * linker.
34  *
35  * MEMORY ALLOCATION: low-level memory allocation is now done in ind_heap.c
36 */
37 
38 #if defined(EMBEDDED)
39 
40 #if 1 // CAFE MOD
41 #include <cafe/os.h>
42 #endif // CAFE MOD
43 
44 #include "indos.h"
45 #include "ind_io.h"
46 
47 #if (__CHAR_BIT > 8) || 1
48 #  define DO_OPEN_CREAT_MODE
49 #endif
50 
51 #if defined(DO_OPEN_CREAT_MODE)
52 #include <stdarg.h>
53 #endif
54 
55 /*============================================================================*/
56 /*	FUNCTIONS NEEDED TO PRINT OUT HELLO WORLD AND ENTER SIMPLE INPUT      */
57 /*============================================================================*/
58 /*	write()		output an array of characters to a file descriptor    */
59 /*	read()		input an array of characters from a file descriptor   */
60 /*============================================================================*/
61 
62 /******************************************************************************/
63 /*  int write (int fno, const void *buf, int size);			      */
64 /*  Write at most size bytes into the file connected to fno (where fno is     */
65 /*  one of the file numbers returned by open() or creat()) into buf.	      */
66 /*  Return the number of bytes written, or -1 to indicate an error and	      */
67 /*  set errno appropriately.						      */
68 /*									      */
69 /*  Note that line breaks have not received any special processing.  If you   */
70 /*  are reimplementing this to talk to a serial port and a terminal, you will */
71 /*  need to output a "\r\n" sequence for each '\n' in the character array.    */
72 /*  The typical symptom that this is necessary is "barber pole" text output.  */
73 /******************************************************************************/
74 #pragma weak write=__ghs_hostio_write
75 
76 #if 1 // CAFE MOD
__ghs_hostio_write(int fno,const void * buf,int size)77 int __ghs_hostio_write (int fno, const void *buf, int size)
78 {
79     if (fno == 1 || fno == 2) {
80         OSConsoleWrite(buf, size);
81         return size;
82     } else {
83 #pragma ghs nowarning 1547	/* Syscall prototype problems */
84     return __ghs_syscall(SYSCALL_WRITE, fno, buf, size);
85 #pragma ghs endnowarning 1547
86     }
87 }
88 #endif // CAFE MOD
89 
90 #if 0 // CAFE GHS ORIG
91 int __ghs_hostio_write (int fno, const void *buf, int size)
92 {
93 #pragma ghs nowarning 1547	/* Syscall prototype problems */
94     return __ghs_syscall(SYSCALL_WRITE, fno, buf, size);
95 #pragma ghs endnowarning 1547
96 }
97 #endif // CAFE GHS ORIG
98 
99 /******************************************************************************/
100 /* int read (int fno, void *buf, int size);				      */
101 /*  Read at most size bytes into buf from the file connected to fno (where    */
102 /*  fno is one of the file numbers returned by open() or creat()).	      */
103 /*  Return the number of bytes read.  Return 0 at end of file.  Return -1 on  */
104 /*  error and set errno appropriately.					      */
105 /*									      */
106 /*  The stdio libraries assume that (as on unix) line breaks are converted to */
107 /*  single '\n' characters by the time read() returns success. If you are     */
108 /*  taking characters from a terminal, replace any '\r' you see with a '\n'.  */
109 /******************************************************************************/
110 #pragma weak read=__ghs_hostio_read
__ghs_hostio_read(int fno,void * buf,int size)111 int __ghs_hostio_read (int fno, void *buf, int size)
112 {
113 #pragma ghs nowarning 1547	/* Syscall prototype problems */
114     return __ghs_syscall(SYSCALL_READ, fno, buf, size);
115 #pragma ghs endnowarning 1547
116 }
117 
118 /*============================================================================*/
119 /*	  FUNCTIONS NEEDED TO USE THE HOST FILESYSTEM FROM YOUR TARGET	      */
120 /*============================================================================*/
121 /*	open()		start using a file				      */
122 /*	creat()		create a new file and start using it		      */
123 /*	close()		stop using a file				      */
124 /*	lseek()		move around in a file				      */
125 /*	unlink()	delete a file on the host (!!) (be careful!)	      */
126 /*	fcntl()		do evil things to the file descriptor (avoid this)    */
127 /*============================================================================*/
128 
129 /******************************************************************************/
130 /* int open (const char *filename, int mode, ...);			      */
131 /*  Open the file named filename with the indicated mode.		      */
132 /*  filename is a null terminated string and mode is one of the following     */
133 /*									      */
134 /*	0	=> open for reading					      */
135 /*	1	=> open for writing					      */
136 /*	2	=> open for reading & writing				      */
137 /*									      */
138 /*  If the open is successful return a small non-negative integer file number.*/
139 /*  On failure return -1, and set errno in accordance with the error.	      */
140 /******************************************************************************/
141 #pragma ghs nowarning 236 /* va_arg() "controlling expression is constant" */
142 #pragma weak open=__ghs_hostio_open
__ghs_hostio_open(const char * filename,int flags,...)143 int __ghs_hostio_open (const char *filename, int flags, ...)
144 {
145     if(flags & O_CREAT) {
146 	int mode;
147 #if defined(DO_OPEN_CREAT_MODE)
148 	va_list va;
149 
150 	va_start(va, flags);
151 
152 	mode = va_arg(va, int);
153 
154 	va_end(va);
155 #else
156 	mode = 066;
157 #endif
158 #pragma ghs nowarning 1547	/* Syscall prototype problems */
159 	return __ghs_syscall(SYSCALL_OPEN2, filename, flags, mode);
160 #pragma ghs endnowarning 1547
161     } else {
162 #pragma ghs nowarning 1547	/* Syscall prototype problems */
163 	return __ghs_syscall(SYSCALL_OPEN, filename, flags);
164 #pragma ghs endnowarning 1547
165     }
166 }
167 
168 /******************************************************************************/
169 /* int creat (const char *filename, int prot);				      */
170 /*  Create and open for writing a file named filename with protection	      */
171 /*  as specified by prot.  filename is a null terminated string.	      */
172 /*  prot is expressed in unix format, it is the logical or of:		      */
173 /*									      */
174 /*		0400: owner read 					      */
175 /*		0200: owner write					      */
176 /*		0100: owner execute/search directory			      */
177 /*		0040: group read					      */
178 /*		0020: group write					      */
179 /*		0010: group execute/search directory			      */
180 /*		0004: other (world) read				      */
181 /*		0002: other (world) write				      */
182 /*		0001: other (world) execute/search directory		      */
183 /*									      */
184 /*  For things like terminals that cannot be created it should just open the  */
185 /*  device.  If successful, return a small integer file number.  On failure   */
186 /*  return -1 and set errno appropriately.				      */
187 /******************************************************************************/
188 #pragma weak creat=__ghs_hostio_creat
__ghs_hostio_creat(const char * filename,int prot)189 int __ghs_hostio_creat (const char *filename, int prot)
190 {
191 #pragma ghs nowarning 1547	/* Syscall prototype problems */
192     return __ghs_syscall(SYSCALL_CREAT, filename, prot);
193 #pragma ghs endnowarning 1547
194 }
195 
196 /******************************************************************************/
197 /* int close (int fno);							      */
198 /*  Close the file associated with the file number fno (returned by open()    */
199 /*  or creat()).  Return 0 if all goes well.  Return -1 if something went     */
200 /*  wrong and set errno appropriately.					      */
201 /******************************************************************************/
202 #pragma weak close=__ghs_hostio_close
__ghs_hostio_close(int fno)203 int __ghs_hostio_close (int fno)
204 {
205 #pragma ghs nowarning 1547	/* Syscall prototype problems */
206     return __ghs_syscall(SYSCALL_CLOSE, fno);
207 #pragma ghs endnowarning 1547
208 }
209 
210 /******************************************************************************/
211 /* long lseek (int fno, long offset, int end);				      */
212 /*  Seek to a new position within the file connected to the file number fno   */
213 /*  (returned by open() or creat()).  If end is 0, seek to offset bytes from  */
214 /*  the beginning of the file.  If end is 1, seek to offset bytes from the    */
215 /*  current position in the file.  If end is 2 seek to offset bytes from      */
216 /*  the end of the file.  lseek does no I/O.  The next I/O operation to	      */
217 /*  file number fno will begin at the new position in the file.		      */
218 /*									      */
219 /*  Return the offset from the beginning of the file after the seek takes     */
220 /*  place.  If an error occurs return -1 and set errno appropriately.	      */
221 /*  If an error occurs the file position is not changed.		      */
222 /******************************************************************************/
223 #pragma weak lseek=__ghs_hostio_lseek
__ghs_hostio_lseek(int fno,off_t offset,int end)224 off_t __ghs_hostio_lseek (int fno, off_t offset, int end)
225 {
226 #pragma ghs nowarning 1547	/* Syscall prototype problems */
227     return __ghs_syscall(SYSCALL_LSEEK, fno, (long)offset, end);
228 #pragma ghs endnowarning 1547
229 }
230 
231 /******************************************************************************/
232 /*  int unlink (const char *name);					      */
233 /*									      */
234 /*  name is the name of a file.  The named file is deleted.		      */
235 /*  Return 0 if the named file is deleted.  Return -1 if there is no such     */
236 /*  file or if the file cannot be deleted, and set errno appropriately.	      */
237 /******************************************************************************/
238 #pragma weak unlink=__ghs_hostio_unlink
__ghs_hostio_unlink(const char * name)239 int __ghs_hostio_unlink (const char *name)
240 {
241 #pragma ghs nowarning 1547	/* Syscall prototype problems */
242     return __ghs_syscall(SYSCALL_UNLINK, name);
243 #pragma ghs endnowarning 1547
244 }
245 
246 /******************************************************************************/
247 /* int fcntl (int fno, int cmd, int arg);				      */
248 /* When running under a Green Hills debugger, calls the host fcntl() function */
249 /* with the specified arguments.  NO VALIDATION OR TRANSLATION IS PERFORMED.  */
250 /* This call was added for use by C++ libraries only and should be avoided    */
251 /* because the argument values may vary from host to host.		      */
252 /*									      */
253 /*  Return the value which was returned by the host fcntl() call.             */
254 /*  If an error occurs return -1 and set errno appropriately.		      */
255 /******************************************************************************/
256 #pragma weak fcntl=__ghs_hostio_fcntl
__ghs_hostio_fcntl(int fno,int cmd,int arg)257 int __ghs_hostio_fcntl (int fno, int cmd, int arg)
258 {
259 #pragma ghs nowarning 1547	/* Syscall prototype problems */
260     return __ghs_syscall(SYSCALL_FCNTL, fno, cmd, arg);
261 #pragma ghs endnowarning 1547
262 }
263 #endif	/* EMBEDDED */
264