linux/arch/sparc64/prom/p1275.c
<<
>>
Prefs
   1/* $Id: p1275.c,v 1.22 2001/10/18 09:40:00 davem Exp $
   2 * p1275.c: Sun IEEE 1275 PROM low level interface routines
   3 *
   4 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   5 */
   6
   7#include <linux/kernel.h>
   8#include <linux/init.h>
   9#include <linux/sched.h>
  10#include <linux/smp.h>
  11#include <linux/string.h>
  12#include <linux/spinlock.h>
  13
  14#include <asm/openprom.h>
  15#include <asm/oplib.h>
  16#include <asm/system.h>
  17#include <asm/spitfire.h>
  18#include <asm/pstate.h>
  19#include <asm/ldc.h>
  20
  21struct {
  22        long prom_callback;                     /* 0x00 */
  23        void (*prom_cif_handler)(long *);       /* 0x08 */
  24        unsigned long prom_cif_stack;           /* 0x10 */
  25        unsigned long prom_args [23];           /* 0x18 */
  26        char prom_buffer [3000];
  27} p1275buf;
  28
  29extern void prom_world(int);
  30
  31extern void prom_cif_interface(void);
  32extern void prom_cif_callback(void);
  33
  34/*
  35 * This provides SMP safety on the p1275buf. prom_callback() drops this lock
  36 * to allow recursuve acquisition.
  37 */
  38DEFINE_SPINLOCK(prom_entry_lock);
  39
  40long p1275_cmd(const char *service, long fmt, ...)
  41{
  42        char *p, *q;
  43        unsigned long flags;
  44        int nargs, nrets, i;
  45        va_list list;
  46        long attrs, x;
  47        
  48        p = p1275buf.prom_buffer;
  49
  50        spin_lock_irqsave(&prom_entry_lock, flags);
  51
  52        p1275buf.prom_args[0] = (unsigned long)p;               /* service */
  53        strcpy (p, service);
  54        p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
  55        p1275buf.prom_args[1] = nargs = (fmt & 0x0f);           /* nargs */
  56        p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4);    /* nrets */
  57        attrs = fmt >> 8;
  58        va_start(list, fmt);
  59        for (i = 0; i < nargs; i++, attrs >>= 3) {
  60                switch (attrs & 0x7) {
  61                case P1275_ARG_NUMBER:
  62                        p1275buf.prom_args[i + 3] =
  63                                                (unsigned)va_arg(list, long);
  64                        break;
  65                case P1275_ARG_IN_64B:
  66                        p1275buf.prom_args[i + 3] =
  67                                va_arg(list, unsigned long);
  68                        break;
  69                case P1275_ARG_IN_STRING:
  70                        strcpy (p, va_arg(list, char *));
  71                        p1275buf.prom_args[i + 3] = (unsigned long)p;
  72                        p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
  73                        break;
  74                case P1275_ARG_OUT_BUF:
  75                        (void) va_arg(list, char *);
  76                        p1275buf.prom_args[i + 3] = (unsigned long)p;
  77                        x = va_arg(list, long);
  78                        i++; attrs >>= 3;
  79                        p = (char *)(((long)(p + (int)x + 7)) & ~7);
  80                        p1275buf.prom_args[i + 3] = x;
  81                        break;
  82                case P1275_ARG_IN_BUF:
  83                        q = va_arg(list, char *);
  84                        p1275buf.prom_args[i + 3] = (unsigned long)p;
  85                        x = va_arg(list, long);
  86                        i++; attrs >>= 3;
  87                        memcpy (p, q, (int)x);
  88                        p = (char *)(((long)(p + (int)x + 7)) & ~7);
  89                        p1275buf.prom_args[i + 3] = x;
  90                        break;
  91                case P1275_ARG_OUT_32B:
  92                        (void) va_arg(list, char *);
  93                        p1275buf.prom_args[i + 3] = (unsigned long)p;
  94                        p += 32;
  95                        break;
  96                case P1275_ARG_IN_FUNCTION:
  97                        p1275buf.prom_args[i + 3] =
  98                                        (unsigned long)prom_cif_callback;
  99                        p1275buf.prom_callback = va_arg(list, long);
 100                        break;
 101                }
 102        }
 103        va_end(list);
 104
 105        prom_world(1);
 106        prom_cif_interface();
 107        prom_world(0);
 108
 109        attrs = fmt >> 8;
 110        va_start(list, fmt);
 111        for (i = 0; i < nargs; i++, attrs >>= 3) {
 112                switch (attrs & 0x7) {
 113                case P1275_ARG_NUMBER:
 114                        (void) va_arg(list, long);
 115                        break;
 116                case P1275_ARG_IN_STRING:
 117                        (void) va_arg(list, char *);
 118                        break;
 119                case P1275_ARG_IN_FUNCTION:
 120                        (void) va_arg(list, long);
 121                        break;
 122                case P1275_ARG_IN_BUF:
 123                        (void) va_arg(list, char *);
 124                        (void) va_arg(list, long);
 125                        i++; attrs >>= 3;
 126                        break;
 127                case P1275_ARG_OUT_BUF:
 128                        p = va_arg(list, char *);
 129                        x = va_arg(list, long);
 130                        memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x);
 131                        i++; attrs >>= 3;
 132                        break;
 133                case P1275_ARG_OUT_32B:
 134                        p = va_arg(list, char *);
 135                        memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32);
 136                        break;
 137                }
 138        }
 139        va_end(list);
 140        x = p1275buf.prom_args [nargs + 3];
 141
 142        spin_unlock_irqrestore(&prom_entry_lock, flags);
 143
 144        return x;
 145}
 146
 147void prom_cif_init(void *cif_handler, void *cif_stack)
 148{
 149        p1275buf.prom_cif_handler = (void (*)(long *))cif_handler;
 150        p1275buf.prom_cif_stack = (unsigned long)cif_stack;
 151}
 152