1*7ed7df23SJanosch Frank /* 2*7ed7df23SJanosch Frank * SCLP ASCII access driver 3*7ed7df23SJanosch Frank * 4*7ed7df23SJanosch Frank * Copyright (c) 2013 Alexander Graf <agraf@suse.de> 5*7ed7df23SJanosch Frank * 6*7ed7df23SJanosch Frank * This work is licensed under the terms of the GNU GPL, version 2 or (at 7*7ed7df23SJanosch Frank * your option) any later version. See the COPYING file in the top-level 8*7ed7df23SJanosch Frank * directory. 9*7ed7df23SJanosch Frank */ 10*7ed7df23SJanosch Frank 11*7ed7df23SJanosch Frank #include <libcflat.h> 12*7ed7df23SJanosch Frank #include <string.h> 13*7ed7df23SJanosch Frank #include <asm/page.h> 14*7ed7df23SJanosch Frank #include "sclp.h" 15*7ed7df23SJanosch Frank 16*7ed7df23SJanosch Frank char _sccb[PAGE_SIZE] __attribute__((__aligned__(4096))); 17*7ed7df23SJanosch Frank 18*7ed7df23SJanosch Frank /* Perform service call. Return 0 on success, non-zero otherwise. */ 19*7ed7df23SJanosch Frank int sclp_service_call(unsigned int command, void *sccb) 20*7ed7df23SJanosch Frank { 21*7ed7df23SJanosch Frank int cc; 22*7ed7df23SJanosch Frank 23*7ed7df23SJanosch Frank asm volatile( 24*7ed7df23SJanosch Frank " .insn rre,0xb2200000,%1,%2\n" /* servc %1,%2 */ 25*7ed7df23SJanosch Frank " ipm %0\n" 26*7ed7df23SJanosch Frank " srl %0,28" 27*7ed7df23SJanosch Frank : "=&d" (cc) : "d" (command), "a" (__pa(sccb)) 28*7ed7df23SJanosch Frank : "cc", "memory"); 29*7ed7df23SJanosch Frank if (cc == 3) 30*7ed7df23SJanosch Frank return -1; 31*7ed7df23SJanosch Frank if (cc == 2) 32*7ed7df23SJanosch Frank return -1; 33*7ed7df23SJanosch Frank return 0; 34*7ed7df23SJanosch Frank } 35*7ed7df23SJanosch Frank 36*7ed7df23SJanosch Frank static void sclp_set_write_mask(void) 37*7ed7df23SJanosch Frank { 38*7ed7df23SJanosch Frank WriteEventMask *sccb = (void *)_sccb; 39*7ed7df23SJanosch Frank 40*7ed7df23SJanosch Frank sccb->h.length = sizeof(WriteEventMask); 41*7ed7df23SJanosch Frank sccb->mask_length = sizeof(unsigned int); 42*7ed7df23SJanosch Frank sccb->receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 43*7ed7df23SJanosch Frank sccb->cp_receive_mask = SCLP_EVENT_MASK_MSG_ASCII; 44*7ed7df23SJanosch Frank sccb->send_mask = SCLP_EVENT_MASK_MSG_ASCII; 45*7ed7df23SJanosch Frank sccb->cp_send_mask = SCLP_EVENT_MASK_MSG_ASCII; 46*7ed7df23SJanosch Frank 47*7ed7df23SJanosch Frank sclp_service_call(SCLP_CMD_WRITE_EVENT_MASK, sccb); 48*7ed7df23SJanosch Frank } 49*7ed7df23SJanosch Frank 50*7ed7df23SJanosch Frank void sclp_console_setup(void) 51*7ed7df23SJanosch Frank { 52*7ed7df23SJanosch Frank sclp_set_write_mask(); 53*7ed7df23SJanosch Frank } 54*7ed7df23SJanosch Frank 55*7ed7df23SJanosch Frank void sclp_print(const char *str) 56*7ed7df23SJanosch Frank { 57*7ed7df23SJanosch Frank int len = strlen(str); 58*7ed7df23SJanosch Frank WriteEventData *sccb = (void *)_sccb; 59*7ed7df23SJanosch Frank 60*7ed7df23SJanosch Frank sccb->h.length = sizeof(WriteEventData) + len; 61*7ed7df23SJanosch Frank sccb->h.function_code = SCLP_FC_NORMAL_WRITE; 62*7ed7df23SJanosch Frank sccb->ebh.length = sizeof(EventBufferHeader) + len; 63*7ed7df23SJanosch Frank sccb->ebh.type = SCLP_EVENT_ASCII_CONSOLE_DATA; 64*7ed7df23SJanosch Frank sccb->ebh.flags = 0; 65*7ed7df23SJanosch Frank memcpy(sccb->data, str, len); 66*7ed7df23SJanosch Frank 67*7ed7df23SJanosch Frank sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb); 68*7ed7df23SJanosch Frank } 69