1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  IOCB dispatcher		    	File: cfe_xreq.c
5    *
6    *  This routine is the main API dispatch for CFE.  User API
7    *  calls, via the ROM entry point, get dispatched to routines
8    *  in this module.
9    *
10    *  This module looks similar to cfe_iocb_dispatch - it is different
11    *  in that the data structure used, cfe_xiocb_t, uses fixed
12    *  size field members (specifically, all 64-bits) no matter how
13    *  the firmware is compiled.  This ensures a consistent API
14    *  interface on any implementation.  When you call CFE
15    *  from another program, the entry vector comes here first.
16    *
17    *  Should the normal cfe_iocb interface change, this one should
18    *  be kept the same for backward compatibility reasons.
19    *
20    *  Author:  Mitch Lichtenberg (mpl@broadcom.com)
21    *
22    *********************************************************************
23    *
24    *  Copyright 2000,2001,2002,2003
25    *  Broadcom Corporation. All rights reserved.
26    *
27    *  This software is furnished under license and may be used and
28    *  copied only in accordance with the following terms and
29    *  conditions.  Subject to these conditions, you may download,
30    *  copy, install, use, modify and distribute modified or unmodified
31    *  copies of this software in source and/or binary form.  No title
32    *  or ownership is transferred hereby.
33    *
34    *  1) Any source code used, modified or distributed must reproduce
35    *     and retain this copyright notice and list of conditions
36    *     as they appear in the source file.
37    *
38    *  2) No right is granted to use any trade name, trademark, or
39    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
40    *     name may not be used to endorse or promote products derived
41    *     from this software without the prior written permission of
42    *     Broadcom Corporation.
43    *
44    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
45    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
46    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
47    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
48    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
49    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
50    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
51    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
52    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
53    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
54    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
55    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
56    *     THE POSSIBILITY OF SUCH DAMAGE.
57    ********************************************************************* */
58
59
60#include "bsp_config.h"
61#include "lib_types.h"
62#include "lib_malloc.h"
63#include "lib_queue.h"
64#include "lib_printf.h"
65#include "lib_string.h"
66#include "cfe_iocb.h"
67#include "cfe_xiocb.h"
68#if CFG_VENDOR_EXTENSIONS
69#include "cfe_vendor_iocb.h"
70#include "cfe_vendor_xiocb.h"
71#endif
72#include "cfe_error.h"
73#include "cfe_device.h"
74#include "cfe_timer.h"
75#include "cfe_mem.h"
76#include "env_subr.h"
77#include "cfe.h"
78
79
80/*  *********************************************************************
81    *  Constants
82    ********************************************************************* */
83
84/* enum values for various plist types */
85
86#define PLBUF	1		/* iocb_buffer_t */
87#define PLCPU	2		/* iocb_cpuctl_t */
88#define PLMEM	3		/* iocb_meminfo_t */
89#define PLENV	4		/* iocb_envbuf_t */
90#define PLINP	5		/* iocb_inpstat_t */
91#define PLTIM	6		/* iocb_time_t */
92#define PLINF   7		/* iocb_fwinfo_t */
93#define PLEXIT  8		/* iocb_exitstat_t */
94
95/*  *********************************************************************
96    *  Structures
97    ********************************************************************* */
98
99struct cfe_xcmd_dispatch_s {
100    int xplistsize;
101    int iplistsize;
102    int plisttype;
103};
104
105
106/*  *********************************************************************
107    *  Command conversion table
108    *  This table contains useful information for converting
109    *  iocbs to xiocbs.
110    ********************************************************************* */
111
112const static struct cfe_xcmd_dispatch_s cfe_xcmd_dispatch_table[CFE_CMD_MAX] = {
113    {sizeof(xiocb_fwinfo_t), sizeof(iocb_fwinfo_t), PLINF},	/* 0 : CFE_CMD_FW_GETINFO */
114    {sizeof(xiocb_exitstat_t),sizeof(iocb_exitstat_t),PLEXIT},  /* 1 : CFE_CMD_FW_RESTART */
115    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 2 : CFE_CMD_FW_BOOT */
116    {sizeof(xiocb_cpuctl_t), sizeof(iocb_cpuctl_t), PLCPU},	/* 3 : CFE_CMD_FW_CPUCTL */
117    {sizeof(xiocb_time_t),   sizeof(iocb_time_t),   PLTIM},	/* 4 : CFE_CMD_FW_GETTIME */
118    {sizeof(xiocb_meminfo_t),sizeof(iocb_meminfo_t),PLMEM},	/* 5 : CFE_CMD_FW_MEMENUM */
119    {0,		    	     0,                     0},		/* 6 : CFE_CMD_FW_FLUSHCACHE */
120    {-1,		     0,                     0},		/* 7 : */
121    {-1,		     0,                     0},		/* 8 : */
122    {0,			     0,                     0},		/* 9 : CFE_CMD_DEV_GETHANDLE */
123    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 10 : CFE_CMD_DEV_ENUM */
124    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 11 : CFE_CMD_DEV_OPEN_*/
125    {sizeof(xiocb_inpstat_t),sizeof(iocb_inpstat_t),PLINP},	/* 12 : CFE_CMD_DEV_INPSTAT */
126    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 13 : CFE_CMD_DEV_READ */
127    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 14 : CFE_CMD_DEV_WRITE */
128    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 15 : CFE_CMD_DEV_IOCTL */
129    {0,			     0,                     0},		/* 16 : CFE_CMD_DEV_CLOSE */
130    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 17 : CFE_CMD_DEV_GETINFO */
131    {-1,		     0,                     0},		/* 18 : */
132    {-1,		     0,                     0},		/* 19 : */
133    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 20 : CFE_CMD_ENV_ENUM */
134    {-1,		     0,                     0},		/* 21 : */
135    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 22 : CFE_CMD_ENV_GET */
136    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 23 : CFE_CMD_ENV_SET */
137    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 24 : CFE_CMD_ENV_DEL */
138    {-1,		     0,                     0},		/* 25 : */
139    {-1,		     0,                     0},		/* 26 : */
140    {-1,		     0,                     0},		/* 27 : */
141    {-1,		     0,                     0},		/* 28 : */
142    {-1,		     0,                     0},		/* 29 : */
143    {-1,		     0,                     0},		/* 30 : */
144    {-1,		     0,                     0}		/* 31 : */
145};
146
147
148/*  *********************************************************************
149    *  Externs
150    ********************************************************************* */
151
152extern int cfe_iocb_dispatch(cfe_iocb_t *iocb);
153cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb);
154#if CFG_VENDOR_EXTENSIONS
155extern cfe_int_t cfe_vendor_doxreq(cfe_vendor_xiocb_t *xiocb);
156#endif
157
158/*  *********************************************************************
159    *  cfe_doxreq(xiocb)
160    *
161    *  Process an xiocb request.  This routine converts an xiocb
162    *  into an iocb, calls the IOCB dispatcher, converts the results
163    *  back into the xiocb, and returns.
164    *
165    *  Input parameters:
166    *  	   xiocb - pointer to user xiocb
167    *
168    *  Return value:
169    *  	   command status, <0 if error occured
170    ********************************************************************* */
171
172cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb)
173{
174    const struct cfe_xcmd_dispatch_s *disp;
175    cfe_iocb_t iiocb;
176    cfe_int_t res;
177
178    /*
179     * Call out to customer-specific IOCBs.  Customers may choose
180     * to implement their own XIOCBs directly, or go through their own
181     * translation layer (xiocb->iocb like CFE does) to insulate
182     * themselves from IOCB changes in the future.
183     */
184    if (xiocb->xiocb_fcode >= CFE_CMD_VENDOR_USE) {
185#if CFG_VENDOR_EXTENSIONS
186	return cfe_vendor_doxreq((cfe_vendor_xiocb_t *)xiocb);
187#else
188	return CFE_ERR_INV_COMMAND;
189#endif
190	}
191
192    /*
193     * Check for commands codes out of range
194     */
195
196    if ((xiocb->xiocb_fcode < 0) || (xiocb->xiocb_fcode >= CFE_CMD_MAX)) {
197	xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
198	return xiocb->xiocb_status;
199	}
200
201    /*
202     * Check for command codes in range but invalid
203     */
204
205    disp = &cfe_xcmd_dispatch_table[xiocb->xiocb_fcode];
206
207    if (disp->xplistsize < 0) {
208	xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
209	return xiocb->xiocb_status;
210	}
211
212    /*
213     * Check for invalid parameter list size
214     */
215
216    if (disp->xplistsize != xiocb->xiocb_psize) {
217	xiocb->xiocb_status = CFE_ERR_INV_PARAM;
218	return xiocb->xiocb_status;
219	}
220
221    /*
222     * Okay, copy parameters into the internal IOCB.
223     * First, the fixed header.
224     */
225
226    iiocb.iocb_fcode = (unsigned int) xiocb->xiocb_fcode;
227    iiocb.iocb_status = (int) xiocb->xiocb_status;
228    iiocb.iocb_handle = (int) xiocb->xiocb_handle;
229    iiocb.iocb_flags = (unsigned int) xiocb->xiocb_flags;
230    iiocb.iocb_psize = (unsigned int) disp->iplistsize;
231
232    /*
233     * Now the parameter list
234     */
235
236    switch (disp->plisttype) {
237	case PLBUF:
238	    iiocb.plist.iocb_buffer.buf_offset = (cfe_offset_t) xiocb->plist.xiocb_buffer.buf_offset;
239	    iiocb.plist.iocb_buffer.buf_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_buffer.buf_ptr;
240	    iiocb.plist.iocb_buffer.buf_length = (unsigned int) xiocb->plist.xiocb_buffer.buf_length;
241	    iiocb.plist.iocb_buffer.buf_retlen = (unsigned int) xiocb->plist.xiocb_buffer.buf_retlen;
242	    iiocb.plist.iocb_buffer.buf_ioctlcmd = (unsigned int) xiocb->plist.xiocb_buffer.buf_ioctlcmd;
243	    break;
244	case PLCPU:
245	    iiocb.plist.iocb_cpuctl.cpu_number = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_number;
246	    iiocb.plist.iocb_cpuctl.cpu_command = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_command;
247	    iiocb.plist.iocb_cpuctl.start_addr = (unsigned long) xiocb->plist.xiocb_cpuctl.start_addr;
248	    iiocb.plist.iocb_cpuctl.gp_val = (unsigned long) xiocb->plist.xiocb_cpuctl.gp_val;
249	    iiocb.plist.iocb_cpuctl.sp_val = (unsigned long) xiocb->plist.xiocb_cpuctl.sp_val;
250	    iiocb.plist.iocb_cpuctl.a1_val = (unsigned long) xiocb->plist.xiocb_cpuctl.a1_val;
251	    break;
252	case PLMEM:
253	    iiocb.plist.iocb_meminfo.mi_idx  = (int) xiocb->plist.xiocb_meminfo.mi_idx;
254	    iiocb.plist.iocb_meminfo.mi_type = (int) xiocb->plist.xiocb_meminfo.mi_type;
255	    iiocb.plist.iocb_meminfo.mi_addr = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_addr;
256	    iiocb.plist.iocb_meminfo.mi_size = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_size;
257	    break;
258	case PLENV:
259	    iiocb.plist.iocb_envbuf.enum_idx = (int) xiocb->plist.xiocb_envbuf.enum_idx;
260	    iiocb.plist.iocb_envbuf.name_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.name_ptr;
261	    iiocb.plist.iocb_envbuf.name_length = (int) xiocb->plist.xiocb_envbuf.name_length;
262	    iiocb.plist.iocb_envbuf.val_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.val_ptr;
263	    iiocb.plist.iocb_envbuf.val_length = (int) xiocb->plist.xiocb_envbuf.val_length;
264	    break;
265	case PLINP:
266	    iiocb.plist.iocb_inpstat.inp_status = (int) xiocb->plist.xiocb_inpstat.inp_status;
267	    break;
268	case PLTIM:
269	    iiocb.plist.iocb_time.ticks = (long long) xiocb->plist.xiocb_time.ticks;
270	    break;
271	case PLINF:
272	    break;
273	case PLEXIT:
274	    iiocb.plist.iocb_exitstat.status = (long long) xiocb->plist.xiocb_exitstat.status;
275	    break;
276	}
277
278    /*
279     * Do the internal function dispatch
280     */
281
282    res = (cfe_int_t) cfe_iocb_dispatch(&iiocb);
283
284    /*
285     * Now convert the parameter list members back
286     */
287
288    switch (disp->plisttype) {
289	case PLBUF:
290	    xiocb->plist.xiocb_buffer.buf_offset = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_offset;
291	    xiocb->plist.xiocb_buffer.buf_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_buffer.buf_ptr;
292	    xiocb->plist.xiocb_buffer.buf_length = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_length;
293	    xiocb->plist.xiocb_buffer.buf_retlen = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_retlen;
294	    xiocb->plist.xiocb_buffer.buf_ioctlcmd = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_ioctlcmd;
295	    break;
296	case PLCPU:
297	    xiocb->plist.xiocb_cpuctl.cpu_number = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_number;
298	    xiocb->plist.xiocb_cpuctl.cpu_command = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_command;
299	    xiocb->plist.xiocb_cpuctl.start_addr = (cfe_uint_t) iiocb.plist.iocb_cpuctl.start_addr;
300	    break;
301	case PLMEM:
302	    xiocb->plist.xiocb_meminfo.mi_idx = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_idx;
303	    xiocb->plist.xiocb_meminfo.mi_type = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_type;
304	    xiocb->plist.xiocb_meminfo.mi_addr = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_addr;
305	    xiocb->plist.xiocb_meminfo.mi_size = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_size;
306	    break;
307	case PLENV:
308	    xiocb->plist.xiocb_envbuf.enum_idx = (cfe_int_t) iiocb.plist.iocb_envbuf.enum_idx;
309	    xiocb->plist.xiocb_envbuf.name_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.name_ptr;
310	    xiocb->plist.xiocb_envbuf.name_length = (cfe_int_t) iiocb.plist.iocb_envbuf.name_length;
311	    xiocb->plist.xiocb_envbuf.val_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.val_ptr;
312	    xiocb->plist.xiocb_envbuf.val_length = (cfe_int_t) iiocb.plist.iocb_envbuf.val_length;
313	    break;
314	case PLINP:
315	    xiocb->plist.xiocb_inpstat.inp_status = (cfe_int_t) iiocb.plist.iocb_inpstat.inp_status;
316	    break;
317	case PLTIM:
318	    xiocb->plist.xiocb_time.ticks = (cfe_int_t) iiocb.plist.iocb_time.ticks;
319	    break;
320	case PLINF:
321	    xiocb->plist.xiocb_fwinfo.fwi_version = iiocb.plist.iocb_fwinfo.fwi_version;
322	    xiocb->plist.xiocb_fwinfo.fwi_totalmem = iiocb.plist.iocb_fwinfo.fwi_totalmem;
323	    xiocb->plist.xiocb_fwinfo.fwi_flags = iiocb.plist.iocb_fwinfo.fwi_flags;
324	    xiocb->plist.xiocb_fwinfo.fwi_boardid = iiocb.plist.iocb_fwinfo.fwi_boardid;
325	    xiocb->plist.xiocb_fwinfo.fwi_bootarea_va = iiocb.plist.iocb_fwinfo.fwi_bootarea_va;
326	    xiocb->plist.xiocb_fwinfo.fwi_bootarea_pa = iiocb.plist.iocb_fwinfo.fwi_bootarea_pa;
327	    xiocb->plist.xiocb_fwinfo.fwi_bootarea_size = iiocb.plist.iocb_fwinfo.fwi_bootarea_size;
328	    xiocb->plist.xiocb_fwinfo.fwi_reserved1 = iiocb.plist.iocb_fwinfo.fwi_reserved1;
329	    xiocb->plist.xiocb_fwinfo.fwi_reserved2 = iiocb.plist.iocb_fwinfo.fwi_reserved2;
330	    xiocb->plist.xiocb_fwinfo.fwi_reserved3 = iiocb.plist.iocb_fwinfo.fwi_reserved3;
331	    break;
332	case PLEXIT:
333	    xiocb->plist.xiocb_exitstat.status = (cfe_int_t) iiocb.plist.iocb_exitstat.status;
334	    break;
335	}
336
337    /*
338     * And the fixed header
339     */
340
341    xiocb->xiocb_status = (cfe_int_t) iiocb.iocb_status;
342    xiocb->xiocb_handle = (cfe_int_t) iiocb.iocb_handle;
343    xiocb->xiocb_flags = (cfe_uint_t) iiocb.iocb_flags;
344
345    return xiocb->xiocb_status;
346}
347