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 "libc.h" 12 #include "s390-ccw.h" 13 #include "sclp.h" 14 15 long write(int fd, const void *str, size_t len); 16 17 static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); 18 19 const unsigned char ebc2asc[256] = 20 /* 0123456789abcdef0123456789abcdef */ 21 "................................" /* 1F */ 22 "................................" /* 3F */ 23 " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */ 24 "-/.........,%_>?.........`:#@'=\""/* 7F */ 25 ".abcdefghi.......jklmnopqr......" /* 9F */ 26 "..stuvwxyz......................" /* BF */ 27 ".ABCDEFGHI.......JKLMNOPQR......" /* DF */ 28 "..STUVWXYZ......0123456789......";/* FF */ 29 30 /* Perform service call. Return 0 on success, non-zero otherwise. */ 31 static int sclp_service_call(unsigned int command, void *sccb) 32 { 33 int cc; 34 35 asm volatile( 36 " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ 37 " ipm %0\n" 38 " srl %0,28" 39 : "=&d" (cc) : "d" (command), "a" (__pa(sccb)) 40 : "cc", "memory"); 41 consume_sclp_int(); 42 if (cc == 3) 43 return -EIO; 44 if (cc == 2) 45 return -EBUSY; 46 return 0; 47 } 48 49 static void sclp_set_write_mask(void) 50 { 51 WriteEventMask *sccb = (void *)_sccb; 52 53 sccb->h.length = sizeof(WriteEventMask); 54 sccb->mask_length = sizeof(unsigned int); 55 sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 56 sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 57 sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII; 58 sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII; 59 60 sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb); 61 } 62 63 void sclp_setup(void) 64 { 65 sclp_set_write_mask(); 66 } 67 68 static int _strlen(const char *str) 69 { 70 int i; 71 for (i = 0; *str; i++) 72 str++; 73 return i; 74 } 75 76 long write(int fd, const void *str, size_t len) 77 { 78 WriteEventData *sccb = (void *)_sccb; 79 80 if (fd != 1 && fd != 2) { 81 return -EIO; 82 } 83 84 sccb->h.length = sizeof(WriteEventData) + len; 85 sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 86 sccb->ebh.length = sizeof(EventBufferHeader) + len; 87 sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; 88 sccb->ebh.flags = 0; 89 memcpy(sccb->data, str, len); 90 91 sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 92 93 return len; 94 } 95 96 void sclp_print(const char *str) 97 { 98 write(1, str, _strlen(str)); 99 } 100 101 void sclp_get_loadparm_ascii(char *loadparm) 102 { 103 104 ReadInfo *sccb = (void *)_sccb; 105 106 memset((char *)_sccb, 0, sizeof(ReadInfo)); 107 sccb->h.length = sizeof(ReadInfo); 108 if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) { 109 ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8); 110 } 111 } 112