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
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 "cfe.h"
61#include "cfe_xiocb.h"
62#if CFG_VENDOR_EXTENSIONS
63#include "cfe_vendor_iocb.h"
64#include "cfe_vendor_xiocb.h"
65#endif
66#include "env_subr.h"
67
68
69/*  *********************************************************************
70    *  Constants
71    ********************************************************************* */
72
73/* enum values for various plist types */
74
75#define PLBUF	1		/* iocb_buffer_t */
76#define PLCPU	2		/* iocb_cpuctl_t */
77#define PLMEM	3		/* iocb_meminfo_t */
78#define PLENV	4		/* iocb_envbuf_t */
79#define PLINP	5		/* iocb_inpstat_t */
80#define PLTIM	6		/* iocb_time_t */
81#define PLINF   7		/* iocb_fwinfo_t */
82#define PLEXIT  8		/* iocb_exitstat_t */
83
84/*  *********************************************************************
85    *  Structures
86    ********************************************************************* */
87
88struct cfe_xcmd_dispatch_s {
89    int xplistsize;
90    int iplistsize;
91    int plisttype;
92};
93
94
95/*  *********************************************************************
96    *  Command conversion table
97    *  This table contains useful information for converting
98    *  iocbs to xiocbs.
99    ********************************************************************* */
100
101const static struct cfe_xcmd_dispatch_s cfe_xcmd_dispatch_table[CFE_CMD_MAX] = {
102    {sizeof(xiocb_fwinfo_t), sizeof(iocb_fwinfo_t), PLINF},	/* 0 : CFE_CMD_FW_GETINFO */
103    {sizeof(xiocb_exitstat_t),sizeof(iocb_exitstat_t),PLEXIT},  /* 1 : CFE_CMD_FW_RESTART */
104    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 2 : CFE_CMD_FW_BOOT */
105    {sizeof(xiocb_cpuctl_t), sizeof(iocb_cpuctl_t), PLCPU},	/* 3 : CFE_CMD_FW_CPUCTL */
106    {sizeof(xiocb_time_t),   sizeof(iocb_time_t),   PLTIM},	/* 4 : CFE_CMD_FW_GETTIME */
107    {sizeof(xiocb_meminfo_t),sizeof(iocb_meminfo_t),PLMEM},	/* 5 : CFE_CMD_FW_MEMENUM */
108    {0,		    	     0,                     0},		/* 6 : CFE_CMD_FW_FLUSHCACHE */
109    {-1,		     0,                     0},		/* 7 : */
110    {-1,		     0,                     0},		/* 8 : */
111    {0,			     0,                     0},		/* 9 : CFE_CMD_DEV_GETHANDLE */
112    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 10 : CFE_CMD_DEV_ENUM */
113    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 11 : CFE_CMD_DEV_OPEN_*/
114    {sizeof(xiocb_inpstat_t),sizeof(iocb_inpstat_t),PLINP},	/* 12 : CFE_CMD_DEV_INPSTAT */
115    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 13 : CFE_CMD_DEV_READ */
116    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 14 : CFE_CMD_DEV_WRITE */
117    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 15 : CFE_CMD_DEV_IOCTL */
118    {0,			     0,                     0},		/* 16 : CFE_CMD_DEV_CLOSE */
119    {sizeof(xiocb_buffer_t), sizeof(iocb_buffer_t), PLBUF},	/* 17 : CFE_CMD_DEV_GETINFO */
120    {-1,		     0,                     0},		/* 18 : */
121    {-1,		     0,                     0},		/* 19 : */
122    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 20 : CFE_CMD_ENV_ENUM */
123    {-1,		     0,                     0},		/* 21 : */
124    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 22 : CFE_CMD_ENV_GET */
125    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 23 : CFE_CMD_ENV_SET */
126    {sizeof(xiocb_envbuf_t), sizeof(iocb_envbuf_t), PLENV},	/* 24 : CFE_CMD_ENV_DEL */
127    {-1,		     0,                     0},		/* 25 : */
128    {-1,		     0,                     0},		/* 26 : */
129    {-1,		     0,                     0},		/* 27 : */
130    {-1,		     0,                     0},		/* 28 : */
131    {-1,		     0,                     0},		/* 29 : */
132    {-1,		     0,                     0},		/* 30 : */
133    {-1,		     0,                     0}		/* 31 : */
134};
135
136
137/*  *********************************************************************
138    *  Externs
139    ********************************************************************* */
140
141extern int cfe_iocb_dispatch(cfe_iocb_t *iocb);
142cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb);
143#if CFG_VENDOR_EXTENSIONS
144extern cfe_int_t cfe_vendor_doxreq(cfe_vendor_xiocb_t *xiocb);
145#endif
146
147/*  *********************************************************************
148    *  cfe_doxreq(xiocb)
149    *
150    *  Process an xiocb request.  This routine converts an xiocb
151    *  into an iocb, calls the IOCB dispatcher, converts the results
152    *  back into the xiocb, and returns.
153    *
154    *  Input parameters:
155    *  	   xiocb - pointer to user xiocb
156    *
157    *  Return value:
158    *  	   command status, <0 if error occured
159    ********************************************************************* */
160
161cfe_int_t cfe_doxreq(cfe_xiocb_t *xiocb)
162{
163    const struct cfe_xcmd_dispatch_s *disp;
164    cfe_iocb_t iiocb;
165    cfe_int_t res;
166
167    /*
168     * Call out to customer-specific IOCBs.  Customers may choose
169     * to implement their own XIOCBs directly, or go through their own
170     * translation layer (xiocb->iocb like CFE does) to insulate
171     * themselves from IOCB changes in the future.
172     */
173    if (xiocb->xiocb_fcode >= CFE_CMD_VENDOR_USE) {
174#if CFG_VENDOR_EXTENSIONS
175	return cfe_vendor_doxreq((cfe_vendor_xiocb_t *)xiocb);
176#else
177	return CFE_ERR_INV_COMMAND;
178#endif
179	}
180
181    /*
182     * Check for commands codes out of range
183     */
184
185    if ((xiocb->xiocb_fcode < 0) || (xiocb->xiocb_fcode >= CFE_CMD_MAX)) {
186	xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
187	return xiocb->xiocb_status;
188	}
189
190    /*
191     * Check for command codes in range but invalid
192     */
193
194    disp = &cfe_xcmd_dispatch_table[xiocb->xiocb_fcode];
195
196    if (disp->xplistsize < 0) {
197	xiocb->xiocb_status = CFE_ERR_INV_COMMAND;
198	return xiocb->xiocb_status;
199	}
200
201    /*
202     * Check for invalid parameter list size
203     */
204
205    if (disp->xplistsize != xiocb->xiocb_psize) {
206	xiocb->xiocb_status = CFE_ERR_INV_PARAM;
207	return xiocb->xiocb_status;
208	}
209
210    /*
211     * Okay, copy parameters into the internal IOCB.
212     * First, the fixed header.
213     */
214
215    iiocb.iocb_fcode = (unsigned int) xiocb->xiocb_fcode;
216    iiocb.iocb_status = (int) xiocb->xiocb_status;
217    iiocb.iocb_handle = (int) xiocb->xiocb_handle;
218    iiocb.iocb_flags = (unsigned int) xiocb->xiocb_flags;
219    iiocb.iocb_psize = (unsigned int) disp->iplistsize;
220
221    /*
222     * Now the parameter list
223     */
224
225    switch (disp->plisttype) {
226	case PLBUF:
227	    iiocb.plist.iocb_buffer.buf_offset = (cfe_offset_t) xiocb->plist.xiocb_buffer.buf_offset;
228	    iiocb.plist.iocb_buffer.buf_ptr = xiocb->plist.xiocb_buffer.buf_ptr;
229	    iiocb.plist.iocb_buffer.buf_length = (unsigned int) xiocb->plist.xiocb_buffer.buf_length;
230	    iiocb.plist.iocb_buffer.buf_retlen = (unsigned int) xiocb->plist.xiocb_buffer.buf_retlen;
231	    iiocb.plist.iocb_buffer.buf_ioctlcmd = (unsigned int) xiocb->plist.xiocb_buffer.buf_ioctlcmd;
232	    break;
233	case PLCPU:
234	    iiocb.plist.iocb_cpuctl.cpu_number = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_number;
235	    iiocb.plist.iocb_cpuctl.cpu_command = (unsigned int) xiocb->plist.xiocb_cpuctl.cpu_command;
236	    iiocb.plist.iocb_cpuctl.start_addr = xiocb->plist.xiocb_cpuctl.start_addr;
237	    iiocb.plist.iocb_cpuctl.gp_val = xiocb->plist.xiocb_cpuctl.gp_val;
238	    iiocb.plist.iocb_cpuctl.sp_val = xiocb->plist.xiocb_cpuctl.sp_val;
239	    iiocb.plist.iocb_cpuctl.a1_val = xiocb->plist.xiocb_cpuctl.a1_val;
240	    break;
241	case PLMEM:
242	    iiocb.plist.iocb_meminfo.mi_idx  = (int) xiocb->plist.xiocb_meminfo.mi_idx;
243	    iiocb.plist.iocb_meminfo.mi_type = (int) xiocb->plist.xiocb_meminfo.mi_type;
244	    iiocb.plist.iocb_meminfo.mi_addr = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_addr;
245	    iiocb.plist.iocb_meminfo.mi_size = (unsigned long long) xiocb->plist.xiocb_meminfo.mi_size;
246	    break;
247	case PLENV:
248	    iiocb.plist.iocb_envbuf.enum_idx = (int) xiocb->plist.xiocb_envbuf.enum_idx;
249	    iiocb.plist.iocb_envbuf.name_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.name_ptr;
250	    iiocb.plist.iocb_envbuf.name_length = (int) xiocb->plist.xiocb_envbuf.name_length;
251	    iiocb.plist.iocb_envbuf.val_ptr = (unsigned char *) (uintptr_t) xiocb->plist.xiocb_envbuf.val_ptr;
252	    iiocb.plist.iocb_envbuf.val_length = (int) xiocb->plist.xiocb_envbuf.val_length;
253	    break;
254	case PLINP:
255	    iiocb.plist.iocb_inpstat.inp_status = (int) xiocb->plist.xiocb_inpstat.inp_status;
256	    break;
257	case PLTIM:
258	    iiocb.plist.iocb_time.ticks = (long long) xiocb->plist.xiocb_time.ticks;
259	    break;
260	case PLINF:
261	    break;
262	case PLEXIT:
263	    iiocb.plist.iocb_exitstat.status = (long long) xiocb->plist.xiocb_exitstat.status;
264	    break;
265	}
266
267    /*
268     * Do the internal function dispatch
269     */
270
271    res = (cfe_int_t) cfe_iocb_dispatch(&iiocb);
272
273    /*
274     * Now convert the parameter list members back
275     */
276
277    switch (disp->plisttype) {
278	case PLBUF:
279	    xiocb->plist.xiocb_buffer.buf_offset = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_offset;
280	    xiocb->plist.xiocb_buffer.buf_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_buffer.buf_ptr;
281	    xiocb->plist.xiocb_buffer.buf_length = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_length;
282	    xiocb->plist.xiocb_buffer.buf_retlen = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_retlen;
283	    xiocb->plist.xiocb_buffer.buf_ioctlcmd = (cfe_uint_t) iiocb.plist.iocb_buffer.buf_ioctlcmd;
284	    break;
285	case PLCPU:
286	    xiocb->plist.xiocb_cpuctl.cpu_number = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_number;
287	    xiocb->plist.xiocb_cpuctl.cpu_command = (cfe_uint_t) iiocb.plist.iocb_cpuctl.cpu_command;
288	    xiocb->plist.xiocb_cpuctl.start_addr = iiocb.plist.iocb_cpuctl.start_addr;
289	    break;
290	case PLMEM:
291	    xiocb->plist.xiocb_meminfo.mi_idx = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_idx;
292	    xiocb->plist.xiocb_meminfo.mi_type = (cfe_int_t) iiocb.plist.iocb_meminfo.mi_type;
293	    xiocb->plist.xiocb_meminfo.mi_addr = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_addr;
294	    xiocb->plist.xiocb_meminfo.mi_size = (cfe_int64_t) iiocb.plist.iocb_meminfo.mi_size;
295	    break;
296	case PLENV:
297	    xiocb->plist.xiocb_envbuf.enum_idx = (cfe_int_t) iiocb.plist.iocb_envbuf.enum_idx;
298	    xiocb->plist.xiocb_envbuf.name_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.name_ptr;
299	    xiocb->plist.xiocb_envbuf.name_length = (cfe_int_t) iiocb.plist.iocb_envbuf.name_length;
300	    xiocb->plist.xiocb_envbuf.val_ptr = (cfe_xptr_t) (uintptr_t) iiocb.plist.iocb_envbuf.val_ptr;
301	    xiocb->plist.xiocb_envbuf.val_length = (cfe_int_t) iiocb.plist.iocb_envbuf.val_length;
302	    break;
303	case PLINP:
304	    xiocb->plist.xiocb_inpstat.inp_status = (cfe_int_t) iiocb.plist.iocb_inpstat.inp_status;
305	    break;
306	case PLTIM:
307	    xiocb->plist.xiocb_time.ticks = (cfe_int_t) iiocb.plist.iocb_time.ticks;
308	    break;
309	case PLINF:
310	    xiocb->plist.xiocb_fwinfo.fwi_version = iiocb.plist.iocb_fwinfo.fwi_version;
311	    xiocb->plist.xiocb_fwinfo.fwi_totalmem = iiocb.plist.iocb_fwinfo.fwi_totalmem;
312	    xiocb->plist.xiocb_fwinfo.fwi_flags = iiocb.plist.iocb_fwinfo.fwi_flags;
313	    xiocb->plist.xiocb_fwinfo.fwi_boardid = iiocb.plist.iocb_fwinfo.fwi_boardid;
314	    xiocb->plist.xiocb_fwinfo.fwi_bootarea_va = iiocb.plist.iocb_fwinfo.fwi_bootarea_va;
315	    xiocb->plist.xiocb_fwinfo.fwi_bootarea_pa = iiocb.plist.iocb_fwinfo.fwi_bootarea_pa;
316	    xiocb->plist.xiocb_fwinfo.fwi_bootarea_size = iiocb.plist.iocb_fwinfo.fwi_bootarea_size;
317	    xiocb->plist.xiocb_fwinfo.fwi_reserved1 = iiocb.plist.iocb_fwinfo.fwi_reserved1;
318	    xiocb->plist.xiocb_fwinfo.fwi_reserved2 = iiocb.plist.iocb_fwinfo.fwi_reserved2;
319	    xiocb->plist.xiocb_fwinfo.fwi_reserved3 = iiocb.plist.iocb_fwinfo.fwi_reserved3;
320	    break;
321	case PLEXIT:
322	    xiocb->plist.xiocb_exitstat.status = (cfe_int_t) iiocb.plist.iocb_exitstat.status;
323	    break;
324	}
325
326    /*
327     * And the fixed header
328     */
329
330    xiocb->xiocb_status = (cfe_int_t) iiocb.iocb_status;
331    xiocb->xiocb_handle = (cfe_int_t) iiocb.iocb_handle;
332    xiocb->xiocb_flags = (cfe_uint_t) iiocb.iocb_flags;
333
334    return xiocb->xiocb_status;
335}
336