xref: /rk3399_rockchip-uboot/api/api.c (revision 0e8d158664a913392cb01fb11a948d83f72e105e)
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 
28500856ebSRafal Jaworowski #if defined(CONFIG_API)
29500856ebSRafal Jaworowski 
30500856ebSRafal Jaworowski #include <command.h>
31500856ebSRafal Jaworowski #include <common.h>
32500856ebSRafal Jaworowski #include <malloc.h>
33a8409f4fSWolfgang Denk #include <environment.h>
34500856ebSRafal Jaworowski #include <linux/types.h>
35500856ebSRafal Jaworowski #include <api_public.h>
36500856ebSRafal Jaworowski 
37500856ebSRafal Jaworowski #include "api_private.h"
38500856ebSRafal Jaworowski 
39500856ebSRafal Jaworowski #define DEBUG
40500856ebSRafal Jaworowski #undef DEBUG
41500856ebSRafal Jaworowski 
42500856ebSRafal Jaworowski /* U-Boot routines needed */
43500856ebSRafal Jaworowski extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
44500856ebSRafal Jaworowski 
45500856ebSRafal Jaworowski /*****************************************************************************
46500856ebSRafal Jaworowski  *
47500856ebSRafal Jaworowski  * This is the API core.
48500856ebSRafal Jaworowski  *
49500856ebSRafal Jaworowski  * API_ functions are part of U-Boot code and constitute the lowest level
50500856ebSRafal Jaworowski  * calls:
51500856ebSRafal Jaworowski  *
52500856ebSRafal Jaworowski  *  - they know what values they need as arguments
53500856ebSRafal Jaworowski  *  - their direct return value pertains to the API_ "shell" itself (0 on
54500856ebSRafal Jaworowski  *    success, some error code otherwise)
55500856ebSRafal Jaworowski  *  - if the call returns a value it is buried within arguments
56500856ebSRafal Jaworowski  *
57500856ebSRafal Jaworowski  ****************************************************************************/
58500856ebSRafal Jaworowski 
59500856ebSRafal Jaworowski #ifdef DEBUG
60500856ebSRafal Jaworowski #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
61500856ebSRafal Jaworowski #else
62500856ebSRafal Jaworowski #define debugf(fmt, args...)
63500856ebSRafal Jaworowski #endif
64500856ebSRafal Jaworowski 
65500856ebSRafal Jaworowski typedef	int (*cfp_t)(va_list argp);
66500856ebSRafal Jaworowski 
67500856ebSRafal Jaworowski static int calls_no;
68500856ebSRafal Jaworowski 
69500856ebSRafal Jaworowski /*
70500856ebSRafal Jaworowski  * pseudo signature:
71500856ebSRafal Jaworowski  *
72500856ebSRafal Jaworowski  * int API_getc(int *c)
73500856ebSRafal Jaworowski  */
74500856ebSRafal Jaworowski static int API_getc(va_list ap)
75500856ebSRafal Jaworowski {
76500856ebSRafal Jaworowski 	int *c;
77500856ebSRafal Jaworowski 
78500856ebSRafal Jaworowski 	if ((c = (int *)va_arg(ap, u_int32_t)) == NULL)
79500856ebSRafal Jaworowski 		return API_EINVAL;
80500856ebSRafal Jaworowski 
81500856ebSRafal Jaworowski 	*c = getc();
82500856ebSRafal Jaworowski 	return 0;
83500856ebSRafal Jaworowski }
84500856ebSRafal Jaworowski 
85500856ebSRafal Jaworowski /*
86500856ebSRafal Jaworowski  * pseudo signature:
87500856ebSRafal Jaworowski  *
88500856ebSRafal Jaworowski  * int API_tstc(int *c)
89500856ebSRafal Jaworowski  */
90500856ebSRafal Jaworowski static int API_tstc(va_list ap)
91500856ebSRafal Jaworowski {
92500856ebSRafal Jaworowski 	int *t;
93500856ebSRafal Jaworowski 
94500856ebSRafal Jaworowski 	if ((t = (int *)va_arg(ap, u_int32_t)) == NULL)
95500856ebSRafal Jaworowski 		return API_EINVAL;
96500856ebSRafal Jaworowski 
97500856ebSRafal Jaworowski 	*t = tstc();
98500856ebSRafal Jaworowski 	return 0;
99500856ebSRafal Jaworowski }
100500856ebSRafal Jaworowski 
101500856ebSRafal Jaworowski /*
102500856ebSRafal Jaworowski  * pseudo signature:
103500856ebSRafal Jaworowski  *
104500856ebSRafal Jaworowski  * int API_putc(char *ch)
105500856ebSRafal Jaworowski  */
106500856ebSRafal Jaworowski static int API_putc(va_list ap)
107500856ebSRafal Jaworowski {
108500856ebSRafal Jaworowski 	char *c;
109500856ebSRafal Jaworowski 
110500856ebSRafal Jaworowski 	if ((c = (char *)va_arg(ap, u_int32_t)) == NULL)
111500856ebSRafal Jaworowski 		return API_EINVAL;
112500856ebSRafal Jaworowski 
113500856ebSRafal Jaworowski 	putc(*c);
114500856ebSRafal Jaworowski 	return 0;
115500856ebSRafal Jaworowski }
116500856ebSRafal Jaworowski 
117500856ebSRafal Jaworowski /*
118500856ebSRafal Jaworowski  * pseudo signature:
119500856ebSRafal Jaworowski  *
120500856ebSRafal Jaworowski  * int API_puts(char **s)
121500856ebSRafal Jaworowski  */
122500856ebSRafal Jaworowski static int API_puts(va_list ap)
123500856ebSRafal Jaworowski {
124500856ebSRafal Jaworowski 	char *s;
125500856ebSRafal Jaworowski 
126500856ebSRafal Jaworowski 	if ((s = (char *)va_arg(ap, u_int32_t)) == NULL)
127500856ebSRafal Jaworowski 		return API_EINVAL;
128500856ebSRafal Jaworowski 
129500856ebSRafal Jaworowski 	puts(s);
130500856ebSRafal Jaworowski 	return 0;
131500856ebSRafal Jaworowski }
132500856ebSRafal Jaworowski 
133500856ebSRafal Jaworowski /*
134500856ebSRafal Jaworowski  * pseudo signature:
135500856ebSRafal Jaworowski  *
136500856ebSRafal Jaworowski  * int API_reset(void)
137500856ebSRafal Jaworowski  */
138500856ebSRafal Jaworowski static int API_reset(va_list ap)
139500856ebSRafal Jaworowski {
140500856ebSRafal Jaworowski 	do_reset(NULL, 0, 0, NULL);
141500856ebSRafal Jaworowski 
142500856ebSRafal Jaworowski 	/* NOT REACHED */
143500856ebSRafal Jaworowski 	return 0;
144500856ebSRafal Jaworowski }
145500856ebSRafal Jaworowski 
146500856ebSRafal Jaworowski /*
147500856ebSRafal Jaworowski  * pseudo signature:
148500856ebSRafal Jaworowski  *
149500856ebSRafal Jaworowski  * int API_get_sys_info(struct sys_info *si)
150500856ebSRafal Jaworowski  *
151500856ebSRafal Jaworowski  * fill out the sys_info struct containing selected parameters about the
152500856ebSRafal Jaworowski  * machine
153500856ebSRafal Jaworowski  */
154500856ebSRafal Jaworowski static int API_get_sys_info(va_list ap)
155500856ebSRafal Jaworowski {
156500856ebSRafal Jaworowski 	struct sys_info *si;
157500856ebSRafal Jaworowski 
158500856ebSRafal Jaworowski 	si = (struct sys_info *)va_arg(ap, u_int32_t);
159500856ebSRafal Jaworowski 	if (si == NULL)
160500856ebSRafal Jaworowski 		return API_ENOMEM;
161500856ebSRafal Jaworowski 
162500856ebSRafal Jaworowski 	return (platform_sys_info(si)) ? 0 : API_ENODEV;
163500856ebSRafal Jaworowski }
164500856ebSRafal Jaworowski 
165500856ebSRafal Jaworowski /*
166500856ebSRafal Jaworowski  * pseudo signature:
167500856ebSRafal Jaworowski  *
168500856ebSRafal Jaworowski  * int API_udelay(unsigned long *udelay)
169500856ebSRafal Jaworowski  */
170500856ebSRafal Jaworowski static int API_udelay(va_list ap)
171500856ebSRafal Jaworowski {
172500856ebSRafal Jaworowski 	unsigned long *d;
173500856ebSRafal Jaworowski 
174500856ebSRafal Jaworowski 	if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL)
175500856ebSRafal Jaworowski 		return API_EINVAL;
176500856ebSRafal Jaworowski 
177500856ebSRafal Jaworowski 	udelay(*d);
178500856ebSRafal Jaworowski 	return 0;
179500856ebSRafal Jaworowski }
180500856ebSRafal Jaworowski 
181500856ebSRafal Jaworowski /*
182500856ebSRafal Jaworowski  * pseudo signature:
183500856ebSRafal Jaworowski  *
184500856ebSRafal Jaworowski  * int API_get_timer(unsigned long *current, unsigned long *base)
185500856ebSRafal Jaworowski  */
186500856ebSRafal Jaworowski static int API_get_timer(va_list ap)
187500856ebSRafal Jaworowski {
188500856ebSRafal Jaworowski 	unsigned long *base, *cur;
189500856ebSRafal Jaworowski 
190500856ebSRafal Jaworowski 	cur = (unsigned long *)va_arg(ap, u_int32_t);
191500856ebSRafal Jaworowski 	if (cur == NULL)
192500856ebSRafal Jaworowski 		return API_EINVAL;
193500856ebSRafal Jaworowski 
194500856ebSRafal Jaworowski 	base = (unsigned long *)va_arg(ap, u_int32_t);
195500856ebSRafal Jaworowski 	if (base == NULL)
196500856ebSRafal Jaworowski 		return API_EINVAL;
197500856ebSRafal Jaworowski 
198500856ebSRafal Jaworowski 	*cur = get_timer(*base);
199500856ebSRafal Jaworowski 	return 0;
200500856ebSRafal Jaworowski }
201500856ebSRafal Jaworowski 
202500856ebSRafal Jaworowski 
203500856ebSRafal Jaworowski /*****************************************************************************
204500856ebSRafal Jaworowski  *
205500856ebSRafal Jaworowski  * pseudo signature:
206500856ebSRafal Jaworowski  *
207500856ebSRafal Jaworowski  * int API_dev_enum(struct device_info *)
208500856ebSRafal Jaworowski  *
209500856ebSRafal Jaworowski  *
210500856ebSRafal Jaworowski  * cookies uniqely identify the previously enumerated device instance and
211500856ebSRafal Jaworowski  * provide a hint for what to inspect in current enum iteration:
212500856ebSRafal Jaworowski  *
213500856ebSRafal Jaworowski  *   - net: &eth_device struct address from list pointed to by eth_devices
214500856ebSRafal Jaworowski  *
215500856ebSRafal Jaworowski  *   - storage: block_dev_desc_t struct address from &ide_dev_desc[n],
216500856ebSRafal Jaworowski  *     &scsi_dev_desc[n] and similar tables
217500856ebSRafal Jaworowski  *
218500856ebSRafal Jaworowski  ****************************************************************************/
219500856ebSRafal Jaworowski 
220500856ebSRafal Jaworowski static int API_dev_enum(va_list ap)
221500856ebSRafal Jaworowski {
222500856ebSRafal Jaworowski 	struct device_info *di;
223500856ebSRafal Jaworowski 
224500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct we are going to fill out */
225500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
226500856ebSRafal Jaworowski 	if (di == NULL)
227500856ebSRafal Jaworowski 		return API_EINVAL;
228500856ebSRafal Jaworowski 
229500856ebSRafal Jaworowski 	if (di->cookie == NULL) {
230500856ebSRafal Jaworowski 		/* start over - clean up enumeration */
231500856ebSRafal Jaworowski 		dev_enum_reset();	/* XXX shouldn't the name contain 'stor'? */
232500856ebSRafal Jaworowski 		debugf("RESTART ENUM\n");
233500856ebSRafal Jaworowski 
234500856ebSRafal Jaworowski 		/* net device enumeration first */
235500856ebSRafal Jaworowski 		if (dev_enum_net(di))
236500856ebSRafal Jaworowski 			return 0;
237500856ebSRafal Jaworowski 	}
238500856ebSRafal Jaworowski 
239500856ebSRafal Jaworowski 	/*
240500856ebSRafal Jaworowski 	 * The hidden assumption is there can only be one active network
241500856ebSRafal Jaworowski 	 * device and it is identified upon enumeration (re)start, so there's
242500856ebSRafal Jaworowski 	 * no point in trying to find network devices in other cases than the
243500856ebSRafal Jaworowski 	 * (re)start and hence the 'next' device can only be storage
244500856ebSRafal Jaworowski 	 */
245500856ebSRafal Jaworowski 	if (!dev_enum_storage(di))
246500856ebSRafal Jaworowski 		/* make sure we mark there are no more devices */
247500856ebSRafal Jaworowski 		di->cookie = NULL;
248500856ebSRafal Jaworowski 
249500856ebSRafal Jaworowski 	return 0;
250500856ebSRafal Jaworowski }
251500856ebSRafal Jaworowski 
252500856ebSRafal Jaworowski 
253500856ebSRafal Jaworowski static int API_dev_open(va_list ap)
254500856ebSRafal Jaworowski {
255500856ebSRafal Jaworowski 	struct device_info *di;
256500856ebSRafal Jaworowski 	int err = 0;
257500856ebSRafal Jaworowski 
258500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct */
259500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
260500856ebSRafal Jaworowski 	if (di == NULL)
261500856ebSRafal Jaworowski 		return API_EINVAL;
262500856ebSRafal Jaworowski 
263500856ebSRafal Jaworowski 	/* Allow only one consumer of the device at a time */
264500856ebSRafal Jaworowski 	if (di->state == DEV_STA_OPEN)
265500856ebSRafal Jaworowski 		return API_EBUSY;
266500856ebSRafal Jaworowski 
267500856ebSRafal Jaworowski 	if (di->cookie == NULL)
268500856ebSRafal Jaworowski 		return API_ENODEV;
269500856ebSRafal Jaworowski 
270500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
271500856ebSRafal Jaworowski 		err = dev_open_stor(di->cookie);
272500856ebSRafal Jaworowski 
273500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
274500856ebSRafal Jaworowski 		err = dev_open_net(di->cookie);
275500856ebSRafal Jaworowski 	else
276500856ebSRafal Jaworowski 		err = API_ENODEV;
277500856ebSRafal Jaworowski 
278500856ebSRafal Jaworowski 	if (!err)
279500856ebSRafal Jaworowski 		di->state = DEV_STA_OPEN;
280500856ebSRafal Jaworowski 
281500856ebSRafal Jaworowski 	return err;
282500856ebSRafal Jaworowski }
283500856ebSRafal Jaworowski 
284500856ebSRafal Jaworowski 
285500856ebSRafal Jaworowski static int API_dev_close(va_list ap)
286500856ebSRafal Jaworowski {
287500856ebSRafal Jaworowski 	struct device_info *di;
288500856ebSRafal Jaworowski 	int err = 0;
289500856ebSRafal Jaworowski 
290500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct */
291500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
292500856ebSRafal Jaworowski 	if (di == NULL)
293500856ebSRafal Jaworowski 		return API_EINVAL;
294500856ebSRafal Jaworowski 
295500856ebSRafal Jaworowski 	if (di->state == DEV_STA_CLOSED)
296500856ebSRafal Jaworowski 		return 0;
297500856ebSRafal Jaworowski 
298500856ebSRafal Jaworowski 	if (di->cookie == NULL)
299500856ebSRafal Jaworowski 		return API_ENODEV;
300500856ebSRafal Jaworowski 
301500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
302500856ebSRafal Jaworowski 		err = dev_close_stor(di->cookie);
303500856ebSRafal Jaworowski 
304500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
305500856ebSRafal Jaworowski 		err = dev_close_net(di->cookie);
306500856ebSRafal Jaworowski 	else
307500856ebSRafal Jaworowski 		/*
308500856ebSRafal Jaworowski 		 * In case of unknown device we cannot change its state, so
309500856ebSRafal Jaworowski 		 * only return error code
310500856ebSRafal Jaworowski 		 */
311500856ebSRafal Jaworowski 		err = API_ENODEV;
312500856ebSRafal Jaworowski 
313500856ebSRafal Jaworowski 	if (!err)
314500856ebSRafal Jaworowski 		di->state = DEV_STA_CLOSED;
315500856ebSRafal Jaworowski 
316500856ebSRafal Jaworowski 	return err;
317500856ebSRafal Jaworowski }
318500856ebSRafal Jaworowski 
319500856ebSRafal Jaworowski 
320500856ebSRafal Jaworowski /*
321500856ebSRafal Jaworowski  * Notice: this is for sending network packets only, as U-Boot does not
322500856ebSRafal Jaworowski  * support writing to storage at the moment (12.2007)
323500856ebSRafal Jaworowski  *
324500856ebSRafal Jaworowski  * pseudo signature:
325500856ebSRafal Jaworowski  *
326500856ebSRafal Jaworowski  * int API_dev_write(
327500856ebSRafal Jaworowski  *	struct device_info *di,
328500856ebSRafal Jaworowski  *	void *buf,
329500856ebSRafal Jaworowski  *	int *len
330500856ebSRafal Jaworowski  * )
331500856ebSRafal Jaworowski  *
332500856ebSRafal Jaworowski  * buf:	ptr to buffer from where to get the data to send
333500856ebSRafal Jaworowski  *
334500856ebSRafal Jaworowski  * len: length of packet to be sent (in bytes)
335500856ebSRafal Jaworowski  *
336500856ebSRafal Jaworowski  */
337500856ebSRafal Jaworowski static int API_dev_write(va_list ap)
338500856ebSRafal Jaworowski {
339500856ebSRafal Jaworowski 	struct device_info *di;
340500856ebSRafal Jaworowski 	void *buf;
341500856ebSRafal Jaworowski 	int *len;
342500856ebSRafal Jaworowski 	int err = 0;
343500856ebSRafal Jaworowski 
344500856ebSRafal Jaworowski 	/* 1. arg is ptr to the device_info struct */
345500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
346500856ebSRafal Jaworowski 	if (di == NULL)
347500856ebSRafal Jaworowski 		return API_EINVAL;
348500856ebSRafal Jaworowski 
349500856ebSRafal Jaworowski 	/* XXX should we check if device is open? i.e. the ->state ? */
350500856ebSRafal Jaworowski 
351500856ebSRafal Jaworowski 	if (di->cookie == NULL)
352500856ebSRafal Jaworowski 		return API_ENODEV;
353500856ebSRafal Jaworowski 
354500856ebSRafal Jaworowski 	/* 2. arg is ptr to buffer from where to get data to write */
355500856ebSRafal Jaworowski 	buf = (void *)va_arg(ap, u_int32_t);
356500856ebSRafal Jaworowski 	if (buf == NULL)
357500856ebSRafal Jaworowski 		return API_EINVAL;
358500856ebSRafal Jaworowski 
359500856ebSRafal Jaworowski 	/* 3. arg is length of buffer */
360500856ebSRafal Jaworowski 	len = (int *)va_arg(ap, u_int32_t);
361500856ebSRafal Jaworowski 	if (len == NULL)
362500856ebSRafal Jaworowski 		return API_EINVAL;
363500856ebSRafal Jaworowski 	if (*len <= 0)
364500856ebSRafal Jaworowski 		return API_EINVAL;
365500856ebSRafal Jaworowski 
366500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
367500856ebSRafal Jaworowski 		/*
368500856ebSRafal Jaworowski 		 * write to storage is currently not supported by U-Boot:
369500856ebSRafal Jaworowski 		 * no storage device implements block_write() method
370500856ebSRafal Jaworowski 		 */
371500856ebSRafal Jaworowski 		return API_ENODEV;
372500856ebSRafal Jaworowski 
373500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
374500856ebSRafal Jaworowski 		err = dev_write_net(di->cookie, buf, *len);
375500856ebSRafal Jaworowski 	else
376500856ebSRafal Jaworowski 		err = API_ENODEV;
377500856ebSRafal Jaworowski 
378500856ebSRafal Jaworowski 	return err;
379500856ebSRafal Jaworowski }
380500856ebSRafal Jaworowski 
381500856ebSRafal Jaworowski 
382500856ebSRafal Jaworowski /*
383500856ebSRafal Jaworowski  * pseudo signature:
384500856ebSRafal Jaworowski  *
385500856ebSRafal Jaworowski  * int API_dev_read(
386500856ebSRafal Jaworowski  *	struct device_info *di,
387500856ebSRafal Jaworowski  *	void *buf,
388500856ebSRafal Jaworowski  *	size_t *len,
389500856ebSRafal Jaworowski  *	unsigned long *start
390500856ebSRafal Jaworowski  *	size_t *act_len
391500856ebSRafal Jaworowski  * )
392500856ebSRafal Jaworowski  *
393500856ebSRafal Jaworowski  * buf:	ptr to buffer where to put the read data
394500856ebSRafal Jaworowski  *
395500856ebSRafal Jaworowski  * len: ptr to length to be read
396500856ebSRafal Jaworowski  *      - network: len of packet to read (in bytes)
397500856ebSRafal Jaworowski  *      - storage: # of blocks to read (can vary in size depending on define)
398500856ebSRafal Jaworowski  *
399500856ebSRafal Jaworowski  * start: ptr to start block (only used for storage devices, ignored for
400500856ebSRafal Jaworowski  *        network)
401500856ebSRafal Jaworowski  *
402500856ebSRafal Jaworowski  * act_len: ptr to where to put the len actually read
403500856ebSRafal Jaworowski  */
404500856ebSRafal Jaworowski static int API_dev_read(va_list ap)
405500856ebSRafal Jaworowski {
406500856ebSRafal Jaworowski 	struct device_info *di;
407500856ebSRafal Jaworowski 	void *buf;
408500856ebSRafal Jaworowski 	lbasize_t *len_stor, *act_len_stor;
409500856ebSRafal Jaworowski 	lbastart_t *start;
410500856ebSRafal Jaworowski 	int *len_net, *act_len_net;
411500856ebSRafal Jaworowski 
412500856ebSRafal Jaworowski 	/* 1. arg is ptr to the device_info struct */
413500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
414500856ebSRafal Jaworowski 	if (di == NULL)
415500856ebSRafal Jaworowski 		return API_EINVAL;
416500856ebSRafal Jaworowski 
417500856ebSRafal Jaworowski 	/* XXX should we check if device is open? i.e. the ->state ? */
418500856ebSRafal Jaworowski 
419500856ebSRafal Jaworowski 	if (di->cookie == NULL)
420500856ebSRafal Jaworowski 		return API_ENODEV;
421500856ebSRafal Jaworowski 
422500856ebSRafal Jaworowski 	/* 2. arg is ptr to buffer from where to put the read data */
423500856ebSRafal Jaworowski 	buf = (void *)va_arg(ap, u_int32_t);
424500856ebSRafal Jaworowski 	if (buf == NULL)
425500856ebSRafal Jaworowski 		return API_EINVAL;
426500856ebSRafal Jaworowski 
427500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR) {
428500856ebSRafal Jaworowski 		/* 3. arg - ptr to var with # of blocks to read */
429500856ebSRafal Jaworowski 		len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
430500856ebSRafal Jaworowski 		if (!len_stor)
431500856ebSRafal Jaworowski 			return API_EINVAL;
432500856ebSRafal Jaworowski 		if (*len_stor <= 0)
433500856ebSRafal Jaworowski 			return API_EINVAL;
434500856ebSRafal Jaworowski 
435500856ebSRafal Jaworowski 		/* 4. arg - ptr to var with start block */
436500856ebSRafal Jaworowski 		start = (lbastart_t *)va_arg(ap, u_int32_t);
437500856ebSRafal Jaworowski 
438500856ebSRafal Jaworowski 		/* 5. arg - ptr to var where to put the len actually read */
439500856ebSRafal Jaworowski 		act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
440500856ebSRafal Jaworowski 		if (!act_len_stor)
441500856ebSRafal Jaworowski 			return API_EINVAL;
442500856ebSRafal Jaworowski 
443500856ebSRafal Jaworowski 		*act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
444500856ebSRafal Jaworowski 
445500856ebSRafal Jaworowski 	} else if (di->type & DEV_TYP_NET) {
446500856ebSRafal Jaworowski 
447500856ebSRafal Jaworowski 		/* 3. arg points to the var with length of packet to read */
448500856ebSRafal Jaworowski 		len_net = (int *)va_arg(ap, u_int32_t);
449500856ebSRafal Jaworowski 		if (!len_net)
450500856ebSRafal Jaworowski 			return API_EINVAL;
451500856ebSRafal Jaworowski 		if (*len_net <= 0)
452500856ebSRafal Jaworowski 			return API_EINVAL;
453500856ebSRafal Jaworowski 
454500856ebSRafal Jaworowski 		/* 4. - ptr to var where to put the len actually read */
455500856ebSRafal Jaworowski 		act_len_net = (int *)va_arg(ap, u_int32_t);
456500856ebSRafal Jaworowski 		if (!act_len_net)
457500856ebSRafal Jaworowski 			return API_EINVAL;
458500856ebSRafal Jaworowski 
459500856ebSRafal Jaworowski 		*act_len_net = dev_read_net(di->cookie, buf, *len_net);
460500856ebSRafal Jaworowski 
461500856ebSRafal Jaworowski 	} else
462500856ebSRafal Jaworowski 		return API_ENODEV;
463500856ebSRafal Jaworowski 
464500856ebSRafal Jaworowski 	return 0;
465500856ebSRafal Jaworowski }
466500856ebSRafal Jaworowski 
467500856ebSRafal Jaworowski 
468500856ebSRafal Jaworowski /*
469500856ebSRafal Jaworowski  * pseudo signature:
470500856ebSRafal Jaworowski  *
471500856ebSRafal Jaworowski  * int API_env_get(const char *name, char **value)
472500856ebSRafal Jaworowski  *
473500856ebSRafal Jaworowski  * name: ptr to name of env var
474500856ebSRafal Jaworowski  */
475500856ebSRafal Jaworowski static int API_env_get(va_list ap)
476500856ebSRafal Jaworowski {
477500856ebSRafal Jaworowski 	char *name, **value;
478500856ebSRafal Jaworowski 
479500856ebSRafal Jaworowski 	if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
480500856ebSRafal Jaworowski 		return API_EINVAL;
481500856ebSRafal Jaworowski 	if ((value = (char **)va_arg(ap, u_int32_t)) == NULL)
482500856ebSRafal Jaworowski 		return API_EINVAL;
483500856ebSRafal Jaworowski 
484500856ebSRafal Jaworowski 	*value = getenv(name);
485500856ebSRafal Jaworowski 
486500856ebSRafal Jaworowski 	return 0;
487500856ebSRafal Jaworowski }
488500856ebSRafal Jaworowski 
489500856ebSRafal Jaworowski /*
490500856ebSRafal Jaworowski  * pseudo signature:
491500856ebSRafal Jaworowski  *
492500856ebSRafal Jaworowski  * int API_env_set(const char *name, const char *value)
493500856ebSRafal Jaworowski  *
494500856ebSRafal Jaworowski  * name: ptr to name of env var
495500856ebSRafal Jaworowski  *
496500856ebSRafal Jaworowski  * value: ptr to value to be set
497500856ebSRafal Jaworowski  */
498500856ebSRafal Jaworowski static int API_env_set(va_list ap)
499500856ebSRafal Jaworowski {
500500856ebSRafal Jaworowski 	char *name, *value;
501500856ebSRafal Jaworowski 
502500856ebSRafal Jaworowski 	if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
503500856ebSRafal Jaworowski 		return API_EINVAL;
504500856ebSRafal Jaworowski 	if ((value = (char *)va_arg(ap, u_int32_t)) == NULL)
505500856ebSRafal Jaworowski 		return API_EINVAL;
506500856ebSRafal Jaworowski 
507500856ebSRafal Jaworowski 	setenv(name, value);
508500856ebSRafal Jaworowski 
509500856ebSRafal Jaworowski 	return 0;
510500856ebSRafal Jaworowski }
511500856ebSRafal Jaworowski 
512500856ebSRafal Jaworowski /*
513500856ebSRafal Jaworowski  * pseudo signature:
514500856ebSRafal Jaworowski  *
515500856ebSRafal Jaworowski  * int API_env_enum(const char *last, char **next)
516500856ebSRafal Jaworowski  *
517500856ebSRafal Jaworowski  * last: ptr to name of env var found in last iteration
518500856ebSRafal Jaworowski  */
519500856ebSRafal Jaworowski static int API_env_enum(va_list ap)
520500856ebSRafal Jaworowski {
521500856ebSRafal Jaworowski 	int i, n;
522500856ebSRafal Jaworowski 	char *last, **next;
523500856ebSRafal Jaworowski 
524500856ebSRafal Jaworowski 	last = (char *)va_arg(ap, u_int32_t);
525500856ebSRafal Jaworowski 
526500856ebSRafal Jaworowski 	if ((next = (char **)va_arg(ap, u_int32_t)) == NULL)
527500856ebSRafal Jaworowski 		return API_EINVAL;
528500856ebSRafal Jaworowski 
529500856ebSRafal Jaworowski 	if (last == NULL)
530500856ebSRafal Jaworowski 		/* start over */
531500856ebSRafal Jaworowski 		*next = ((char *)env_get_addr(0));
532500856ebSRafal Jaworowski 	else {
533500856ebSRafal Jaworowski 		*next = last;
534500856ebSRafal Jaworowski 
535500856ebSRafal Jaworowski 		for (i = 0; env_get_char(i) != '\0'; i = n + 1) {
536500856ebSRafal Jaworowski 			for (n = i; env_get_char(n) != '\0'; ++n) {
537*0e8d1586SJean-Christophe PLAGNIOL-VILLARD 				if (n >= CONFIG_ENV_SIZE) {
538500856ebSRafal Jaworowski 					/* XXX shouldn't we set *next = NULL?? */
539500856ebSRafal Jaworowski 					return 0;
540500856ebSRafal Jaworowski 				}
541500856ebSRafal Jaworowski 			}
542500856ebSRafal Jaworowski 
543500856ebSRafal Jaworowski 			if (envmatch((uchar *)last, i) < 0)
544500856ebSRafal Jaworowski 				continue;
545500856ebSRafal Jaworowski 
546500856ebSRafal Jaworowski 			/* try to get next name */
547500856ebSRafal Jaworowski 			i = n + 1;
548500856ebSRafal Jaworowski 			if (env_get_char(i) == '\0') {
549500856ebSRafal Jaworowski 				/* no more left */
550500856ebSRafal Jaworowski 				*next = NULL;
551500856ebSRafal Jaworowski 				return 0;
552500856ebSRafal Jaworowski 			}
553500856ebSRafal Jaworowski 
554500856ebSRafal Jaworowski 			*next = ((char *)env_get_addr(i));
555500856ebSRafal Jaworowski 			return 0;
556500856ebSRafal Jaworowski 		}
557500856ebSRafal Jaworowski 	}
558500856ebSRafal Jaworowski 
559500856ebSRafal Jaworowski 	return 0;
560500856ebSRafal Jaworowski }
561500856ebSRafal Jaworowski 
562500856ebSRafal Jaworowski static cfp_t calls_table[API_MAXCALL] = { NULL, };
563500856ebSRafal Jaworowski 
564500856ebSRafal Jaworowski /*
565500856ebSRafal Jaworowski  * The main syscall entry point - this is not reentrant, only one call is
566500856ebSRafal Jaworowski  * serviced until finished.
567500856ebSRafal Jaworowski  *
568500856ebSRafal Jaworowski  * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
569500856ebSRafal Jaworowski  *
570500856ebSRafal Jaworowski  * call:	syscall number
571500856ebSRafal Jaworowski  *
572500856ebSRafal Jaworowski  * retval:	points to the return value placeholder, this is the place the
573500856ebSRafal Jaworowski  *		syscall puts its return value, if NULL the caller does not
574500856ebSRafal Jaworowski  *		expect a return value
575500856ebSRafal Jaworowski  *
576500856ebSRafal Jaworowski  * ...		syscall arguments (variable number)
577500856ebSRafal Jaworowski  *
578500856ebSRafal Jaworowski  * returns:	0 if the call not found, 1 if serviced
579500856ebSRafal Jaworowski  */
580500856ebSRafal Jaworowski int syscall(int call, int *retval, ...)
581500856ebSRafal Jaworowski {
582500856ebSRafal Jaworowski 	va_list	ap;
583500856ebSRafal Jaworowski 	int rv;
584500856ebSRafal Jaworowski 
58520e5ed13SJean-Christophe PLAGNIOL-VILLARD 	if (call < 0 || call >= calls_no) {
586500856ebSRafal Jaworowski 		debugf("invalid call #%d\n", call);
587500856ebSRafal Jaworowski 		return 0;
588500856ebSRafal Jaworowski 	}
589500856ebSRafal Jaworowski 
590500856ebSRafal Jaworowski 	if (calls_table[call] == NULL) {
591500856ebSRafal Jaworowski 		debugf("syscall #%d does not have a handler\n", call);
592500856ebSRafal Jaworowski 		return 0;
593500856ebSRafal Jaworowski 	}
594500856ebSRafal Jaworowski 
595500856ebSRafal Jaworowski 	va_start(ap, retval);
596500856ebSRafal Jaworowski 	rv = calls_table[call](ap);
597500856ebSRafal Jaworowski 	if (retval != NULL)
598500856ebSRafal Jaworowski 		*retval = rv;
599500856ebSRafal Jaworowski 
600500856ebSRafal Jaworowski 	return 1;
601500856ebSRafal Jaworowski }
602500856ebSRafal Jaworowski 
603500856ebSRafal Jaworowski void api_init(void)
604500856ebSRafal Jaworowski {
605500856ebSRafal Jaworowski 	struct api_signature *sig = NULL;
606500856ebSRafal Jaworowski 
607500856ebSRafal Jaworowski 	/* TODO put this into linker set one day... */
608500856ebSRafal Jaworowski 	calls_table[API_RSVD] = NULL;
609500856ebSRafal Jaworowski 	calls_table[API_GETC] = &API_getc;
610500856ebSRafal Jaworowski 	calls_table[API_PUTC] = &API_putc;
611500856ebSRafal Jaworowski 	calls_table[API_TSTC] = &API_tstc;
612500856ebSRafal Jaworowski 	calls_table[API_PUTS] = &API_puts;
613500856ebSRafal Jaworowski 	calls_table[API_RESET] = &API_reset;
614500856ebSRafal Jaworowski 	calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
615500856ebSRafal Jaworowski 	calls_table[API_UDELAY] = &API_udelay;
616500856ebSRafal Jaworowski 	calls_table[API_GET_TIMER] = &API_get_timer;
617500856ebSRafal Jaworowski 	calls_table[API_DEV_ENUM] = &API_dev_enum;
618500856ebSRafal Jaworowski 	calls_table[API_DEV_OPEN] = &API_dev_open;
619500856ebSRafal Jaworowski 	calls_table[API_DEV_CLOSE] = &API_dev_close;
620500856ebSRafal Jaworowski 	calls_table[API_DEV_READ] = &API_dev_read;
621500856ebSRafal Jaworowski 	calls_table[API_DEV_WRITE] = &API_dev_write;
622500856ebSRafal Jaworowski 	calls_table[API_ENV_GET] = &API_env_get;
623500856ebSRafal Jaworowski 	calls_table[API_ENV_SET] = &API_env_set;
624500856ebSRafal Jaworowski 	calls_table[API_ENV_ENUM] = &API_env_enum;
625500856ebSRafal Jaworowski 	calls_no = API_MAXCALL;
626500856ebSRafal Jaworowski 
627500856ebSRafal Jaworowski 	debugf("API initialized with %d calls\n", calls_no);
628500856ebSRafal Jaworowski 
629500856ebSRafal Jaworowski 	dev_stor_init();
630500856ebSRafal Jaworowski 
631500856ebSRafal Jaworowski 	/*
632500856ebSRafal Jaworowski 	 * Produce the signature so the API consumers can find it
633500856ebSRafal Jaworowski 	 */
634500856ebSRafal Jaworowski 	sig = malloc(sizeof(struct api_signature));
635500856ebSRafal Jaworowski 	if (sig == NULL) {
636500856ebSRafal Jaworowski 		printf("API: could not allocate memory for the signature!\n");
637500856ebSRafal Jaworowski 		return;
638500856ebSRafal Jaworowski 	}
639500856ebSRafal Jaworowski 
640500856ebSRafal Jaworowski 	debugf("API sig @ 0x%08x\n", sig);
641500856ebSRafal Jaworowski 	memcpy(sig->magic, API_SIG_MAGIC, 8);
642500856ebSRafal Jaworowski 	sig->version = API_SIG_VERSION;
643500856ebSRafal Jaworowski 	sig->syscall = &syscall;
644500856ebSRafal Jaworowski 	sig->checksum = 0;
645500856ebSRafal Jaworowski 	sig->checksum = crc32(0, (unsigned char *)sig,
646500856ebSRafal Jaworowski 			      sizeof(struct api_signature));
647500856ebSRafal Jaworowski 	debugf("syscall entry: 0x%08x\n", sig->syscall);
648500856ebSRafal Jaworowski }
649500856ebSRafal Jaworowski 
650500856ebSRafal Jaworowski void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
651500856ebSRafal Jaworowski 			int flags)
652500856ebSRafal Jaworowski {
653500856ebSRafal Jaworowski 	int i;
654500856ebSRafal Jaworowski 
655500856ebSRafal Jaworowski 	if (!si->mr || !size || (flags == 0))
656500856ebSRafal Jaworowski 		return;
657500856ebSRafal Jaworowski 
658500856ebSRafal Jaworowski 	/* find free slot */
659500856ebSRafal Jaworowski 	for (i = 0; i < si->mr_no; i++)
660500856ebSRafal Jaworowski 		if (si->mr[i].flags == 0) {
661500856ebSRafal Jaworowski 			/* insert new mem region */
662500856ebSRafal Jaworowski 			si->mr[i].start = start;
663500856ebSRafal Jaworowski 			si->mr[i].size = size;
664500856ebSRafal Jaworowski 			si->mr[i].flags = flags;
665500856ebSRafal Jaworowski 			return;
666500856ebSRafal Jaworowski 		}
667500856ebSRafal Jaworowski }
668500856ebSRafal Jaworowski 
669500856ebSRafal Jaworowski #endif /* CONFIG_API */
670