1 /* 2 * SCLP ASCII access driver 3 * 4 * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 5 * 6 * This work is licensed under the terms of the GNU GPL, version 2 or (at 7 * your option) any later version. See the COPYING file in the top-level 8 * directory. 9 */ 10 11 #include "s390-ccw.h" 12 #include "sclp.h" 13 14 static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); 15 16 /* Perform service call. Return 0 on success, non-zero otherwise. */ 17 static int sclp_service_call(unsigned int command, void *sccb) 18 { 19 int cc; 20 21 asm volatile( 22 " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ 23 " ipm %0\n" 24 " srl %0,28" 25 : "=&d" (cc) : "d" (command), "a" (__pa(sccb)) 26 : "cc", "memory"); 27 consume_sclp_int(); 28 if (cc == 3) 29 return -EIO; 30 if (cc == 2) 31 return -EBUSY; 32 return 0; 33 } 34 35 static void sclp_set_write_mask(void) 36 { 37 WriteEventMask *sccb = (void *)_sccb; 38 39 sccb->h.length = sizeof(WriteEventMask); 40 sccb->mask_length = sizeof(unsigned int); 41 sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 42 sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 43 sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII; 44 sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII; 45 46 sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb); 47 } 48 49 void sclp_setup(void) 50 { 51 sclp_set_write_mask(); 52 } 53 54 static int _strlen(const char *str) 55 { 56 int i; 57 for (i = 0; *str; i++) 58 str++; 59 return i; 60 } 61 62 static void _memcpy(char *dest, const char *src, int len) 63 { 64 int i; 65 for (i = 0; i < len; i++) 66 dest[i] = src[i]; 67 } 68 69 void sclp_print(const char *str) 70 { 71 int len = _strlen(str); 72 WriteEventData *sccb = (void *)_sccb; 73 74 sccb->h.length = sizeof(WriteEventData) + len; 75 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 76 sccb->ebh.length = sizeof(EventBufferHeader) + len; 77 sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; 78 sccb->ebh.flags = 0; 79 _memcpy(sccb->data, str, len); 80 81 sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 82 } 83 84 void sclp_get_loadparm_ascii(char *loadparm) 85 { 86 87 ReadInfo *sccb = (void *)_sccb; 88 89 memset((char *)_sccb, 0, sizeof(ReadInfo)); 90 sccb->h.length = sizeof(ReadInfo); 91 if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) { 92 ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8); 93 } 94 } 95