xref: /openbmc/u-boot/api/api.c (revision a2a5729f)
1500856ebSRafal Jaworowski /*
2500856ebSRafal Jaworowski  * (C) Copyright 2007 Semihalf
3500856ebSRafal Jaworowski  *
4500856ebSRafal Jaworowski  * Written by: Rafal Jaworowski <raj@semihalf.com>
5500856ebSRafal Jaworowski  *
6500856ebSRafal Jaworowski  * See file CREDITS for list of people who contributed to this
7500856ebSRafal Jaworowski  * project.
8500856ebSRafal Jaworowski  *
9500856ebSRafal Jaworowski  * This program is free software; you can redistribute it and/or
10500856ebSRafal Jaworowski  * modify it under the terms of the GNU General Public License as
11500856ebSRafal Jaworowski  * published by the Free Software Foundation; either version 2 of
12500856ebSRafal Jaworowski  * the License, or (at your option) any later version.
13500856ebSRafal Jaworowski  *
14500856ebSRafal Jaworowski  * This program is distributed in the hope that it will be useful,
15500856ebSRafal Jaworowski  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16500856ebSRafal Jaworowski  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17500856ebSRafal Jaworowski  * GNU General Public License for more details.
18500856ebSRafal Jaworowski  *
19500856ebSRafal Jaworowski  * You should have received a copy of the GNU General Public License
20500856ebSRafal Jaworowski  * along with this program; if not, write to the Free Software
21500856ebSRafal Jaworowski  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22500856ebSRafal Jaworowski  * MA 02111-1307 USA
23500856ebSRafal Jaworowski  *
24500856ebSRafal Jaworowski  */
25500856ebSRafal Jaworowski 
26500856ebSRafal Jaworowski #include <config.h>
27500856ebSRafal Jaworowski #include <command.h>
28500856ebSRafal Jaworowski #include <common.h>
29500856ebSRafal Jaworowski #include <malloc.h>
30a8409f4fSWolfgang Denk #include <environment.h>
31500856ebSRafal Jaworowski #include <linux/types.h>
32500856ebSRafal Jaworowski #include <api_public.h>
33500856ebSRafal Jaworowski 
34500856ebSRafal Jaworowski #include "api_private.h"
35500856ebSRafal Jaworowski 
36500856ebSRafal Jaworowski #define DEBUG
37500856ebSRafal Jaworowski #undef DEBUG
38500856ebSRafal Jaworowski 
39500856ebSRafal Jaworowski /*****************************************************************************
40500856ebSRafal Jaworowski  *
41500856ebSRafal Jaworowski  * This is the API core.
42500856ebSRafal Jaworowski  *
43500856ebSRafal Jaworowski  * API_ functions are part of U-Boot code and constitute the lowest level
44500856ebSRafal Jaworowski  * calls:
45500856ebSRafal Jaworowski  *
46500856ebSRafal Jaworowski  *  - they know what values they need as arguments
47500856ebSRafal Jaworowski  *  - their direct return value pertains to the API_ "shell" itself (0 on
48500856ebSRafal Jaworowski  *    success, some error code otherwise)
49500856ebSRafal Jaworowski  *  - if the call returns a value it is buried within arguments
50500856ebSRafal Jaworowski  *
51500856ebSRafal Jaworowski  ****************************************************************************/
52500856ebSRafal Jaworowski 
53500856ebSRafal Jaworowski #ifdef DEBUG
54500856ebSRafal Jaworowski #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
55500856ebSRafal Jaworowski #else
56500856ebSRafal Jaworowski #define debugf(fmt, args...)
57500856ebSRafal Jaworowski #endif
58500856ebSRafal Jaworowski 
59500856ebSRafal Jaworowski typedef	int (*cfp_t)(va_list argp);
60500856ebSRafal Jaworowski 
61500856ebSRafal Jaworowski static int calls_no;
62500856ebSRafal Jaworowski 
63500856ebSRafal Jaworowski /*
64500856ebSRafal Jaworowski  * pseudo signature:
65500856ebSRafal Jaworowski  *
66500856ebSRafal Jaworowski  * int API_getc(int *c)
67500856ebSRafal Jaworowski  */
68500856ebSRafal Jaworowski static int API_getc(va_list ap)
69500856ebSRafal Jaworowski {
70500856ebSRafal Jaworowski 	int *c;
71500856ebSRafal Jaworowski 
72500856ebSRafal Jaworowski 	if ((c = (int *)va_arg(ap, u_int32_t)) == NULL)
73500856ebSRafal Jaworowski 		return API_EINVAL;
74500856ebSRafal Jaworowski 
75500856ebSRafal Jaworowski 	*c = getc();
76500856ebSRafal Jaworowski 	return 0;
77500856ebSRafal Jaworowski }
78500856ebSRafal Jaworowski 
79500856ebSRafal Jaworowski /*
80500856ebSRafal Jaworowski  * pseudo signature:
81500856ebSRafal Jaworowski  *
82500856ebSRafal Jaworowski  * int API_tstc(int *c)
83500856ebSRafal Jaworowski  */
84500856ebSRafal Jaworowski static int API_tstc(va_list ap)
85500856ebSRafal Jaworowski {
86500856ebSRafal Jaworowski 	int *t;
87500856ebSRafal Jaworowski 
88500856ebSRafal Jaworowski 	if ((t = (int *)va_arg(ap, u_int32_t)) == NULL)
89500856ebSRafal Jaworowski 		return API_EINVAL;
90500856ebSRafal Jaworowski 
91500856ebSRafal Jaworowski 	*t = tstc();
92500856ebSRafal Jaworowski 	return 0;
93500856ebSRafal Jaworowski }
94500856ebSRafal Jaworowski 
95500856ebSRafal Jaworowski /*
96500856ebSRafal Jaworowski  * pseudo signature:
97500856ebSRafal Jaworowski  *
98500856ebSRafal Jaworowski  * int API_putc(char *ch)
99500856ebSRafal Jaworowski  */
100500856ebSRafal Jaworowski static int API_putc(va_list ap)
101500856ebSRafal Jaworowski {
102500856ebSRafal Jaworowski 	char *c;
103500856ebSRafal Jaworowski 
104500856ebSRafal Jaworowski 	if ((c = (char *)va_arg(ap, u_int32_t)) == NULL)
105500856ebSRafal Jaworowski 		return API_EINVAL;
106500856ebSRafal Jaworowski 
107500856ebSRafal Jaworowski 	putc(*c);
108500856ebSRafal Jaworowski 	return 0;
109500856ebSRafal Jaworowski }
110500856ebSRafal Jaworowski 
111500856ebSRafal Jaworowski /*
112500856ebSRafal Jaworowski  * pseudo signature:
113500856ebSRafal Jaworowski  *
114500856ebSRafal Jaworowski  * int API_puts(char **s)
115500856ebSRafal Jaworowski  */
116500856ebSRafal Jaworowski static int API_puts(va_list ap)
117500856ebSRafal Jaworowski {
118500856ebSRafal Jaworowski 	char *s;
119500856ebSRafal Jaworowski 
120500856ebSRafal Jaworowski 	if ((s = (char *)va_arg(ap, u_int32_t)) == NULL)
121500856ebSRafal Jaworowski 		return API_EINVAL;
122500856ebSRafal Jaworowski 
123500856ebSRafal Jaworowski 	puts(s);
124500856ebSRafal Jaworowski 	return 0;
125500856ebSRafal Jaworowski }
126500856ebSRafal Jaworowski 
127500856ebSRafal Jaworowski /*
128500856ebSRafal Jaworowski  * pseudo signature:
129500856ebSRafal Jaworowski  *
130500856ebSRafal Jaworowski  * int API_reset(void)
131500856ebSRafal Jaworowski  */
132500856ebSRafal Jaworowski static int API_reset(va_list ap)
133500856ebSRafal Jaworowski {
134500856ebSRafal Jaworowski 	do_reset(NULL, 0, 0, NULL);
135500856ebSRafal Jaworowski 
136500856ebSRafal Jaworowski 	/* NOT REACHED */
137500856ebSRafal Jaworowski 	return 0;
138500856ebSRafal Jaworowski }
139500856ebSRafal Jaworowski 
140500856ebSRafal Jaworowski /*
141500856ebSRafal Jaworowski  * pseudo signature:
142500856ebSRafal Jaworowski  *
143500856ebSRafal Jaworowski  * int API_get_sys_info(struct sys_info *si)
144500856ebSRafal Jaworowski  *
145500856ebSRafal Jaworowski  * fill out the sys_info struct containing selected parameters about the
146500856ebSRafal Jaworowski  * machine
147500856ebSRafal Jaworowski  */
148500856ebSRafal Jaworowski static int API_get_sys_info(va_list ap)
149500856ebSRafal Jaworowski {
150500856ebSRafal Jaworowski 	struct sys_info *si;
151500856ebSRafal Jaworowski 
152500856ebSRafal Jaworowski 	si = (struct sys_info *)va_arg(ap, u_int32_t);
153500856ebSRafal Jaworowski 	if (si == NULL)
154500856ebSRafal Jaworowski 		return API_ENOMEM;
155500856ebSRafal Jaworowski 
156500856ebSRafal Jaworowski 	return (platform_sys_info(si)) ? 0 : API_ENODEV;
157500856ebSRafal Jaworowski }
158500856ebSRafal Jaworowski 
159500856ebSRafal Jaworowski /*
160500856ebSRafal Jaworowski  * pseudo signature:
161500856ebSRafal Jaworowski  *
162500856ebSRafal Jaworowski  * int API_udelay(unsigned long *udelay)
163500856ebSRafal Jaworowski  */
164500856ebSRafal Jaworowski static int API_udelay(va_list ap)
165500856ebSRafal Jaworowski {
166500856ebSRafal Jaworowski 	unsigned long *d;
167500856ebSRafal Jaworowski 
168500856ebSRafal Jaworowski 	if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL)
169500856ebSRafal Jaworowski 		return API_EINVAL;
170500856ebSRafal Jaworowski 
171500856ebSRafal Jaworowski 	udelay(*d);
172500856ebSRafal Jaworowski 	return 0;
173500856ebSRafal Jaworowski }
174500856ebSRafal Jaworowski 
175500856ebSRafal Jaworowski /*
176500856ebSRafal Jaworowski  * pseudo signature:
177500856ebSRafal Jaworowski  *
178500856ebSRafal Jaworowski  * int API_get_timer(unsigned long *current, unsigned long *base)
179500856ebSRafal Jaworowski  */
180500856ebSRafal Jaworowski static int API_get_timer(va_list ap)
181500856ebSRafal Jaworowski {
182500856ebSRafal Jaworowski 	unsigned long *base, *cur;
183500856ebSRafal Jaworowski 
184500856ebSRafal Jaworowski 	cur = (unsigned long *)va_arg(ap, u_int32_t);
185500856ebSRafal Jaworowski 	if (cur == NULL)
186500856ebSRafal Jaworowski 		return API_EINVAL;
187500856ebSRafal Jaworowski 
188500856ebSRafal Jaworowski 	base = (unsigned long *)va_arg(ap, u_int32_t);
189500856ebSRafal Jaworowski 	if (base == NULL)
190500856ebSRafal Jaworowski 		return API_EINVAL;
191500856ebSRafal Jaworowski 
192500856ebSRafal Jaworowski 	*cur = get_timer(*base);
193500856ebSRafal Jaworowski 	return 0;
194500856ebSRafal Jaworowski }
195500856ebSRafal Jaworowski 
196500856ebSRafal Jaworowski 
197500856ebSRafal Jaworowski /*****************************************************************************
198500856ebSRafal Jaworowski  *
199500856ebSRafal Jaworowski  * pseudo signature:
200500856ebSRafal Jaworowski  *
201500856ebSRafal Jaworowski  * int API_dev_enum(struct device_info *)
202500856ebSRafal Jaworowski  *
203500856ebSRafal Jaworowski  *
204500856ebSRafal Jaworowski  * cookies uniqely identify the previously enumerated device instance and
205500856ebSRafal Jaworowski  * provide a hint for what to inspect in current enum iteration:
206500856ebSRafal Jaworowski  *
207500856ebSRafal Jaworowski  *   - net: &eth_device struct address from list pointed to by eth_devices
208500856ebSRafal Jaworowski  *
209500856ebSRafal Jaworowski  *   - storage: block_dev_desc_t struct address from &ide_dev_desc[n],
210500856ebSRafal Jaworowski  *     &scsi_dev_desc[n] and similar tables
211500856ebSRafal Jaworowski  *
212500856ebSRafal Jaworowski  ****************************************************************************/
213500856ebSRafal Jaworowski 
214500856ebSRafal Jaworowski static int API_dev_enum(va_list ap)
215500856ebSRafal Jaworowski {
216500856ebSRafal Jaworowski 	struct device_info *di;
217500856ebSRafal Jaworowski 
218500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct we are going to fill out */
219500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
220500856ebSRafal Jaworowski 	if (di == NULL)
221500856ebSRafal Jaworowski 		return API_EINVAL;
222500856ebSRafal Jaworowski 
223500856ebSRafal Jaworowski 	if (di->cookie == NULL) {
224500856ebSRafal Jaworowski 		/* start over - clean up enumeration */
225500856ebSRafal Jaworowski 		dev_enum_reset();	/* XXX shouldn't the name contain 'stor'? */
226500856ebSRafal Jaworowski 		debugf("RESTART ENUM\n");
227500856ebSRafal Jaworowski 
228500856ebSRafal Jaworowski 		/* net device enumeration first */
229500856ebSRafal Jaworowski 		if (dev_enum_net(di))
230500856ebSRafal Jaworowski 			return 0;
231500856ebSRafal Jaworowski 	}
232500856ebSRafal Jaworowski 
233500856ebSRafal Jaworowski 	/*
234500856ebSRafal Jaworowski 	 * The hidden assumption is there can only be one active network
235500856ebSRafal Jaworowski 	 * device and it is identified upon enumeration (re)start, so there's
236500856ebSRafal Jaworowski 	 * no point in trying to find network devices in other cases than the
237500856ebSRafal Jaworowski 	 * (re)start and hence the 'next' device can only be storage
238500856ebSRafal Jaworowski 	 */
239500856ebSRafal Jaworowski 	if (!dev_enum_storage(di))
240500856ebSRafal Jaworowski 		/* make sure we mark there are no more devices */
241500856ebSRafal Jaworowski 		di->cookie = NULL;
242500856ebSRafal Jaworowski 
243500856ebSRafal Jaworowski 	return 0;
244500856ebSRafal Jaworowski }
245500856ebSRafal Jaworowski 
246500856ebSRafal Jaworowski 
247500856ebSRafal Jaworowski static int API_dev_open(va_list ap)
248500856ebSRafal Jaworowski {
249500856ebSRafal Jaworowski 	struct device_info *di;
250500856ebSRafal Jaworowski 	int err = 0;
251500856ebSRafal Jaworowski 
252500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct */
253500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
254500856ebSRafal Jaworowski 	if (di == NULL)
255500856ebSRafal Jaworowski 		return API_EINVAL;
256500856ebSRafal Jaworowski 
257500856ebSRafal Jaworowski 	/* Allow only one consumer of the device at a time */
258500856ebSRafal Jaworowski 	if (di->state == DEV_STA_OPEN)
259500856ebSRafal Jaworowski 		return API_EBUSY;
260500856ebSRafal Jaworowski 
261500856ebSRafal Jaworowski 	if (di->cookie == NULL)
262500856ebSRafal Jaworowski 		return API_ENODEV;
263500856ebSRafal Jaworowski 
264500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
265500856ebSRafal Jaworowski 		err = dev_open_stor(di->cookie);
266500856ebSRafal Jaworowski 
267500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
268500856ebSRafal Jaworowski 		err = dev_open_net(di->cookie);
269500856ebSRafal Jaworowski 	else
270500856ebSRafal Jaworowski 		err = API_ENODEV;
271500856ebSRafal Jaworowski 
272500856ebSRafal Jaworowski 	if (!err)
273500856ebSRafal Jaworowski 		di->state = DEV_STA_OPEN;
274500856ebSRafal Jaworowski 
275500856ebSRafal Jaworowski 	return err;
276500856ebSRafal Jaworowski }
277500856ebSRafal Jaworowski 
278500856ebSRafal Jaworowski 
279500856ebSRafal Jaworowski static int API_dev_close(va_list ap)
280500856ebSRafal Jaworowski {
281500856ebSRafal Jaworowski 	struct device_info *di;
282500856ebSRafal Jaworowski 	int err = 0;
283500856ebSRafal Jaworowski 
284500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct */
285500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
286500856ebSRafal Jaworowski 	if (di == NULL)
287500856ebSRafal Jaworowski 		return API_EINVAL;
288500856ebSRafal Jaworowski 
289500856ebSRafal Jaworowski 	if (di->state == DEV_STA_CLOSED)
290500856ebSRafal Jaworowski 		return 0;
291500856ebSRafal Jaworowski 
292500856ebSRafal Jaworowski 	if (di->cookie == NULL)
293500856ebSRafal Jaworowski 		return API_ENODEV;
294500856ebSRafal Jaworowski 
295500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
296500856ebSRafal Jaworowski 		err = dev_close_stor(di->cookie);
297500856ebSRafal Jaworowski 
298500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
299500856ebSRafal Jaworowski 		err = dev_close_net(di->cookie);
300500856ebSRafal Jaworowski 	else
301500856ebSRafal Jaworowski 		/*
302500856ebSRafal Jaworowski 		 * In case of unknown device we cannot change its state, so
303500856ebSRafal Jaworowski 		 * only return error code
304500856ebSRafal Jaworowski 		 */
305500856ebSRafal Jaworowski 		err = API_ENODEV;
306500856ebSRafal Jaworowski 
307500856ebSRafal Jaworowski 	if (!err)
308500856ebSRafal Jaworowski 		di->state = DEV_STA_CLOSED;
309500856ebSRafal Jaworowski 
310500856ebSRafal Jaworowski 	return err;
311500856ebSRafal Jaworowski }
312500856ebSRafal Jaworowski 
313500856ebSRafal Jaworowski 
314500856ebSRafal Jaworowski /*
315500856ebSRafal Jaworowski  * Notice: this is for sending network packets only, as U-Boot does not
316500856ebSRafal Jaworowski  * support writing to storage at the moment (12.2007)
317500856ebSRafal Jaworowski  *
318500856ebSRafal Jaworowski  * pseudo signature:
319500856ebSRafal Jaworowski  *
320500856ebSRafal Jaworowski  * int API_dev_write(
321500856ebSRafal Jaworowski  *	struct device_info *di,
322500856ebSRafal Jaworowski  *	void *buf,
323500856ebSRafal Jaworowski  *	int *len
324500856ebSRafal Jaworowski  * )
325500856ebSRafal Jaworowski  *
326500856ebSRafal Jaworowski  * buf:	ptr to buffer from where to get the data to send
327500856ebSRafal Jaworowski  *
328500856ebSRafal Jaworowski  * len: length of packet to be sent (in bytes)
329500856ebSRafal Jaworowski  *
330500856ebSRafal Jaworowski  */
331500856ebSRafal Jaworowski static int API_dev_write(va_list ap)
332500856ebSRafal Jaworowski {
333500856ebSRafal Jaworowski 	struct device_info *di;
334500856ebSRafal Jaworowski 	void *buf;
335500856ebSRafal Jaworowski 	int *len;
336500856ebSRafal Jaworowski 	int err = 0;
337500856ebSRafal Jaworowski 
338500856ebSRafal Jaworowski 	/* 1. arg is ptr to the device_info struct */
339500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
340500856ebSRafal Jaworowski 	if (di == NULL)
341500856ebSRafal Jaworowski 		return API_EINVAL;
342500856ebSRafal Jaworowski 
343500856ebSRafal Jaworowski 	/* XXX should we check if device is open? i.e. the ->state ? */
344500856ebSRafal Jaworowski 
345500856ebSRafal Jaworowski 	if (di->cookie == NULL)
346500856ebSRafal Jaworowski 		return API_ENODEV;
347500856ebSRafal Jaworowski 
348500856ebSRafal Jaworowski 	/* 2. arg is ptr to buffer from where to get data to write */
349500856ebSRafal Jaworowski 	buf = (void *)va_arg(ap, u_int32_t);
350500856ebSRafal Jaworowski 	if (buf == NULL)
351500856ebSRafal Jaworowski 		return API_EINVAL;
352500856ebSRafal Jaworowski 
353500856ebSRafal Jaworowski 	/* 3. arg is length of buffer */
354500856ebSRafal Jaworowski 	len = (int *)va_arg(ap, u_int32_t);
355500856ebSRafal Jaworowski 	if (len == NULL)
356500856ebSRafal Jaworowski 		return API_EINVAL;
357500856ebSRafal Jaworowski 	if (*len <= 0)
358500856ebSRafal Jaworowski 		return API_EINVAL;
359500856ebSRafal Jaworowski 
360500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
361500856ebSRafal Jaworowski 		/*
362500856ebSRafal Jaworowski 		 * write to storage is currently not supported by U-Boot:
363500856ebSRafal Jaworowski 		 * no storage device implements block_write() method
364500856ebSRafal Jaworowski 		 */
365500856ebSRafal Jaworowski 		return API_ENODEV;
366500856ebSRafal Jaworowski 
367500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
368500856ebSRafal Jaworowski 		err = dev_write_net(di->cookie, buf, *len);
369500856ebSRafal Jaworowski 	else
370500856ebSRafal Jaworowski 		err = API_ENODEV;
371500856ebSRafal Jaworowski 
372500856ebSRafal Jaworowski 	return err;
373500856ebSRafal Jaworowski }
374500856ebSRafal Jaworowski 
375500856ebSRafal Jaworowski 
376500856ebSRafal Jaworowski /*
377500856ebSRafal Jaworowski  * pseudo signature:
378500856ebSRafal Jaworowski  *
379500856ebSRafal Jaworowski  * int API_dev_read(
380500856ebSRafal Jaworowski  *	struct device_info *di,
381500856ebSRafal Jaworowski  *	void *buf,
382500856ebSRafal Jaworowski  *	size_t *len,
383500856ebSRafal Jaworowski  *	unsigned long *start
384500856ebSRafal Jaworowski  *	size_t *act_len
385500856ebSRafal Jaworowski  * )
386500856ebSRafal Jaworowski  *
387500856ebSRafal Jaworowski  * buf:	ptr to buffer where to put the read data
388500856ebSRafal Jaworowski  *
389500856ebSRafal Jaworowski  * len: ptr to length to be read
390500856ebSRafal Jaworowski  *      - network: len of packet to read (in bytes)
391500856ebSRafal Jaworowski  *      - storage: # of blocks to read (can vary in size depending on define)
392500856ebSRafal Jaworowski  *
393500856ebSRafal Jaworowski  * start: ptr to start block (only used for storage devices, ignored for
394500856ebSRafal Jaworowski  *        network)
395500856ebSRafal Jaworowski  *
396500856ebSRafal Jaworowski  * act_len: ptr to where to put the len actually read
397500856ebSRafal Jaworowski  */
398500856ebSRafal Jaworowski static int API_dev_read(va_list ap)
399500856ebSRafal Jaworowski {
400500856ebSRafal Jaworowski 	struct device_info *di;
401500856ebSRafal Jaworowski 	void *buf;
402500856ebSRafal Jaworowski 	lbasize_t *len_stor, *act_len_stor;
403500856ebSRafal Jaworowski 	lbastart_t *start;
404500856ebSRafal Jaworowski 	int *len_net, *act_len_net;
405500856ebSRafal Jaworowski 
406500856ebSRafal Jaworowski 	/* 1. arg is ptr to the device_info struct */
407500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
408500856ebSRafal Jaworowski 	if (di == NULL)
409500856ebSRafal Jaworowski 		return API_EINVAL;
410500856ebSRafal Jaworowski 
411500856ebSRafal Jaworowski 	/* XXX should we check if device is open? i.e. the ->state ? */
412500856ebSRafal Jaworowski 
413500856ebSRafal Jaworowski 	if (di->cookie == NULL)
414500856ebSRafal Jaworowski 		return API_ENODEV;
415500856ebSRafal Jaworowski 
416500856ebSRafal Jaworowski 	/* 2. arg is ptr to buffer from where to put the read data */
417500856ebSRafal Jaworowski 	buf = (void *)va_arg(ap, u_int32_t);
418500856ebSRafal Jaworowski 	if (buf == NULL)
419500856ebSRafal Jaworowski 		return API_EINVAL;
420500856ebSRafal Jaworowski 
421500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR) {
422500856ebSRafal Jaworowski 		/* 3. arg - ptr to var with # of blocks to read */
423500856ebSRafal Jaworowski 		len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
424500856ebSRafal Jaworowski 		if (!len_stor)
425500856ebSRafal Jaworowski 			return API_EINVAL;
426500856ebSRafal Jaworowski 		if (*len_stor <= 0)
427500856ebSRafal Jaworowski 			return API_EINVAL;
428500856ebSRafal Jaworowski 
429500856ebSRafal Jaworowski 		/* 4. arg - ptr to var with start block */
430500856ebSRafal Jaworowski 		start = (lbastart_t *)va_arg(ap, u_int32_t);
431500856ebSRafal Jaworowski 
432500856ebSRafal Jaworowski 		/* 5. arg - ptr to var where to put the len actually read */
433500856ebSRafal Jaworowski 		act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
434500856ebSRafal Jaworowski 		if (!act_len_stor)
435500856ebSRafal Jaworowski 			return API_EINVAL;
436500856ebSRafal Jaworowski 
437500856ebSRafal Jaworowski 		*act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
438500856ebSRafal Jaworowski 
439500856ebSRafal Jaworowski 	} else if (di->type & DEV_TYP_NET) {
440500856ebSRafal Jaworowski 
441500856ebSRafal Jaworowski 		/* 3. arg points to the var with length of packet to read */
442500856ebSRafal Jaworowski 		len_net = (int *)va_arg(ap, u_int32_t);
443500856ebSRafal Jaworowski 		if (!len_net)
444500856ebSRafal Jaworowski 			return API_EINVAL;
445500856ebSRafal Jaworowski 		if (*len_net <= 0)
446500856ebSRafal Jaworowski 			return API_EINVAL;
447500856ebSRafal Jaworowski 
448500856ebSRafal Jaworowski 		/* 4. - ptr to var where to put the len actually read */
449500856ebSRafal Jaworowski 		act_len_net = (int *)va_arg(ap, u_int32_t);
450500856ebSRafal Jaworowski 		if (!act_len_net)
451500856ebSRafal Jaworowski 			return API_EINVAL;
452500856ebSRafal Jaworowski 
453500856ebSRafal Jaworowski 		*act_len_net = dev_read_net(di->cookie, buf, *len_net);
454500856ebSRafal Jaworowski 
455500856ebSRafal Jaworowski 	} else
456500856ebSRafal Jaworowski 		return API_ENODEV;
457500856ebSRafal Jaworowski 
458500856ebSRafal Jaworowski 	return 0;
459500856ebSRafal Jaworowski }
460500856ebSRafal Jaworowski 
461500856ebSRafal Jaworowski 
462500856ebSRafal Jaworowski /*
463500856ebSRafal Jaworowski  * pseudo signature:
464500856ebSRafal Jaworowski  *
465500856ebSRafal Jaworowski  * int API_env_get(const char *name, char **value)
466500856ebSRafal Jaworowski  *
467500856ebSRafal Jaworowski  * name: ptr to name of env var
468500856ebSRafal Jaworowski  */
469500856ebSRafal Jaworowski static int API_env_get(va_list ap)
470500856ebSRafal Jaworowski {
471500856ebSRafal Jaworowski 	char *name, **value;
472500856ebSRafal Jaworowski 
473500856ebSRafal Jaworowski 	if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
474500856ebSRafal Jaworowski 		return API_EINVAL;
475500856ebSRafal Jaworowski 	if ((value = (char **)va_arg(ap, u_int32_t)) == NULL)
476500856ebSRafal Jaworowski 		return API_EINVAL;
477500856ebSRafal Jaworowski 
478500856ebSRafal Jaworowski 	*value = getenv(name);
479500856ebSRafal Jaworowski 
480500856ebSRafal Jaworowski 	return 0;
481500856ebSRafal Jaworowski }
482500856ebSRafal Jaworowski 
483500856ebSRafal Jaworowski /*
484500856ebSRafal Jaworowski  * pseudo signature:
485500856ebSRafal Jaworowski  *
486500856ebSRafal Jaworowski  * int API_env_set(const char *name, const char *value)
487500856ebSRafal Jaworowski  *
488500856ebSRafal Jaworowski  * name: ptr to name of env var
489500856ebSRafal Jaworowski  *
490500856ebSRafal Jaworowski  * value: ptr to value to be set
491500856ebSRafal Jaworowski  */
492500856ebSRafal Jaworowski static int API_env_set(va_list ap)
493500856ebSRafal Jaworowski {
494500856ebSRafal Jaworowski 	char *name, *value;
495500856ebSRafal Jaworowski 
496500856ebSRafal Jaworowski 	if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
497500856ebSRafal Jaworowski 		return API_EINVAL;
498500856ebSRafal Jaworowski 	if ((value = (char *)va_arg(ap, u_int32_t)) == NULL)
499500856ebSRafal Jaworowski 		return API_EINVAL;
500500856ebSRafal Jaworowski 
501500856ebSRafal Jaworowski 	setenv(name, value);
502500856ebSRafal Jaworowski 
503500856ebSRafal Jaworowski 	return 0;
504500856ebSRafal Jaworowski }
505500856ebSRafal Jaworowski 
506500856ebSRafal Jaworowski /*
507500856ebSRafal Jaworowski  * pseudo signature:
508500856ebSRafal Jaworowski  *
509500856ebSRafal Jaworowski  * int API_env_enum(const char *last, char **next)
510500856ebSRafal Jaworowski  *
511500856ebSRafal Jaworowski  * last: ptr to name of env var found in last iteration
512500856ebSRafal Jaworowski  */
513500856ebSRafal Jaworowski static int API_env_enum(va_list ap)
514500856ebSRafal Jaworowski {
515500856ebSRafal Jaworowski 	int i, n;
516500856ebSRafal Jaworowski 	char *last, **next;
517500856ebSRafal Jaworowski 
518500856ebSRafal Jaworowski 	last = (char *)va_arg(ap, u_int32_t);
519500856ebSRafal Jaworowski 
520500856ebSRafal Jaworowski 	if ((next = (char **)va_arg(ap, u_int32_t)) == NULL)
521500856ebSRafal Jaworowski 		return API_EINVAL;
522500856ebSRafal Jaworowski 
523500856ebSRafal Jaworowski 	if (last == NULL)
524500856ebSRafal Jaworowski 		/* start over */
525500856ebSRafal Jaworowski 		*next = ((char *)env_get_addr(0));
526500856ebSRafal Jaworowski 	else {
527500856ebSRafal Jaworowski 		*next = last;
528500856ebSRafal Jaworowski 
529500856ebSRafal Jaworowski 		for (i = 0; env_get_char(i) != '\0'; i = n + 1) {
530500856ebSRafal Jaworowski 			for (n = i; env_get_char(n) != '\0'; ++n) {
5310e8d1586SJean-Christophe PLAGNIOL-VILLARD 				if (n >= CONFIG_ENV_SIZE) {
532500856ebSRafal Jaworowski 					/* XXX shouldn't we set *next = NULL?? */
533500856ebSRafal Jaworowski 					return 0;
534500856ebSRafal Jaworowski 				}
535500856ebSRafal Jaworowski 			}
536500856ebSRafal Jaworowski 
537500856ebSRafal Jaworowski 			if (envmatch((uchar *)last, i) < 0)
538500856ebSRafal Jaworowski 				continue;
539500856ebSRafal Jaworowski 
540500856ebSRafal Jaworowski 			/* try to get next name */
541500856ebSRafal Jaworowski 			i = n + 1;
542500856ebSRafal Jaworowski 			if (env_get_char(i) == '\0') {
543500856ebSRafal Jaworowski 				/* no more left */
544500856ebSRafal Jaworowski 				*next = NULL;
545500856ebSRafal Jaworowski 				return 0;
546500856ebSRafal Jaworowski 			}
547500856ebSRafal Jaworowski 
548500856ebSRafal Jaworowski 			*next = ((char *)env_get_addr(i));
549500856ebSRafal Jaworowski 			return 0;
550500856ebSRafal Jaworowski 		}
551500856ebSRafal Jaworowski 	}
552500856ebSRafal Jaworowski 
553500856ebSRafal Jaworowski 	return 0;
554500856ebSRafal Jaworowski }
555500856ebSRafal Jaworowski 
556*a2a5729fSChe-Liang Chiou /*
557*a2a5729fSChe-Liang Chiou  * pseudo signature:
558*a2a5729fSChe-Liang Chiou  *
559*a2a5729fSChe-Liang Chiou  * int API_display_get_info(int type, struct display_info *di)
560*a2a5729fSChe-Liang Chiou  */
561*a2a5729fSChe-Liang Chiou static int API_display_get_info(va_list ap)
562*a2a5729fSChe-Liang Chiou {
563*a2a5729fSChe-Liang Chiou 	int type;
564*a2a5729fSChe-Liang Chiou 	struct display_info *di;
565*a2a5729fSChe-Liang Chiou 
566*a2a5729fSChe-Liang Chiou 	type = va_arg(ap, int);
567*a2a5729fSChe-Liang Chiou 	di = va_arg(ap, struct display_info *);
568*a2a5729fSChe-Liang Chiou 
569*a2a5729fSChe-Liang Chiou 	return display_get_info(type, di);
570*a2a5729fSChe-Liang Chiou }
571*a2a5729fSChe-Liang Chiou 
572*a2a5729fSChe-Liang Chiou /*
573*a2a5729fSChe-Liang Chiou  * pseudo signature:
574*a2a5729fSChe-Liang Chiou  *
575*a2a5729fSChe-Liang Chiou  * int API_display_draw_bitmap(ulong bitmap, int x, int y)
576*a2a5729fSChe-Liang Chiou  */
577*a2a5729fSChe-Liang Chiou static int API_display_draw_bitmap(va_list ap)
578*a2a5729fSChe-Liang Chiou {
579*a2a5729fSChe-Liang Chiou 	ulong bitmap;
580*a2a5729fSChe-Liang Chiou 	int x, y;
581*a2a5729fSChe-Liang Chiou 
582*a2a5729fSChe-Liang Chiou 	bitmap = va_arg(ap, ulong);
583*a2a5729fSChe-Liang Chiou 	x = va_arg(ap, int);
584*a2a5729fSChe-Liang Chiou 	y = va_arg(ap, int);
585*a2a5729fSChe-Liang Chiou 
586*a2a5729fSChe-Liang Chiou 	return display_draw_bitmap(bitmap, x, y);
587*a2a5729fSChe-Liang Chiou }
588*a2a5729fSChe-Liang Chiou 
589*a2a5729fSChe-Liang Chiou /*
590*a2a5729fSChe-Liang Chiou  * pseudo signature:
591*a2a5729fSChe-Liang Chiou  *
592*a2a5729fSChe-Liang Chiou  * void API_display_clear(void)
593*a2a5729fSChe-Liang Chiou  */
594*a2a5729fSChe-Liang Chiou static int API_display_clear(va_list ap)
595*a2a5729fSChe-Liang Chiou {
596*a2a5729fSChe-Liang Chiou 	display_clear();
597*a2a5729fSChe-Liang Chiou 	return 0;
598*a2a5729fSChe-Liang Chiou }
599*a2a5729fSChe-Liang Chiou 
600500856ebSRafal Jaworowski static cfp_t calls_table[API_MAXCALL] = { NULL, };
601500856ebSRafal Jaworowski 
602500856ebSRafal Jaworowski /*
603500856ebSRafal Jaworowski  * The main syscall entry point - this is not reentrant, only one call is
604500856ebSRafal Jaworowski  * serviced until finished.
605500856ebSRafal Jaworowski  *
606500856ebSRafal Jaworowski  * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
607500856ebSRafal Jaworowski  *
608500856ebSRafal Jaworowski  * call:	syscall number
609500856ebSRafal Jaworowski  *
610500856ebSRafal Jaworowski  * retval:	points to the return value placeholder, this is the place the
611500856ebSRafal Jaworowski  *		syscall puts its return value, if NULL the caller does not
612500856ebSRafal Jaworowski  *		expect a return value
613500856ebSRafal Jaworowski  *
614500856ebSRafal Jaworowski  * ...		syscall arguments (variable number)
615500856ebSRafal Jaworowski  *
616500856ebSRafal Jaworowski  * returns:	0 if the call not found, 1 if serviced
617500856ebSRafal Jaworowski  */
618500856ebSRafal Jaworowski int syscall(int call, int *retval, ...)
619500856ebSRafal Jaworowski {
620500856ebSRafal Jaworowski 	va_list	ap;
621500856ebSRafal Jaworowski 	int rv;
622500856ebSRafal Jaworowski 
62320e5ed13SJean-Christophe PLAGNIOL-VILLARD 	if (call < 0 || call >= calls_no) {
624500856ebSRafal Jaworowski 		debugf("invalid call #%d\n", call);
625500856ebSRafal Jaworowski 		return 0;
626500856ebSRafal Jaworowski 	}
627500856ebSRafal Jaworowski 
628500856ebSRafal Jaworowski 	if (calls_table[call] == NULL) {
629500856ebSRafal Jaworowski 		debugf("syscall #%d does not have a handler\n", call);
630500856ebSRafal Jaworowski 		return 0;
631500856ebSRafal Jaworowski 	}
632500856ebSRafal Jaworowski 
633500856ebSRafal Jaworowski 	va_start(ap, retval);
634500856ebSRafal Jaworowski 	rv = calls_table[call](ap);
635500856ebSRafal Jaworowski 	if (retval != NULL)
636500856ebSRafal Jaworowski 		*retval = rv;
637500856ebSRafal Jaworowski 
638500856ebSRafal Jaworowski 	return 1;
639500856ebSRafal Jaworowski }
640500856ebSRafal Jaworowski 
641500856ebSRafal Jaworowski void api_init(void)
642500856ebSRafal Jaworowski {
643500856ebSRafal Jaworowski 	struct api_signature *sig = NULL;
644500856ebSRafal Jaworowski 
645500856ebSRafal Jaworowski 	/* TODO put this into linker set one day... */
646500856ebSRafal Jaworowski 	calls_table[API_RSVD] = NULL;
647500856ebSRafal Jaworowski 	calls_table[API_GETC] = &API_getc;
648500856ebSRafal Jaworowski 	calls_table[API_PUTC] = &API_putc;
649500856ebSRafal Jaworowski 	calls_table[API_TSTC] = &API_tstc;
650500856ebSRafal Jaworowski 	calls_table[API_PUTS] = &API_puts;
651500856ebSRafal Jaworowski 	calls_table[API_RESET] = &API_reset;
652500856ebSRafal Jaworowski 	calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
653500856ebSRafal Jaworowski 	calls_table[API_UDELAY] = &API_udelay;
654500856ebSRafal Jaworowski 	calls_table[API_GET_TIMER] = &API_get_timer;
655500856ebSRafal Jaworowski 	calls_table[API_DEV_ENUM] = &API_dev_enum;
656500856ebSRafal Jaworowski 	calls_table[API_DEV_OPEN] = &API_dev_open;
657500856ebSRafal Jaworowski 	calls_table[API_DEV_CLOSE] = &API_dev_close;
658500856ebSRafal Jaworowski 	calls_table[API_DEV_READ] = &API_dev_read;
659500856ebSRafal Jaworowski 	calls_table[API_DEV_WRITE] = &API_dev_write;
660500856ebSRafal Jaworowski 	calls_table[API_ENV_GET] = &API_env_get;
661500856ebSRafal Jaworowski 	calls_table[API_ENV_SET] = &API_env_set;
662500856ebSRafal Jaworowski 	calls_table[API_ENV_ENUM] = &API_env_enum;
663*a2a5729fSChe-Liang Chiou 	calls_table[API_DISPLAY_GET_INFO] = &API_display_get_info;
664*a2a5729fSChe-Liang Chiou 	calls_table[API_DISPLAY_DRAW_BITMAP] = &API_display_draw_bitmap;
665*a2a5729fSChe-Liang Chiou 	calls_table[API_DISPLAY_CLEAR] = &API_display_clear;
666500856ebSRafal Jaworowski 	calls_no = API_MAXCALL;
667500856ebSRafal Jaworowski 
668500856ebSRafal Jaworowski 	debugf("API initialized with %d calls\n", calls_no);
669500856ebSRafal Jaworowski 
670500856ebSRafal Jaworowski 	dev_stor_init();
671500856ebSRafal Jaworowski 
672500856ebSRafal Jaworowski 	/*
673500856ebSRafal Jaworowski 	 * Produce the signature so the API consumers can find it
674500856ebSRafal Jaworowski 	 */
675500856ebSRafal Jaworowski 	sig = malloc(sizeof(struct api_signature));
676500856ebSRafal Jaworowski 	if (sig == NULL) {
677500856ebSRafal Jaworowski 		printf("API: could not allocate memory for the signature!\n");
678500856ebSRafal Jaworowski 		return;
679500856ebSRafal Jaworowski 	}
680500856ebSRafal Jaworowski 
681500856ebSRafal Jaworowski 	debugf("API sig @ 0x%08x\n", sig);
682500856ebSRafal Jaworowski 	memcpy(sig->magic, API_SIG_MAGIC, 8);
683500856ebSRafal Jaworowski 	sig->version = API_SIG_VERSION;
684500856ebSRafal Jaworowski 	sig->syscall = &syscall;
685500856ebSRafal Jaworowski 	sig->checksum = 0;
686500856ebSRafal Jaworowski 	sig->checksum = crc32(0, (unsigned char *)sig,
687500856ebSRafal Jaworowski 			      sizeof(struct api_signature));
688500856ebSRafal Jaworowski 	debugf("syscall entry: 0x%08x\n", sig->syscall);
689500856ebSRafal Jaworowski }
690500856ebSRafal Jaworowski 
691500856ebSRafal Jaworowski void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
692500856ebSRafal Jaworowski 			int flags)
693500856ebSRafal Jaworowski {
694500856ebSRafal Jaworowski 	int i;
695500856ebSRafal Jaworowski 
696500856ebSRafal Jaworowski 	if (!si->mr || !size || (flags == 0))
697500856ebSRafal Jaworowski 		return;
698500856ebSRafal Jaworowski 
699500856ebSRafal Jaworowski 	/* find free slot */
700500856ebSRafal Jaworowski 	for (i = 0; i < si->mr_no; i++)
701500856ebSRafal Jaworowski 		if (si->mr[i].flags == 0) {
702500856ebSRafal Jaworowski 			/* insert new mem region */
703500856ebSRafal Jaworowski 			si->mr[i].start = start;
704500856ebSRafal Jaworowski 			si->mr[i].size = size;
705500856ebSRafal Jaworowski 			si->mr[i].flags = flags;
706500856ebSRafal Jaworowski 			return;
707500856ebSRafal Jaworowski 		}
708500856ebSRafal Jaworowski }
709