10369b2ebSAlexander Graf /* 20369b2ebSAlexander Graf * SCLP ASCII access driver 30369b2ebSAlexander Graf * 40369b2ebSAlexander Graf * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 50369b2ebSAlexander Graf * 60369b2ebSAlexander Graf * This work is licensed under the terms of the GNU GPL, version 2 or (at 70369b2ebSAlexander Graf * your option) any later version. See the COPYING file in the top-level 80369b2ebSAlexander Graf * directory. 90369b2ebSAlexander Graf */ 100369b2ebSAlexander Graf 110369b2ebSAlexander Graf #include "s390-ccw.h" 120369b2ebSAlexander Graf #include "sclp.h" 130369b2ebSAlexander Graf 140369b2ebSAlexander Graf static char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); 150369b2ebSAlexander Graf 160369b2ebSAlexander Graf /* Perform service call. Return 0 on success, non-zero otherwise. */ 170369b2ebSAlexander Graf static int sclp_service_call(unsigned int command, void *sccb) 180369b2ebSAlexander Graf { 190369b2ebSAlexander Graf int cc; 200369b2ebSAlexander Graf 210369b2ebSAlexander Graf asm volatile( 220369b2ebSAlexander Graf " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ 230369b2ebSAlexander Graf " ipm %0\n" 240369b2ebSAlexander Graf " srl %0,28" 250369b2ebSAlexander Graf : "=&d" (cc) : "d" (command), "a" (__pa(sccb)) 260369b2ebSAlexander Graf : "cc", "memory"); 27bdc7fe36SChristian Borntraeger consume_sclp_int(); 280369b2ebSAlexander Graf if (cc == 3) 290369b2ebSAlexander Graf return -EIO; 300369b2ebSAlexander Graf if (cc == 2) 310369b2ebSAlexander Graf return -EBUSY; 320369b2ebSAlexander Graf return 0; 330369b2ebSAlexander Graf } 340369b2ebSAlexander Graf 350369b2ebSAlexander Graf static void sclp_set_write_mask(void) 360369b2ebSAlexander Graf { 370369b2ebSAlexander Graf WriteEventMask *sccb = (void *)_sccb; 380369b2ebSAlexander Graf 390369b2ebSAlexander Graf sccb->h.length = sizeof(WriteEventMask); 400369b2ebSAlexander Graf sccb->mask_length = sizeof(unsigned int); 410369b2ebSAlexander Graf sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 420369b2ebSAlexander Graf sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 430369b2ebSAlexander Graf sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII; 440369b2ebSAlexander Graf sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII; 450369b2ebSAlexander Graf 460369b2ebSAlexander Graf sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb); 470369b2ebSAlexander Graf } 480369b2ebSAlexander Graf 490369b2ebSAlexander Graf void sclp_setup(void) 500369b2ebSAlexander Graf { 510369b2ebSAlexander Graf sclp_set_write_mask(); 520369b2ebSAlexander Graf } 530369b2ebSAlexander Graf 540369b2ebSAlexander Graf static int _strlen(const char *str) 550369b2ebSAlexander Graf { 560369b2ebSAlexander Graf int i; 570369b2ebSAlexander Graf for (i = 0; *str; i++) 580369b2ebSAlexander Graf str++; 590369b2ebSAlexander Graf return i; 600369b2ebSAlexander Graf } 610369b2ebSAlexander Graf 620369b2ebSAlexander Graf static void _memcpy(char *dest, const char *src, int len) 630369b2ebSAlexander Graf { 640369b2ebSAlexander Graf int i; 650369b2ebSAlexander Graf for (i = 0; i < len; i++) 660369b2ebSAlexander Graf dest[i] = src[i]; 670369b2ebSAlexander Graf } 680369b2ebSAlexander Graf 690369b2ebSAlexander Graf void sclp_print(const char *str) 700369b2ebSAlexander Graf { 710369b2ebSAlexander Graf int len = _strlen(str); 720369b2ebSAlexander Graf WriteEventData *sccb = (void *)_sccb; 730369b2ebSAlexander Graf 740369b2ebSAlexander Graf sccb->h.length = sizeof(WriteEventData) + len; 750369b2ebSAlexander Graf sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 760369b2ebSAlexander Graf sccb->ebh.length = sizeof(EventBufferHeader) + len; 770369b2ebSAlexander Graf sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; 780369b2ebSAlexander Graf sccb->ebh.flags = 0; 790369b2ebSAlexander Graf _memcpy(sccb->data, str, len); 800369b2ebSAlexander Graf 810369b2ebSAlexander Graf sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 820369b2ebSAlexander Graf } 83*9a22473cSFarhan Ali 84*9a22473cSFarhan Ali void sclp_get_loadparm_ascii(char *loadparm) 85*9a22473cSFarhan Ali { 86*9a22473cSFarhan Ali 87*9a22473cSFarhan Ali ReadInfo *sccb = (void *)_sccb; 88*9a22473cSFarhan Ali 89*9a22473cSFarhan Ali memset((char *)_sccb, 0, sizeof(ReadInfo)); 90*9a22473cSFarhan Ali sccb->h.length = sizeof(ReadInfo); 91*9a22473cSFarhan Ali if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) { 92*9a22473cSFarhan Ali ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8); 93*9a22473cSFarhan Ali } 94*9a22473cSFarhan Ali } 95