import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / s390x / kernel / cpcmd.c
1 /*
2  *  arch/s390/kernel/cpcmd.c
3  *
4  *  S390 version
5  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
6  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7  */
8
9 #include <linux/string.h>
10 #include <linux/spinlock.h>
11 #include <asm/cpcmd.h>
12 #include <asm/ebcdic.h>
13 #include <asm/system.h>
14
15 static spinlock_t cpcmd_lock = SPIN_LOCK_UNLOCKED;
16 static char cpcmd_buf[128];
17
18 void cpcmd(char *cmd, char *response, int rlen)
19 {
20         const int mask = 0x40000000L;
21         unsigned long flags;
22         int cmdlen;
23
24         spin_lock_irqsave(&cpcmd_lock, flags);
25         cmdlen = strlen(cmd);
26         strcpy(cpcmd_buf, cmd);
27         ASCEBC(cpcmd_buf, cmdlen);
28
29         if (response != NULL && rlen > 0) {
30                 asm volatile ("   lrag  2,0(%0)\n"
31                               "   lgr   4,%1\n"
32                               "   o     4,%4\n"
33                               "   lrag  3,0(%2)\n"
34                               "   lgr   5,%3\n"
35                               "   sam31\n"
36                               "   .long 0x83240008 # Diagnose 83\n"
37                               "   sam64"
38                               : /* no output */
39                               : "a" (cpcmd_buf), "d" (cmdlen),
40                                 "a" (response), "d" (rlen), "m" (mask)
41                               : "2", "3", "4", "5" );
42                 EBCASC(response, rlen);
43         } else {
44                 asm volatile ("   lrag  2,0(%0)\n"
45                               "   lgr   3,%1\n"
46                               "   sam31\n"
47                               "   .long 0x83230008 # Diagnose 83\n"
48                               "   sam64"
49                               : /* no output */
50                               : "a" (cpcmd_buf), "d" (cmdlen)
51                               : "2", "3"  );
52         }
53         spin_unlock_irqrestore(&cpcmd_lock, flags);
54 }
55