real1.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *
  3.  * This file is subject to the terms and conditions of the GNU General Public
  4.  * License.  See the file "COPYING" in the main directory of this archive
  5.  * for more details.
  6.  *
  7.  * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
  8.  *
  9.  * most of these calls might reasonably be moved to ../kernel -PB
  10.  *
  11.  * The basic principle is to construct a stack frame in C then call
  12.  * some assembly which adopts that stack, does some rfi magic, may
  13.  * switch wide/narrow mode, and calls the routine described by the
  14.  * 'fn' parameter WHICH IS NOT A FUNCTION POINTER!!!!!!!!!!!!!!!!
  15.  */
  16. #include <linux/spinlock.h>
  17. #include <asm/system.h>
  18. #include <stdarg.h>
  19. #include <asm/pgtable.h> /* for __pa() */
  20. #include <asm/pdc.h>
  21. static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
  22. /***************** 32-bit real-mode calls ***********/
  23. /* The struct below is used
  24.  * to overlay real_stack (real2.S), preparing a 32-bit call frame.
  25.  * real32_call_asm() then uses this stack in narrow real mode
  26.  */
  27. struct narrow_stack {
  28.     /* use int, not long which is 64 bits */
  29.     unsigned int arg13;
  30.     unsigned int arg12;
  31.     unsigned int arg11;
  32.     unsigned int arg10;
  33.     unsigned int arg9;
  34.     unsigned int arg8;
  35.     unsigned int arg7;
  36.     unsigned int arg6;
  37.     unsigned int arg5;
  38.     unsigned int arg4;
  39.     unsigned int arg3;
  40.     unsigned int arg2;
  41.     unsigned int arg1;
  42.     unsigned int arg0;
  43.     unsigned int frame_marker[8];
  44.     unsigned int sp;
  45.     /* in reality, there's nearly 8k of stack after this */
  46. };
  47. long
  48. real32_call(unsigned long fn, ...)
  49. {
  50.     unsigned long r;
  51.     va_list args;
  52.     unsigned long flags;
  53.     extern struct narrow_stack real_stack;
  54.     extern unsigned long real32_call_asm(unsigned int *,
  55. unsigned int *, unsigned int);
  56.     
  57.     va_start(args, fn);
  58.     real_stack.arg0 = va_arg(args, unsigned int);
  59.     real_stack.arg1 = va_arg(args, unsigned int);
  60.     real_stack.arg2 = va_arg(args, unsigned int);
  61.     real_stack.arg3 = va_arg(args, unsigned int);
  62.     real_stack.arg4 = va_arg(args, unsigned int);
  63.     real_stack.arg5 = va_arg(args, unsigned int);
  64.     real_stack.arg6 = va_arg(args, unsigned int);
  65.     real_stack.arg7 = va_arg(args, unsigned int);
  66.     real_stack.arg8 = va_arg(args, unsigned int);
  67.     real_stack.arg9 = va_arg(args, unsigned int);
  68.     real_stack.arg10 = va_arg(args, unsigned int);
  69.     real_stack.arg11 = va_arg(args, unsigned int);
  70.     real_stack.arg12 = va_arg(args, unsigned int);
  71.     real_stack.arg13 = va_arg(args, unsigned int);
  72.     va_end(args);
  73.     if (fn == 0) {
  74.     /* mem_pdc call */
  75.     fn = PAGE0->mem_pdc;
  76.     }
  77.     spin_lock_irqsave(&pdc_lock, flags);
  78.     r = real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
  79.     spin_unlock_irqrestore(&pdc_lock, flags);
  80.     return r;
  81. }
  82. #ifdef __LP64__
  83. /***************** 64-bit real-mode calls ***********/
  84. struct wide_stack {
  85.     unsigned long arg0;
  86.     unsigned long arg1;
  87.     unsigned long arg2;
  88.     unsigned long arg3;
  89.     unsigned long arg4;
  90.     unsigned long arg5;
  91.     unsigned long arg6;
  92.     unsigned long arg7;
  93.     unsigned long arg8;
  94.     unsigned long arg9;
  95.     unsigned long arg10;
  96.     unsigned long arg11;
  97.     unsigned long arg12;
  98.     unsigned long arg13;
  99.     unsigned long frame_marker[2]; /* rp, previous sp */
  100.     unsigned long sp;
  101.     /* in reality, there's nearly 8k of stack after this */
  102. };
  103. long
  104. real64_call(unsigned long fn, ...)
  105. {
  106.     unsigned long r;
  107.     va_list args;
  108.     unsigned long flags;
  109.     extern struct wide_stack real_stack;
  110.     extern unsigned long real64_call_asm(unsigned long *,
  111. unsigned long *, unsigned long);
  112.     
  113.     va_start(args, fn);
  114.     real_stack.arg0 = va_arg(args, unsigned long);
  115.     real_stack.arg1 = va_arg(args, unsigned long);
  116.     real_stack.arg2 = va_arg(args, unsigned long);
  117.     real_stack.arg3 = va_arg(args, unsigned long);
  118.     real_stack.arg4 = va_arg(args, unsigned long);
  119.     real_stack.arg5 = va_arg(args, unsigned long);
  120.     real_stack.arg6 = va_arg(args, unsigned long);
  121.     real_stack.arg7 = va_arg(args, unsigned long);
  122.     real_stack.arg8 = va_arg(args, unsigned long);
  123.     real_stack.arg9 = va_arg(args, unsigned long);
  124.     real_stack.arg10 = va_arg(args, unsigned long);
  125.     real_stack.arg11 = va_arg(args, unsigned long);
  126.     real_stack.arg12 = va_arg(args, unsigned long);
  127.     real_stack.arg13 = va_arg(args, unsigned long);
  128.     va_end(args);
  129.     if (fn == 0) {
  130.     /* mem_pdc call */
  131.     fn = PAGE0->mem_pdc_hi;
  132.     fn <<= 32;
  133.     fn |= PAGE0->mem_pdc;
  134.     }
  135.     spin_lock_irqsave(&pdc_lock, flags);
  136.     r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn);
  137.     spin_unlock_irqrestore(&pdc_lock, flags);
  138.     return r;
  139. }
  140. #endif