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