From 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 15:20:36 -0700 Subject: Linux-2.6.12-rc2 Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip! --- arch/s390/kernel/cpcmd.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 arch/s390/kernel/cpcmd.c (limited to 'arch/s390/kernel/cpcmd.c') diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c new file mode 100644 index 00000000000..44df8dc07c5 --- /dev/null +++ b/arch/s390/kernel/cpcmd.c @@ -0,0 +1,111 @@ +/* + * arch/s390/kernel/cpcmd.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + * Christian Borntraeger (cborntra@de.ibm.com), + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static DEFINE_SPINLOCK(cpcmd_lock); +static char cpcmd_buf[240]; + +/* + * the caller of __cpcmd has to ensure that the response buffer is below 2 GB + */ +void __cpcmd(char *cmd, char *response, int rlen) +{ + const int mask = 0x40000000L; + unsigned long flags; + int cmdlen; + + spin_lock_irqsave(&cpcmd_lock, flags); + cmdlen = strlen(cmd); + BUG_ON(cmdlen > 240); + strcpy(cpcmd_buf, cmd); + ASCEBC(cpcmd_buf, cmdlen); + + if (response != NULL && rlen > 0) { + memset(response, 0, rlen); +#ifndef CONFIG_ARCH_S390X + asm volatile ("LRA 2,0(%0)\n\t" + "LR 4,%1\n\t" + "O 4,%4\n\t" + "LRA 3,0(%2)\n\t" + "LR 5,%3\n\t" + ".long 0x83240008 # Diagnose X'08'\n\t" + : /* no output */ + : "a" (cpcmd_buf), "d" (cmdlen), + "a" (response), "d" (rlen), "m" (mask) + : "cc", "2", "3", "4", "5" ); +#else /* CONFIG_ARCH_S390X */ + asm volatile (" lrag 2,0(%0)\n" + " lgr 4,%1\n" + " o 4,%4\n" + " lrag 3,0(%2)\n" + " lgr 5,%3\n" + " sam31\n" + " .long 0x83240008 # Diagnose X'08'\n" + " sam64" + : /* no output */ + : "a" (cpcmd_buf), "d" (cmdlen), + "a" (response), "d" (rlen), "m" (mask) + : "cc", "2", "3", "4", "5" ); +#endif /* CONFIG_ARCH_S390X */ + EBCASC(response, rlen); + } else { +#ifndef CONFIG_ARCH_S390X + asm volatile ("LRA 2,0(%0)\n\t" + "LR 3,%1\n\t" + ".long 0x83230008 # Diagnose X'08'\n\t" + : /* no output */ + : "a" (cpcmd_buf), "d" (cmdlen) + : "2", "3" ); +#else /* CONFIG_ARCH_S390X */ + asm volatile (" lrag 2,0(%0)\n" + " lgr 3,%1\n" + " sam31\n" + " .long 0x83230008 # Diagnose X'08'\n" + " sam64" + : /* no output */ + : "a" (cpcmd_buf), "d" (cmdlen) + : "2", "3" ); +#endif /* CONFIG_ARCH_S390X */ + } + spin_unlock_irqrestore(&cpcmd_lock, flags); +} + +EXPORT_SYMBOL(__cpcmd); + +#ifdef CONFIG_ARCH_S390X +void cpcmd(char *cmd, char *response, int rlen) +{ + char *lowbuf; + if ((rlen == 0) || (response == NULL) + || !((unsigned long)response >> 31)) + __cpcmd(cmd, response, rlen); + else { + lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA); + if (!lowbuf) { + printk(KERN_WARNING + "cpcmd: could not allocate response buffer\n"); + return; + } + __cpcmd(cmd, lowbuf, rlen); + memcpy(response, lowbuf, rlen); + kfree(lowbuf); + } +} + +EXPORT_SYMBOL(cpcmd); +#endif /* CONFIG_ARCH_S390X */ -- cgit v1.2.3