xref: /openbmc/u-boot/api/api.c (revision 500856eb)
1*500856ebSRafal Jaworowski /*
2*500856ebSRafal Jaworowski  * (C) Copyright 2007 Semihalf
3*500856ebSRafal Jaworowski  *
4*500856ebSRafal Jaworowski  * Written by: Rafal Jaworowski <raj@semihalf.com>
5*500856ebSRafal Jaworowski  *
6*500856ebSRafal Jaworowski  * See file CREDITS for list of people who contributed to this
7*500856ebSRafal Jaworowski  * project.
8*500856ebSRafal Jaworowski  *
9*500856ebSRafal Jaworowski  * This program is free software; you can redistribute it and/or
10*500856ebSRafal Jaworowski  * modify it under the terms of the GNU General Public License as
11*500856ebSRafal Jaworowski  * published by the Free Software Foundation; either version 2 of
12*500856ebSRafal Jaworowski  * the License, or (at your option) any later version.
13*500856ebSRafal Jaworowski  *
14*500856ebSRafal Jaworowski  * This program is distributed in the hope that it will be useful,
15*500856ebSRafal Jaworowski  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*500856ebSRafal Jaworowski  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*500856ebSRafal Jaworowski  * GNU General Public License for more details.
18*500856ebSRafal Jaworowski  *
19*500856ebSRafal Jaworowski  * You should have received a copy of the GNU General Public License
20*500856ebSRafal Jaworowski  * along with this program; if not, write to the Free Software
21*500856ebSRafal Jaworowski  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22*500856ebSRafal Jaworowski  * MA 02111-1307 USA
23*500856ebSRafal Jaworowski  *
24*500856ebSRafal Jaworowski  */
25*500856ebSRafal Jaworowski 
26*500856ebSRafal Jaworowski #include <config.h>
27*500856ebSRafal Jaworowski 
28*500856ebSRafal Jaworowski #if defined(CONFIG_API)
29*500856ebSRafal Jaworowski 
30*500856ebSRafal Jaworowski #include <command.h>
31*500856ebSRafal Jaworowski #include <common.h>
32*500856ebSRafal Jaworowski #include <malloc.h>
33*500856ebSRafal Jaworowski #include <linux/types.h>
34*500856ebSRafal Jaworowski #include <api_public.h>
35*500856ebSRafal Jaworowski 
36*500856ebSRafal Jaworowski #include "api_private.h"
37*500856ebSRafal Jaworowski 
38*500856ebSRafal Jaworowski #define DEBUG
39*500856ebSRafal Jaworowski #undef DEBUG
40*500856ebSRafal Jaworowski 
41*500856ebSRafal Jaworowski /* U-Boot routines needed */
42*500856ebSRafal Jaworowski extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
43*500856ebSRafal Jaworowski extern uchar (*env_get_char)(int);
44*500856ebSRafal Jaworowski extern uchar *env_get_addr(int);
45*500856ebSRafal Jaworowski 
46*500856ebSRafal Jaworowski /*****************************************************************************
47*500856ebSRafal Jaworowski  *
48*500856ebSRafal Jaworowski  * This is the API core.
49*500856ebSRafal Jaworowski  *
50*500856ebSRafal Jaworowski  * API_ functions are part of U-Boot code and constitute the lowest level
51*500856ebSRafal Jaworowski  * calls:
52*500856ebSRafal Jaworowski  *
53*500856ebSRafal Jaworowski  *  - they know what values they need as arguments
54*500856ebSRafal Jaworowski  *  - their direct return value pertains to the API_ "shell" itself (0 on
55*500856ebSRafal Jaworowski  *    success, some error code otherwise)
56*500856ebSRafal Jaworowski  *  - if the call returns a value it is buried within arguments
57*500856ebSRafal Jaworowski  *
58*500856ebSRafal Jaworowski  ****************************************************************************/
59*500856ebSRafal Jaworowski 
60*500856ebSRafal Jaworowski #ifdef DEBUG
61*500856ebSRafal Jaworowski #define debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt, ##args); } while (0)
62*500856ebSRafal Jaworowski #else
63*500856ebSRafal Jaworowski #define debugf(fmt, args...)
64*500856ebSRafal Jaworowski #endif
65*500856ebSRafal Jaworowski 
66*500856ebSRafal Jaworowski typedef	int (*cfp_t)(va_list argp);
67*500856ebSRafal Jaworowski 
68*500856ebSRafal Jaworowski static int calls_no;
69*500856ebSRafal Jaworowski 
70*500856ebSRafal Jaworowski /*
71*500856ebSRafal Jaworowski  * pseudo signature:
72*500856ebSRafal Jaworowski  *
73*500856ebSRafal Jaworowski  * int API_getc(int *c)
74*500856ebSRafal Jaworowski  */
75*500856ebSRafal Jaworowski static int API_getc(va_list ap)
76*500856ebSRafal Jaworowski {
77*500856ebSRafal Jaworowski 	int *c;
78*500856ebSRafal Jaworowski 
79*500856ebSRafal Jaworowski 	if ((c = (int *)va_arg(ap, u_int32_t)) == NULL)
80*500856ebSRafal Jaworowski 		return API_EINVAL;
81*500856ebSRafal Jaworowski 
82*500856ebSRafal Jaworowski 	*c = getc();
83*500856ebSRafal Jaworowski 	return 0;
84*500856ebSRafal Jaworowski }
85*500856ebSRafal Jaworowski 
86*500856ebSRafal Jaworowski /*
87*500856ebSRafal Jaworowski  * pseudo signature:
88*500856ebSRafal Jaworowski  *
89*500856ebSRafal Jaworowski  * int API_tstc(int *c)
90*500856ebSRafal Jaworowski  */
91*500856ebSRafal Jaworowski static int API_tstc(va_list ap)
92*500856ebSRafal Jaworowski {
93*500856ebSRafal Jaworowski 	int *t;
94*500856ebSRafal Jaworowski 
95*500856ebSRafal Jaworowski 	if ((t = (int *)va_arg(ap, u_int32_t)) == NULL)
96*500856ebSRafal Jaworowski 		return API_EINVAL;
97*500856ebSRafal Jaworowski 
98*500856ebSRafal Jaworowski 	*t = tstc();
99*500856ebSRafal Jaworowski 	return 0;
100*500856ebSRafal Jaworowski }
101*500856ebSRafal Jaworowski 
102*500856ebSRafal Jaworowski /*
103*500856ebSRafal Jaworowski  * pseudo signature:
104*500856ebSRafal Jaworowski  *
105*500856ebSRafal Jaworowski  * int API_putc(char *ch)
106*500856ebSRafal Jaworowski  */
107*500856ebSRafal Jaworowski static int API_putc(va_list ap)
108*500856ebSRafal Jaworowski {
109*500856ebSRafal Jaworowski 	char *c;
110*500856ebSRafal Jaworowski 
111*500856ebSRafal Jaworowski 	if ((c = (char *)va_arg(ap, u_int32_t)) == NULL)
112*500856ebSRafal Jaworowski 		return API_EINVAL;
113*500856ebSRafal Jaworowski 
114*500856ebSRafal Jaworowski 	putc(*c);
115*500856ebSRafal Jaworowski 	return 0;
116*500856ebSRafal Jaworowski }
117*500856ebSRafal Jaworowski 
118*500856ebSRafal Jaworowski /*
119*500856ebSRafal Jaworowski  * pseudo signature:
120*500856ebSRafal Jaworowski  *
121*500856ebSRafal Jaworowski  * int API_puts(char **s)
122*500856ebSRafal Jaworowski  */
123*500856ebSRafal Jaworowski static int API_puts(va_list ap)
124*500856ebSRafal Jaworowski {
125*500856ebSRafal Jaworowski 	char *s;
126*500856ebSRafal Jaworowski 
127*500856ebSRafal Jaworowski 	if ((s = (char *)va_arg(ap, u_int32_t)) == NULL)
128*500856ebSRafal Jaworowski 		return API_EINVAL;
129*500856ebSRafal Jaworowski 
130*500856ebSRafal Jaworowski 	puts(s);
131*500856ebSRafal Jaworowski 	return 0;
132*500856ebSRafal Jaworowski }
133*500856ebSRafal Jaworowski 
134*500856ebSRafal Jaworowski /*
135*500856ebSRafal Jaworowski  * pseudo signature:
136*500856ebSRafal Jaworowski  *
137*500856ebSRafal Jaworowski  * int API_reset(void)
138*500856ebSRafal Jaworowski  */
139*500856ebSRafal Jaworowski static int API_reset(va_list ap)
140*500856ebSRafal Jaworowski {
141*500856ebSRafal Jaworowski 	do_reset(NULL, 0, 0, NULL);
142*500856ebSRafal Jaworowski 
143*500856ebSRafal Jaworowski 	/* NOT REACHED */
144*500856ebSRafal Jaworowski 	return 0;
145*500856ebSRafal Jaworowski }
146*500856ebSRafal Jaworowski 
147*500856ebSRafal Jaworowski /*
148*500856ebSRafal Jaworowski  * pseudo signature:
149*500856ebSRafal Jaworowski  *
150*500856ebSRafal Jaworowski  * int API_get_sys_info(struct sys_info *si)
151*500856ebSRafal Jaworowski  *
152*500856ebSRafal Jaworowski  * fill out the sys_info struct containing selected parameters about the
153*500856ebSRafal Jaworowski  * machine
154*500856ebSRafal Jaworowski  */
155*500856ebSRafal Jaworowski static int API_get_sys_info(va_list ap)
156*500856ebSRafal Jaworowski {
157*500856ebSRafal Jaworowski 	struct sys_info *si;
158*500856ebSRafal Jaworowski 
159*500856ebSRafal Jaworowski 	si = (struct sys_info *)va_arg(ap, u_int32_t);
160*500856ebSRafal Jaworowski 	if (si == NULL)
161*500856ebSRafal Jaworowski 		return API_ENOMEM;
162*500856ebSRafal Jaworowski 
163*500856ebSRafal Jaworowski 	return (platform_sys_info(si)) ? 0 : API_ENODEV;
164*500856ebSRafal Jaworowski }
165*500856ebSRafal Jaworowski 
166*500856ebSRafal Jaworowski /*
167*500856ebSRafal Jaworowski  * pseudo signature:
168*500856ebSRafal Jaworowski  *
169*500856ebSRafal Jaworowski  * int API_udelay(unsigned long *udelay)
170*500856ebSRafal Jaworowski  */
171*500856ebSRafal Jaworowski static int API_udelay(va_list ap)
172*500856ebSRafal Jaworowski {
173*500856ebSRafal Jaworowski 	unsigned long *d;
174*500856ebSRafal Jaworowski 
175*500856ebSRafal Jaworowski 	if ((d = (unsigned long *)va_arg(ap, u_int32_t)) == NULL)
176*500856ebSRafal Jaworowski 		return API_EINVAL;
177*500856ebSRafal Jaworowski 
178*500856ebSRafal Jaworowski 	udelay(*d);
179*500856ebSRafal Jaworowski 	return 0;
180*500856ebSRafal Jaworowski }
181*500856ebSRafal Jaworowski 
182*500856ebSRafal Jaworowski /*
183*500856ebSRafal Jaworowski  * pseudo signature:
184*500856ebSRafal Jaworowski  *
185*500856ebSRafal Jaworowski  * int API_get_timer(unsigned long *current, unsigned long *base)
186*500856ebSRafal Jaworowski  */
187*500856ebSRafal Jaworowski static int API_get_timer(va_list ap)
188*500856ebSRafal Jaworowski {
189*500856ebSRafal Jaworowski 	unsigned long *base, *cur;
190*500856ebSRafal Jaworowski 
191*500856ebSRafal Jaworowski 	cur = (unsigned long *)va_arg(ap, u_int32_t);
192*500856ebSRafal Jaworowski 	if (cur == NULL)
193*500856ebSRafal Jaworowski 		return API_EINVAL;
194*500856ebSRafal Jaworowski 
195*500856ebSRafal Jaworowski 	base = (unsigned long *)va_arg(ap, u_int32_t);
196*500856ebSRafal Jaworowski 	if (base == NULL)
197*500856ebSRafal Jaworowski 		return API_EINVAL;
198*500856ebSRafal Jaworowski 
199*500856ebSRafal Jaworowski 	*cur = get_timer(*base);
200*500856ebSRafal Jaworowski 	return 0;
201*500856ebSRafal Jaworowski }
202*500856ebSRafal Jaworowski 
203*500856ebSRafal Jaworowski 
204*500856ebSRafal Jaworowski /*****************************************************************************
205*500856ebSRafal Jaworowski  *
206*500856ebSRafal Jaworowski  * pseudo signature:
207*500856ebSRafal Jaworowski  *
208*500856ebSRafal Jaworowski  * int API_dev_enum(struct device_info *)
209*500856ebSRafal Jaworowski  *
210*500856ebSRafal Jaworowski  *
211*500856ebSRafal Jaworowski  * cookies uniqely identify the previously enumerated device instance and
212*500856ebSRafal Jaworowski  * provide a hint for what to inspect in current enum iteration:
213*500856ebSRafal Jaworowski  *
214*500856ebSRafal Jaworowski  *   - net: &eth_device struct address from list pointed to by eth_devices
215*500856ebSRafal Jaworowski  *
216*500856ebSRafal Jaworowski  *   - storage: block_dev_desc_t struct address from &ide_dev_desc[n],
217*500856ebSRafal Jaworowski  *     &scsi_dev_desc[n] and similar tables
218*500856ebSRafal Jaworowski  *
219*500856ebSRafal Jaworowski  ****************************************************************************/
220*500856ebSRafal Jaworowski 
221*500856ebSRafal Jaworowski static int API_dev_enum(va_list ap)
222*500856ebSRafal Jaworowski {
223*500856ebSRafal Jaworowski 	struct device_info *di;
224*500856ebSRafal Jaworowski 
225*500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct we are going to fill out */
226*500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
227*500856ebSRafal Jaworowski 	if (di == NULL)
228*500856ebSRafal Jaworowski 		return API_EINVAL;
229*500856ebSRafal Jaworowski 
230*500856ebSRafal Jaworowski 	if (di->cookie == NULL) {
231*500856ebSRafal Jaworowski 		/* start over - clean up enumeration */
232*500856ebSRafal Jaworowski 		dev_enum_reset();	/* XXX shouldn't the name contain 'stor'? */
233*500856ebSRafal Jaworowski 		debugf("RESTART ENUM\n");
234*500856ebSRafal Jaworowski 
235*500856ebSRafal Jaworowski 		/* net device enumeration first */
236*500856ebSRafal Jaworowski 		if (dev_enum_net(di))
237*500856ebSRafal Jaworowski 			return 0;
238*500856ebSRafal Jaworowski 	}
239*500856ebSRafal Jaworowski 
240*500856ebSRafal Jaworowski 	/*
241*500856ebSRafal Jaworowski 	 * The hidden assumption is there can only be one active network
242*500856ebSRafal Jaworowski 	 * device and it is identified upon enumeration (re)start, so there's
243*500856ebSRafal Jaworowski 	 * no point in trying to find network devices in other cases than the
244*500856ebSRafal Jaworowski 	 * (re)start and hence the 'next' device can only be storage
245*500856ebSRafal Jaworowski 	 */
246*500856ebSRafal Jaworowski 	if (!dev_enum_storage(di))
247*500856ebSRafal Jaworowski 		/* make sure we mark there are no more devices */
248*500856ebSRafal Jaworowski 		di->cookie = NULL;
249*500856ebSRafal Jaworowski 
250*500856ebSRafal Jaworowski 	return 0;
251*500856ebSRafal Jaworowski }
252*500856ebSRafal Jaworowski 
253*500856ebSRafal Jaworowski 
254*500856ebSRafal Jaworowski static int API_dev_open(va_list ap)
255*500856ebSRafal Jaworowski {
256*500856ebSRafal Jaworowski 	struct device_info *di;
257*500856ebSRafal Jaworowski 	int err = 0;
258*500856ebSRafal Jaworowski 
259*500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct */
260*500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
261*500856ebSRafal Jaworowski 	if (di == NULL)
262*500856ebSRafal Jaworowski 		return API_EINVAL;
263*500856ebSRafal Jaworowski 
264*500856ebSRafal Jaworowski 	/* Allow only one consumer of the device at a time */
265*500856ebSRafal Jaworowski 	if (di->state == DEV_STA_OPEN)
266*500856ebSRafal Jaworowski 		return API_EBUSY;
267*500856ebSRafal Jaworowski 
268*500856ebSRafal Jaworowski 	if (di->cookie == NULL)
269*500856ebSRafal Jaworowski 		return API_ENODEV;
270*500856ebSRafal Jaworowski 
271*500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
272*500856ebSRafal Jaworowski 		err = dev_open_stor(di->cookie);
273*500856ebSRafal Jaworowski 
274*500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
275*500856ebSRafal Jaworowski 		err = dev_open_net(di->cookie);
276*500856ebSRafal Jaworowski 	else
277*500856ebSRafal Jaworowski 		err = API_ENODEV;
278*500856ebSRafal Jaworowski 
279*500856ebSRafal Jaworowski 	if (!err)
280*500856ebSRafal Jaworowski 		di->state = DEV_STA_OPEN;
281*500856ebSRafal Jaworowski 
282*500856ebSRafal Jaworowski 	return err;
283*500856ebSRafal Jaworowski }
284*500856ebSRafal Jaworowski 
285*500856ebSRafal Jaworowski 
286*500856ebSRafal Jaworowski static int API_dev_close(va_list ap)
287*500856ebSRafal Jaworowski {
288*500856ebSRafal Jaworowski 	struct device_info *di;
289*500856ebSRafal Jaworowski 	int err = 0;
290*500856ebSRafal Jaworowski 
291*500856ebSRafal Jaworowski 	/* arg is ptr to the device_info struct */
292*500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
293*500856ebSRafal Jaworowski 	if (di == NULL)
294*500856ebSRafal Jaworowski 		return API_EINVAL;
295*500856ebSRafal Jaworowski 
296*500856ebSRafal Jaworowski 	if (di->state == DEV_STA_CLOSED)
297*500856ebSRafal Jaworowski 		return 0;
298*500856ebSRafal Jaworowski 
299*500856ebSRafal Jaworowski 	if (di->cookie == NULL)
300*500856ebSRafal Jaworowski 		return API_ENODEV;
301*500856ebSRafal Jaworowski 
302*500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
303*500856ebSRafal Jaworowski 		err = dev_close_stor(di->cookie);
304*500856ebSRafal Jaworowski 
305*500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
306*500856ebSRafal Jaworowski 		err = dev_close_net(di->cookie);
307*500856ebSRafal Jaworowski 	else
308*500856ebSRafal Jaworowski 		/*
309*500856ebSRafal Jaworowski 		 * In case of unknown device we cannot change its state, so
310*500856ebSRafal Jaworowski 		 * only return error code
311*500856ebSRafal Jaworowski 		 */
312*500856ebSRafal Jaworowski 		err = API_ENODEV;
313*500856ebSRafal Jaworowski 
314*500856ebSRafal Jaworowski 	if (!err)
315*500856ebSRafal Jaworowski 		di->state = DEV_STA_CLOSED;
316*500856ebSRafal Jaworowski 
317*500856ebSRafal Jaworowski 	return err;
318*500856ebSRafal Jaworowski }
319*500856ebSRafal Jaworowski 
320*500856ebSRafal Jaworowski 
321*500856ebSRafal Jaworowski /*
322*500856ebSRafal Jaworowski  * Notice: this is for sending network packets only, as U-Boot does not
323*500856ebSRafal Jaworowski  * support writing to storage at the moment (12.2007)
324*500856ebSRafal Jaworowski  *
325*500856ebSRafal Jaworowski  * pseudo signature:
326*500856ebSRafal Jaworowski  *
327*500856ebSRafal Jaworowski  * int API_dev_write(
328*500856ebSRafal Jaworowski  *	struct device_info *di,
329*500856ebSRafal Jaworowski  *	void *buf,
330*500856ebSRafal Jaworowski  *	int *len
331*500856ebSRafal Jaworowski  * )
332*500856ebSRafal Jaworowski  *
333*500856ebSRafal Jaworowski  * buf:	ptr to buffer from where to get the data to send
334*500856ebSRafal Jaworowski  *
335*500856ebSRafal Jaworowski  * len: length of packet to be sent (in bytes)
336*500856ebSRafal Jaworowski  *
337*500856ebSRafal Jaworowski  */
338*500856ebSRafal Jaworowski static int API_dev_write(va_list ap)
339*500856ebSRafal Jaworowski {
340*500856ebSRafal Jaworowski 	struct device_info *di;
341*500856ebSRafal Jaworowski 	void *buf;
342*500856ebSRafal Jaworowski 	int *len;
343*500856ebSRafal Jaworowski 	int err = 0;
344*500856ebSRafal Jaworowski 
345*500856ebSRafal Jaworowski 	/* 1. arg is ptr to the device_info struct */
346*500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
347*500856ebSRafal Jaworowski 	if (di == NULL)
348*500856ebSRafal Jaworowski 		return API_EINVAL;
349*500856ebSRafal Jaworowski 
350*500856ebSRafal Jaworowski 	/* XXX should we check if device is open? i.e. the ->state ? */
351*500856ebSRafal Jaworowski 
352*500856ebSRafal Jaworowski 	if (di->cookie == NULL)
353*500856ebSRafal Jaworowski 		return API_ENODEV;
354*500856ebSRafal Jaworowski 
355*500856ebSRafal Jaworowski 	/* 2. arg is ptr to buffer from where to get data to write */
356*500856ebSRafal Jaworowski 	buf = (void *)va_arg(ap, u_int32_t);
357*500856ebSRafal Jaworowski 	if (buf == NULL)
358*500856ebSRafal Jaworowski 		return API_EINVAL;
359*500856ebSRafal Jaworowski 
360*500856ebSRafal Jaworowski 	/* 3. arg is length of buffer */
361*500856ebSRafal Jaworowski 	len = (int *)va_arg(ap, u_int32_t);
362*500856ebSRafal Jaworowski 	if (len == NULL)
363*500856ebSRafal Jaworowski 		return API_EINVAL;
364*500856ebSRafal Jaworowski 	if (*len <= 0)
365*500856ebSRafal Jaworowski 		return API_EINVAL;
366*500856ebSRafal Jaworowski 
367*500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR)
368*500856ebSRafal Jaworowski 		/*
369*500856ebSRafal Jaworowski 		 * write to storage is currently not supported by U-Boot:
370*500856ebSRafal Jaworowski 		 * no storage device implements block_write() method
371*500856ebSRafal Jaworowski 		 */
372*500856ebSRafal Jaworowski 		return API_ENODEV;
373*500856ebSRafal Jaworowski 
374*500856ebSRafal Jaworowski 	else if (di->type & DEV_TYP_NET)
375*500856ebSRafal Jaworowski 		err = dev_write_net(di->cookie, buf, *len);
376*500856ebSRafal Jaworowski 	else
377*500856ebSRafal Jaworowski 		err = API_ENODEV;
378*500856ebSRafal Jaworowski 
379*500856ebSRafal Jaworowski 	return err;
380*500856ebSRafal Jaworowski }
381*500856ebSRafal Jaworowski 
382*500856ebSRafal Jaworowski 
383*500856ebSRafal Jaworowski /*
384*500856ebSRafal Jaworowski  * pseudo signature:
385*500856ebSRafal Jaworowski  *
386*500856ebSRafal Jaworowski  * int API_dev_read(
387*500856ebSRafal Jaworowski  *	struct device_info *di,
388*500856ebSRafal Jaworowski  *	void *buf,
389*500856ebSRafal Jaworowski  *	size_t *len,
390*500856ebSRafal Jaworowski  *	unsigned long *start
391*500856ebSRafal Jaworowski  *	size_t *act_len
392*500856ebSRafal Jaworowski  * )
393*500856ebSRafal Jaworowski  *
394*500856ebSRafal Jaworowski  * buf:	ptr to buffer where to put the read data
395*500856ebSRafal Jaworowski  *
396*500856ebSRafal Jaworowski  * len: ptr to length to be read
397*500856ebSRafal Jaworowski  *      - network: len of packet to read (in bytes)
398*500856ebSRafal Jaworowski  *      - storage: # of blocks to read (can vary in size depending on define)
399*500856ebSRafal Jaworowski  *
400*500856ebSRafal Jaworowski  * start: ptr to start block (only used for storage devices, ignored for
401*500856ebSRafal Jaworowski  *        network)
402*500856ebSRafal Jaworowski  *
403*500856ebSRafal Jaworowski  * act_len: ptr to where to put the len actually read
404*500856ebSRafal Jaworowski  */
405*500856ebSRafal Jaworowski static int API_dev_read(va_list ap)
406*500856ebSRafal Jaworowski {
407*500856ebSRafal Jaworowski 	struct device_info *di;
408*500856ebSRafal Jaworowski 	void *buf;
409*500856ebSRafal Jaworowski 	lbasize_t *len_stor, *act_len_stor;
410*500856ebSRafal Jaworowski 	lbastart_t *start;
411*500856ebSRafal Jaworowski 	int *len_net, *act_len_net;
412*500856ebSRafal Jaworowski 
413*500856ebSRafal Jaworowski 	/* 1. arg is ptr to the device_info struct */
414*500856ebSRafal Jaworowski 	di = (struct device_info *)va_arg(ap, u_int32_t);
415*500856ebSRafal Jaworowski 	if (di == NULL)
416*500856ebSRafal Jaworowski 		return API_EINVAL;
417*500856ebSRafal Jaworowski 
418*500856ebSRafal Jaworowski 	/* XXX should we check if device is open? i.e. the ->state ? */
419*500856ebSRafal Jaworowski 
420*500856ebSRafal Jaworowski 	if (di->cookie == NULL)
421*500856ebSRafal Jaworowski 		return API_ENODEV;
422*500856ebSRafal Jaworowski 
423*500856ebSRafal Jaworowski 	/* 2. arg is ptr to buffer from where to put the read data */
424*500856ebSRafal Jaworowski 	buf = (void *)va_arg(ap, u_int32_t);
425*500856ebSRafal Jaworowski 	if (buf == NULL)
426*500856ebSRafal Jaworowski 		return API_EINVAL;
427*500856ebSRafal Jaworowski 
428*500856ebSRafal Jaworowski 	if (di->type & DEV_TYP_STOR) {
429*500856ebSRafal Jaworowski 		/* 3. arg - ptr to var with # of blocks to read */
430*500856ebSRafal Jaworowski 		len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
431*500856ebSRafal Jaworowski 		if (!len_stor)
432*500856ebSRafal Jaworowski 			return API_EINVAL;
433*500856ebSRafal Jaworowski 		if (*len_stor <= 0)
434*500856ebSRafal Jaworowski 			return API_EINVAL;
435*500856ebSRafal Jaworowski 
436*500856ebSRafal Jaworowski 		/* 4. arg - ptr to var with start block */
437*500856ebSRafal Jaworowski 		start = (lbastart_t *)va_arg(ap, u_int32_t);
438*500856ebSRafal Jaworowski 
439*500856ebSRafal Jaworowski 		/* 5. arg - ptr to var where to put the len actually read */
440*500856ebSRafal Jaworowski 		act_len_stor = (lbasize_t *)va_arg(ap, u_int32_t);
441*500856ebSRafal Jaworowski 		if (!act_len_stor)
442*500856ebSRafal Jaworowski 			return API_EINVAL;
443*500856ebSRafal Jaworowski 
444*500856ebSRafal Jaworowski 		*act_len_stor = dev_read_stor(di->cookie, buf, *len_stor, *start);
445*500856ebSRafal Jaworowski 
446*500856ebSRafal Jaworowski 	} else if (di->type & DEV_TYP_NET) {
447*500856ebSRafal Jaworowski 
448*500856ebSRafal Jaworowski 		/* 3. arg points to the var with length of packet to read */
449*500856ebSRafal Jaworowski 		len_net = (int *)va_arg(ap, u_int32_t);
450*500856ebSRafal Jaworowski 		if (!len_net)
451*500856ebSRafal Jaworowski 			return API_EINVAL;
452*500856ebSRafal Jaworowski 		if (*len_net <= 0)
453*500856ebSRafal Jaworowski 			return API_EINVAL;
454*500856ebSRafal Jaworowski 
455*500856ebSRafal Jaworowski 		/* 4. - ptr to var where to put the len actually read */
456*500856ebSRafal Jaworowski 		act_len_net = (int *)va_arg(ap, u_int32_t);
457*500856ebSRafal Jaworowski 		if (!act_len_net)
458*500856ebSRafal Jaworowski 			return API_EINVAL;
459*500856ebSRafal Jaworowski 
460*500856ebSRafal Jaworowski 		*act_len_net = dev_read_net(di->cookie, buf, *len_net);
461*500856ebSRafal Jaworowski 
462*500856ebSRafal Jaworowski 	} else
463*500856ebSRafal Jaworowski 		return API_ENODEV;
464*500856ebSRafal Jaworowski 
465*500856ebSRafal Jaworowski 	return 0;
466*500856ebSRafal Jaworowski }
467*500856ebSRafal Jaworowski 
468*500856ebSRafal Jaworowski 
469*500856ebSRafal Jaworowski /*
470*500856ebSRafal Jaworowski  * pseudo signature:
471*500856ebSRafal Jaworowski  *
472*500856ebSRafal Jaworowski  * int API_env_get(const char *name, char **value)
473*500856ebSRafal Jaworowski  *
474*500856ebSRafal Jaworowski  * name: ptr to name of env var
475*500856ebSRafal Jaworowski  */
476*500856ebSRafal Jaworowski static int API_env_get(va_list ap)
477*500856ebSRafal Jaworowski {
478*500856ebSRafal Jaworowski 	char *name, **value;
479*500856ebSRafal Jaworowski 
480*500856ebSRafal Jaworowski 	if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
481*500856ebSRafal Jaworowski 		return API_EINVAL;
482*500856ebSRafal Jaworowski 	if ((value = (char **)va_arg(ap, u_int32_t)) == NULL)
483*500856ebSRafal Jaworowski 		return API_EINVAL;
484*500856ebSRafal Jaworowski 
485*500856ebSRafal Jaworowski 	*value = getenv(name);
486*500856ebSRafal Jaworowski 
487*500856ebSRafal Jaworowski 	return 0;
488*500856ebSRafal Jaworowski }
489*500856ebSRafal Jaworowski 
490*500856ebSRafal Jaworowski /*
491*500856ebSRafal Jaworowski  * pseudo signature:
492*500856ebSRafal Jaworowski  *
493*500856ebSRafal Jaworowski  * int API_env_set(const char *name, const char *value)
494*500856ebSRafal Jaworowski  *
495*500856ebSRafal Jaworowski  * name: ptr to name of env var
496*500856ebSRafal Jaworowski  *
497*500856ebSRafal Jaworowski  * value: ptr to value to be set
498*500856ebSRafal Jaworowski  */
499*500856ebSRafal Jaworowski static int API_env_set(va_list ap)
500*500856ebSRafal Jaworowski {
501*500856ebSRafal Jaworowski 	char *name, *value;
502*500856ebSRafal Jaworowski 
503*500856ebSRafal Jaworowski 	if ((name = (char *)va_arg(ap, u_int32_t)) == NULL)
504*500856ebSRafal Jaworowski 		return API_EINVAL;
505*500856ebSRafal Jaworowski 	if ((value = (char *)va_arg(ap, u_int32_t)) == NULL)
506*500856ebSRafal Jaworowski 		return API_EINVAL;
507*500856ebSRafal Jaworowski 
508*500856ebSRafal Jaworowski 	setenv(name, value);
509*500856ebSRafal Jaworowski 
510*500856ebSRafal Jaworowski 	return 0;
511*500856ebSRafal Jaworowski }
512*500856ebSRafal Jaworowski 
513*500856ebSRafal Jaworowski /*
514*500856ebSRafal Jaworowski  * pseudo signature:
515*500856ebSRafal Jaworowski  *
516*500856ebSRafal Jaworowski  * int API_env_enum(const char *last, char **next)
517*500856ebSRafal Jaworowski  *
518*500856ebSRafal Jaworowski  * last: ptr to name of env var found in last iteration
519*500856ebSRafal Jaworowski  */
520*500856ebSRafal Jaworowski static int API_env_enum(va_list ap)
521*500856ebSRafal Jaworowski {
522*500856ebSRafal Jaworowski 	int i, n;
523*500856ebSRafal Jaworowski 	char *last, **next;
524*500856ebSRafal Jaworowski 
525*500856ebSRafal Jaworowski 	last = (char *)va_arg(ap, u_int32_t);
526*500856ebSRafal Jaworowski 
527*500856ebSRafal Jaworowski 	if ((next = (char **)va_arg(ap, u_int32_t)) == NULL)
528*500856ebSRafal Jaworowski 		return API_EINVAL;
529*500856ebSRafal Jaworowski 
530*500856ebSRafal Jaworowski 	if (last == NULL)
531*500856ebSRafal Jaworowski 		/* start over */
532*500856ebSRafal Jaworowski 		*next = ((char *)env_get_addr(0));
533*500856ebSRafal Jaworowski 	else {
534*500856ebSRafal Jaworowski 		*next = last;
535*500856ebSRafal Jaworowski 
536*500856ebSRafal Jaworowski 		for (i = 0; env_get_char(i) != '\0'; i = n + 1) {
537*500856ebSRafal Jaworowski 			for (n = i; env_get_char(n) != '\0'; ++n) {
538*500856ebSRafal Jaworowski 				if (n >= CFG_ENV_SIZE) {
539*500856ebSRafal Jaworowski 					/* XXX shouldn't we set *next = NULL?? */
540*500856ebSRafal Jaworowski 					return 0;
541*500856ebSRafal Jaworowski 				}
542*500856ebSRafal Jaworowski 			}
543*500856ebSRafal Jaworowski 
544*500856ebSRafal Jaworowski 			if (envmatch((uchar *)last, i) < 0)
545*500856ebSRafal Jaworowski 				continue;
546*500856ebSRafal Jaworowski 
547*500856ebSRafal Jaworowski 			/* try to get next name */
548*500856ebSRafal Jaworowski 			i = n + 1;
549*500856ebSRafal Jaworowski 			if (env_get_char(i) == '\0') {
550*500856ebSRafal Jaworowski 				/* no more left */
551*500856ebSRafal Jaworowski 				*next = NULL;
552*500856ebSRafal Jaworowski 				return 0;
553*500856ebSRafal Jaworowski 			}
554*500856ebSRafal Jaworowski 
555*500856ebSRafal Jaworowski 			*next = ((char *)env_get_addr(i));
556*500856ebSRafal Jaworowski 			return 0;
557*500856ebSRafal Jaworowski 		}
558*500856ebSRafal Jaworowski 	}
559*500856ebSRafal Jaworowski 
560*500856ebSRafal Jaworowski 	return 0;
561*500856ebSRafal Jaworowski }
562*500856ebSRafal Jaworowski 
563*500856ebSRafal Jaworowski static cfp_t calls_table[API_MAXCALL] = { NULL, };
564*500856ebSRafal Jaworowski 
565*500856ebSRafal Jaworowski /*
566*500856ebSRafal Jaworowski  * The main syscall entry point - this is not reentrant, only one call is
567*500856ebSRafal Jaworowski  * serviced until finished.
568*500856ebSRafal Jaworowski  *
569*500856ebSRafal Jaworowski  * e.g. syscall(1, int *, u_int32_t, u_int32_t, u_int32_t, u_int32_t);
570*500856ebSRafal Jaworowski  *
571*500856ebSRafal Jaworowski  * call:	syscall number
572*500856ebSRafal Jaworowski  *
573*500856ebSRafal Jaworowski  * retval:	points to the return value placeholder, this is the place the
574*500856ebSRafal Jaworowski  *		syscall puts its return value, if NULL the caller does not
575*500856ebSRafal Jaworowski  *		expect a return value
576*500856ebSRafal Jaworowski  *
577*500856ebSRafal Jaworowski  * ...		syscall arguments (variable number)
578*500856ebSRafal Jaworowski  *
579*500856ebSRafal Jaworowski  * returns:	0 if the call not found, 1 if serviced
580*500856ebSRafal Jaworowski  */
581*500856ebSRafal Jaworowski int syscall(int call, int *retval, ...)
582*500856ebSRafal Jaworowski {
583*500856ebSRafal Jaworowski 	va_list	ap;
584*500856ebSRafal Jaworowski 	int rv;
585*500856ebSRafal Jaworowski 
586*500856ebSRafal Jaworowski 	if (call < 0 || call >= calls_no || calls_table[call] == NULL) {
587*500856ebSRafal Jaworowski 		debugf("invalid call #%d\n", call);
588*500856ebSRafal Jaworowski 		return 0;
589*500856ebSRafal Jaworowski 	}
590*500856ebSRafal Jaworowski 
591*500856ebSRafal Jaworowski 	if (calls_table[call] == NULL) {
592*500856ebSRafal Jaworowski 		debugf("syscall #%d does not have a handler\n", call);
593*500856ebSRafal Jaworowski 		return 0;
594*500856ebSRafal Jaworowski 	}
595*500856ebSRafal Jaworowski 
596*500856ebSRafal Jaworowski 	va_start(ap, retval);
597*500856ebSRafal Jaworowski 	rv = calls_table[call](ap);
598*500856ebSRafal Jaworowski 	if (retval != NULL)
599*500856ebSRafal Jaworowski 		*retval = rv;
600*500856ebSRafal Jaworowski 
601*500856ebSRafal Jaworowski 	return 1;
602*500856ebSRafal Jaworowski }
603*500856ebSRafal Jaworowski 
604*500856ebSRafal Jaworowski void api_init(void)
605*500856ebSRafal Jaworowski {
606*500856ebSRafal Jaworowski 	struct api_signature *sig = NULL;
607*500856ebSRafal Jaworowski 
608*500856ebSRafal Jaworowski 	/* TODO put this into linker set one day... */
609*500856ebSRafal Jaworowski 	calls_table[API_RSVD] = NULL;
610*500856ebSRafal Jaworowski 	calls_table[API_GETC] = &API_getc;
611*500856ebSRafal Jaworowski 	calls_table[API_PUTC] = &API_putc;
612*500856ebSRafal Jaworowski 	calls_table[API_TSTC] = &API_tstc;
613*500856ebSRafal Jaworowski 	calls_table[API_PUTS] = &API_puts;
614*500856ebSRafal Jaworowski 	calls_table[API_RESET] = &API_reset;
615*500856ebSRafal Jaworowski 	calls_table[API_GET_SYS_INFO] = &API_get_sys_info;
616*500856ebSRafal Jaworowski 	calls_table[API_UDELAY] = &API_udelay;
617*500856ebSRafal Jaworowski 	calls_table[API_GET_TIMER] = &API_get_timer;
618*500856ebSRafal Jaworowski 	calls_table[API_DEV_ENUM] = &API_dev_enum;
619*500856ebSRafal Jaworowski 	calls_table[API_DEV_OPEN] = &API_dev_open;
620*500856ebSRafal Jaworowski 	calls_table[API_DEV_CLOSE] = &API_dev_close;
621*500856ebSRafal Jaworowski 	calls_table[API_DEV_READ] = &API_dev_read;
622*500856ebSRafal Jaworowski 	calls_table[API_DEV_WRITE] = &API_dev_write;
623*500856ebSRafal Jaworowski 	calls_table[API_ENV_GET] = &API_env_get;
624*500856ebSRafal Jaworowski 	calls_table[API_ENV_SET] = &API_env_set;
625*500856ebSRafal Jaworowski 	calls_table[API_ENV_ENUM] = &API_env_enum;
626*500856ebSRafal Jaworowski 	calls_no = API_MAXCALL;
627*500856ebSRafal Jaworowski 
628*500856ebSRafal Jaworowski 	debugf("API initialized with %d calls\n", calls_no);
629*500856ebSRafal Jaworowski 
630*500856ebSRafal Jaworowski 	dev_stor_init();
631*500856ebSRafal Jaworowski 
632*500856ebSRafal Jaworowski 	/*
633*500856ebSRafal Jaworowski 	 * Produce the signature so the API consumers can find it
634*500856ebSRafal Jaworowski 	 */
635*500856ebSRafal Jaworowski 	sig = malloc(sizeof(struct api_signature));
636*500856ebSRafal Jaworowski 	if (sig == NULL) {
637*500856ebSRafal Jaworowski 		printf("API: could not allocate memory for the signature!\n");
638*500856ebSRafal Jaworowski 		return;
639*500856ebSRafal Jaworowski 	}
640*500856ebSRafal Jaworowski 
641*500856ebSRafal Jaworowski 	debugf("API sig @ 0x%08x\n", sig);
642*500856ebSRafal Jaworowski 	memcpy(sig->magic, API_SIG_MAGIC, 8);
643*500856ebSRafal Jaworowski 	sig->version = API_SIG_VERSION;
644*500856ebSRafal Jaworowski 	sig->syscall = &syscall;
645*500856ebSRafal Jaworowski 	sig->checksum = 0;
646*500856ebSRafal Jaworowski 	sig->checksum = crc32(0, (unsigned char *)sig,
647*500856ebSRafal Jaworowski 			      sizeof(struct api_signature));
648*500856ebSRafal Jaworowski 	debugf("syscall entry: 0x%08x\n", sig->syscall);
649*500856ebSRafal Jaworowski }
650*500856ebSRafal Jaworowski 
651*500856ebSRafal Jaworowski void platform_set_mr(struct sys_info *si, unsigned long start, unsigned long size,
652*500856ebSRafal Jaworowski 			int flags)
653*500856ebSRafal Jaworowski {
654*500856ebSRafal Jaworowski 	int i;
655*500856ebSRafal Jaworowski 
656*500856ebSRafal Jaworowski 	if (!si->mr || !size || (flags == 0))
657*500856ebSRafal Jaworowski 		return;
658*500856ebSRafal Jaworowski 
659*500856ebSRafal Jaworowski 	/* find free slot */
660*500856ebSRafal Jaworowski 	for (i = 0; i < si->mr_no; i++)
661*500856ebSRafal Jaworowski 		if (si->mr[i].flags == 0) {
662*500856ebSRafal Jaworowski 			/* insert new mem region */
663*500856ebSRafal Jaworowski 			si->mr[i].start = start;
664*500856ebSRafal Jaworowski 			si->mr[i].size = size;
665*500856ebSRafal Jaworowski 			si->mr[i].flags = flags;
666*500856ebSRafal Jaworowski 			return;
667*500856ebSRafal Jaworowski 		}
668*500856ebSRafal Jaworowski }
669*500856ebSRafal Jaworowski 
670*500856ebSRafal Jaworowski #endif /* CONFIG_API */
671