19a22473cSFarhan Ali /* 29a22473cSFarhan Ali * SCLP ASCII access driver 39a22473cSFarhan Ali * 49a22473cSFarhan Ali * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 59a22473cSFarhan Ali * 69a22473cSFarhan Ali * This work is licensed under the terms of the GNU GPL, version 2 or (at 79a22473cSFarhan Ali * your option) any later version. See the COPYING file in the top-level 89a22473cSFarhan Ali * directory. 99a22473cSFarhan Ali */ 109a22473cSFarhan Ali 1190806fecSThomas Huth #include "libc.h" 129a22473cSFarhan Ali #include "s390-ccw.h" 139a22473cSFarhan Ali #include "sclp.h" 149a22473cSFarhan Ali 15*3639f93fSThomas Huth long write(int fd, const void *str, size_t len); 16*3639f93fSThomas Huth 179a22473cSFarhan Ali static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); 189a22473cSFarhan Ali 19af3bb73aSThomas Huth const unsigned char ebc2asc[256] = 20af3bb73aSThomas Huth /* 0123456789abcdef0123456789abcdef */ 21af3bb73aSThomas Huth "................................" /* 1F */ 22af3bb73aSThomas Huth "................................" /* 3F */ 23af3bb73aSThomas Huth " ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */ 24af3bb73aSThomas Huth "-/.........,%_>?.........`:#@'=\""/* 7F */ 25af3bb73aSThomas Huth ".abcdefghi.......jklmnopqr......" /* 9F */ 26af3bb73aSThomas Huth "..stuvwxyz......................" /* BF */ 27af3bb73aSThomas Huth ".ABCDEFGHI.......JKLMNOPQR......" /* DF */ 28af3bb73aSThomas Huth "..STUVWXYZ......0123456789......";/* FF */ 29af3bb73aSThomas Huth 309a22473cSFarhan Ali /* Perform service call. Return 0 on success, non-zero otherwise. */ 319a22473cSFarhan Ali static int sclp_service_call(unsigned int command, void *sccb) 329a22473cSFarhan Ali { 339a22473cSFarhan Ali int cc; 349a22473cSFarhan Ali 359a22473cSFarhan Ali asm volatile( 369a22473cSFarhan Ali " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ 379a22473cSFarhan Ali " ipm %0\n" 389a22473cSFarhan Ali " srl %0,28" 399a22473cSFarhan Ali : "=&d" (cc) : "d" (command), "a" (__pa(sccb)) 409a22473cSFarhan Ali : "cc", "memory"); 419a22473cSFarhan Ali consume_sclp_int(); 429a22473cSFarhan Ali if (cc == 3) 439a22473cSFarhan Ali return -EIO; 449a22473cSFarhan Ali if (cc == 2) 459a22473cSFarhan Ali return -EBUSY; 469a22473cSFarhan Ali return 0; 479a22473cSFarhan Ali } 489a22473cSFarhan Ali 499a22473cSFarhan Ali static void sclp_set_write_mask(void) 509a22473cSFarhan Ali { 519a22473cSFarhan Ali WriteEventMask *sccb = (void *)_sccb; 529a22473cSFarhan Ali 539a22473cSFarhan Ali sccb->h.length = sizeof(WriteEventMask); 549a22473cSFarhan Ali sccb->mask_length = sizeof(unsigned int); 559a22473cSFarhan Ali sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 569a22473cSFarhan Ali sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 579a22473cSFarhan Ali sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII; 589a22473cSFarhan Ali sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII; 599a22473cSFarhan Ali 609a22473cSFarhan Ali sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb); 619a22473cSFarhan Ali } 629a22473cSFarhan Ali 639a22473cSFarhan Ali void sclp_setup(void) 649a22473cSFarhan Ali { 659a22473cSFarhan Ali sclp_set_write_mask(); 669a22473cSFarhan Ali } 679a22473cSFarhan Ali 689a22473cSFarhan Ali static int _strlen(const char *str) 699a22473cSFarhan Ali { 709a22473cSFarhan Ali int i; 719a22473cSFarhan Ali for (i = 0; *str; i++) 729a22473cSFarhan Ali str++; 739a22473cSFarhan Ali return i; 749a22473cSFarhan Ali } 759a22473cSFarhan Ali 76*3639f93fSThomas Huth long write(int fd, const void *str, size_t len) 779a22473cSFarhan Ali { 789a22473cSFarhan Ali WriteEventData *sccb = (void *)_sccb; 799a22473cSFarhan Ali 80*3639f93fSThomas Huth if (fd != 1 && fd != 2) { 81*3639f93fSThomas Huth return -EIO; 82*3639f93fSThomas Huth } 83*3639f93fSThomas Huth 849a22473cSFarhan Ali sccb->h.length = sizeof(WriteEventData) + len; 859a22473cSFarhan Ali sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 869a22473cSFarhan Ali sccb->ebh.length = sizeof(EventBufferHeader) + len; 879a22473cSFarhan Ali sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; 889a22473cSFarhan Ali sccb->ebh.flags = 0; 8990806fecSThomas Huth memcpy(sccb->data, str, len); 909a22473cSFarhan Ali 919a22473cSFarhan Ali sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 92*3639f93fSThomas Huth 93*3639f93fSThomas Huth return len; 94*3639f93fSThomas Huth } 95*3639f93fSThomas Huth 96*3639f93fSThomas Huth void sclp_print(const char *str) 97*3639f93fSThomas Huth { 98*3639f93fSThomas Huth write(1, str, _strlen(str)); 999a22473cSFarhan Ali } 1009a22473cSFarhan Ali 1019a22473cSFarhan Ali void sclp_get_loadparm_ascii(char *loadparm) 1029a22473cSFarhan Ali { 1039a22473cSFarhan Ali 1049a22473cSFarhan Ali ReadInfo *sccb = (void *)_sccb; 1059a22473cSFarhan Ali 1069a22473cSFarhan Ali memset((char *)_sccb, 0, sizeof(ReadInfo)); 1079a22473cSFarhan Ali sccb->h.length = sizeof(ReadInfo); 1089a22473cSFarhan Ali if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) { 1099a22473cSFarhan Ali ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8); 1109a22473cSFarhan Ali } 1119a22473cSFarhan Ali } 112