OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [arch/] [s390/] [kernel/] [cpcmd.c] - Blame information for rev 63

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 63 marcus.erl
/*
2
 *  arch/s390/kernel/cpcmd.c
3
 *
4
 *  S390 version
5
 *    Copyright IBM Corp. 1999,2007
6
 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
7
 *               Christian Borntraeger (cborntra@de.ibm.com),
8
 */
9
 
10
#include <linux/kernel.h>
11
#include <linux/module.h>
12
#include <linux/slab.h>
13
#include <linux/spinlock.h>
14
#include <linux/stddef.h>
15
#include <linux/string.h>
16
#include <asm/ebcdic.h>
17
#include <asm/cpcmd.h>
18
#include <asm/system.h>
19
#include <asm/io.h>
20
 
21
static DEFINE_SPINLOCK(cpcmd_lock);
22
static char cpcmd_buf[241];
23
 
24
static int diag8_noresponse(int cmdlen)
25
{
26
        register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
27
        register unsigned long reg3 asm ("3") = cmdlen;
28
 
29
        asm volatile(
30
#ifndef CONFIG_64BIT
31
                "       diag    %1,%0,0x8\n"
32
#else /* CONFIG_64BIT */
33
                "       sam31\n"
34
                "       diag    %1,%0,0x8\n"
35
                "       sam64\n"
36
#endif /* CONFIG_64BIT */
37
                : "+d" (reg3) : "d" (reg2) : "cc");
38
        return reg3;
39
}
40
 
41
static int diag8_response(int cmdlen, char *response, int *rlen)
42
{
43
        register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
44
        register unsigned long reg3 asm ("3") = (addr_t) response;
45
        register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
46
        register unsigned long reg5 asm ("5") = *rlen;
47
 
48
        asm volatile(
49
#ifndef CONFIG_64BIT
50
                "       diag    %2,%0,0x8\n"
51
                "       brc     8,1f\n"
52
                "       ar      %1,%4\n"
53
#else /* CONFIG_64BIT */
54
                "       sam31\n"
55
                "       diag    %2,%0,0x8\n"
56
                "       sam64\n"
57
                "       brc     8,1f\n"
58
                "       agr     %1,%4\n"
59
#endif /* CONFIG_64BIT */
60
                "1:\n"
61
                : "+d" (reg4), "+d" (reg5)
62
                : "d" (reg2), "d" (reg3), "d" (*rlen) : "cc");
63
        *rlen = reg5;
64
        return reg4;
65
}
66
 
67
/*
68
 * __cpcmd has some restrictions over cpcmd
69
 *  - the response buffer must reside below 2GB (if any)
70
 *  - __cpcmd is unlocked and therefore not SMP-safe
71
 */
72
int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
73
{
74
        int cmdlen;
75
        int rc;
76
        int response_len;
77
 
78
        cmdlen = strlen(cmd);
79
        BUG_ON(cmdlen > 240);
80
        memcpy(cpcmd_buf, cmd, cmdlen);
81
        ASCEBC(cpcmd_buf, cmdlen);
82
 
83
        if (response) {
84
                memset(response, 0, rlen);
85
                response_len = rlen;
86
                rc = diag8_response(cmdlen, response, &rlen);
87
                EBCASC(response, response_len);
88
        } else {
89
                rc = diag8_noresponse(cmdlen);
90
        }
91
        if (response_code)
92
                *response_code = rc;
93
        return rlen;
94
}
95
EXPORT_SYMBOL(__cpcmd);
96
 
97
int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
98
{
99
        char *lowbuf;
100
        int len;
101
        unsigned long flags;
102
 
103
        if ((virt_to_phys(response) != (unsigned long) response) ||
104
                        (((unsigned long)response + rlen) >> 31)) {
105
                lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
106
                if (!lowbuf) {
107
                        printk(KERN_WARNING
108
                                "cpcmd: could not allocate response buffer\n");
109
                        return -ENOMEM;
110
                }
111
                spin_lock_irqsave(&cpcmd_lock, flags);
112
                len = __cpcmd(cmd, lowbuf, rlen, response_code);
113
                spin_unlock_irqrestore(&cpcmd_lock, flags);
114
                memcpy(response, lowbuf, rlen);
115
                kfree(lowbuf);
116
        } else {
117
                spin_lock_irqsave(&cpcmd_lock, flags);
118
                len = __cpcmd(cmd, response, rlen, response_code);
119
                spin_unlock_irqrestore(&cpcmd_lock, flags);
120
        }
121
        return len;
122
}
123
EXPORT_SYMBOL(cpcmd);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.