Files
org-hyperion-cules/service.c
Fish (David B. Trout) 26a1f86d7f PTT facility enhancements:
1. Expand trace class to 64-bits.
2. Predefined convenience macros.
3. Expand trace message to 18 characters.
4. Use convenience macros where possible.

This commit is mostly in preparation for upcoming LCS debugging via PTT facility enhancements to help debug Issue #43 (which is a race condition and thus timing dependent, thus PTT debugging rather than logmsg debugging), but I tried to design it to make it easier for other modules (e.g. QETH) to also transition away from logmsg debugging to debugging via PTT facilty instead.
2015-01-24 06:16:05 -08:00

2029 lines
71 KiB
C

/* SERVICE.C (c) Copyright Roger Bowler, 1999-2012 */
/* (c) Copyright Jan Jaeger, 1999-2012 */
/* ESA/390 Service Processor */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
/* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2012 */
/* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2012 */
/*-------------------------------------------------------------------*/
/* This module implements service processor functions */
/* for the Hercules ESA/390 emulator. */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
/* Additional credits: */
/* Corrections contributed by Jan Jaeger */
/* HMC system console functions by Jan Jaeger 2000-02-08 */
/* Expanded storage support by Jan Jaeger */
/* Dynamic CPU reconfiguration - Jan Jaeger */
/* Suppress superflous HHC701I/HHC702I messages - Jan Jaeger */
/* Break syscons output if too long - Jan Jaeger */
/* Added CPI - Control Program Information ev. - JJ 2001-11-19 */
/*-------------------------------------------------------------------*/
#include "hstdinc.h"
#if !defined(_HENGINE_DLL_)
#define _HENGINE_DLL_
#endif
#if !defined(_SERVICE_C_)
#define _SERVICE_C_
#endif
#include "hercules.h"
#include "opcode.h"
#include "inline.h"
#include "sr.h"
#if !defined(_SERVICE_C)
#define _SERVICE_C
/*-------------------------------------------------------------------*/
/* Service processor state data */
/*-------------------------------------------------------------------*/
static U32 servc_cp_recv_mask; /* Syscons CP receive mask */
static U32 servc_cp_send_mask; /* Syscons CP send mask */
static U32 servc_attn_pending; /* Attention pending mask */
static char servc_scpcmdstr[123+1]; /* Operator command string */
static U16 servc_signal_quiesce_count;
static BYTE servc_signal_quiesce_unit;
static BYTE servc_sysg_cmdcode; /* Pending SYSG read command */
/*-------------------------------------------------------------------*/
/* Reset the service processor to its initial state */
/*-------------------------------------------------------------------*/
void sclp_reset()
{
servc_cp_recv_mask = 0;
servc_cp_send_mask = 0;
servc_attn_pending = 0;
servc_signal_quiesce_count = 0;
servc_signal_quiesce_unit = 0;
servc_sysg_cmdcode = 0;
sysblk.servparm = 0;
}
// #ifdef FEATURE_SYSTEM_CONSOLE
/*-------------------------------------------------------------------*/
/* Raise service signal external interrupt */
/* (the caller is expected to hold the interrupt lock) */
/*-------------------------------------------------------------------*/
void sclp_attention(U16 type)
{
/* Set pending mask */
servc_attn_pending |= 0x80000000 >> (type -1);
/* Ignore request if already pending */
if (!(IS_IC_SERVSIG && (sysblk.servparm & SERVSIG_PEND)))
{
/* Set event pending flag in service parameter */
sysblk.servparm |= SERVSIG_PEND;
/* Set service signal interrupt pending for read event data */
ON_IC_SERVSIG;
WAKEUP_CPUS_MASK (sysblk.waiting_mask);
}
}
static void* sclp_attn_thread(void* arg)
{
U16 *type = (U16*) arg;
OBTAIN_INTLOCK(NULL);
// The VM boys appear to have made an error in not
// allowing for asyncronous attentions to be merged
// with pending interrupts as such we will wait here
// until a pending interrupt has been cleared. *JJ
while(IS_IC_SERVSIG)
{
RELEASE_INTLOCK(NULL);
sched_yield();
OBTAIN_INTLOCK(NULL);
}
sclp_attention(*type);
free(type);
RELEASE_INTLOCK(NULL);
return NULL;
}
static void sclp_attn_async(U16 type)
{
int rc;
if(!IS_IC_SERVSIG)
sclp_attention(type);
else
{
TID sclp_attn_tid;
U16 *typ;
typ=malloc(sizeof(U16));
*typ=type;
rc = create_thread(&sclp_attn_tid, &sysblk.detattr, sclp_attn_thread, typ, "attn_thread");
if (rc)
WRMSG(HHC00102, "E", strerror(rc));
}
}
static U32 sclp_attn_pending(U16 type)
{
U32 pending;
if(type)
{
pending = servc_attn_pending & (0x80000000 >> (type -1));
servc_attn_pending &= ~pending;
return pending;
}
else
return servc_attn_pending;
}
/*-------------------------------------------------------------------*/
/* Issue SCP command */
/* */
/* This function is called from the control panel when the operator */
/* enters an HMC system console SCP command or SCP priority message. */
/* The command is queued for processing by the SCLP_READ_EVENT_DATA */
/* service call, and a service signal interrupt is made pending. */
/* */
/* Input: */
/* command Null-terminated ASCII command string */
/* priomsg 0=SCP command, 1=SCP priority message */
/*-------------------------------------------------------------------*/
int scp_command (char *command, int priomsg, int echo)
{
int rc = 0;
/* Error if disabled for priority messages */
if (priomsg && !SCLP_RECV_ENABLED(PRIOR))
{
WRMSG (HHC00002, "E", "priority commands");
return -1;
}
/* Error if disabled for commands */
if (!priomsg && !SCLP_RECV_ENABLED(OPCMD))
{
WRMSG (HHC00002, "E", "operator commands");
return -1;
}
/* Error if command string is missing */
if (strlen(command) < 1)
{
WRMSG (HHC00003, "E");
return -1;
}
if (echo)
WRMSG(HHC00160, "I", priomsg ? "priority " : "", command);
/* Obtain the interrupt lock */
OBTAIN_INTLOCK(NULL);
/* Save command string and message type for read event data */
strncpy (servc_scpcmdstr, command, sizeof(servc_scpcmdstr));
/* Ensure termination of the command string */
servc_scpcmdstr[sizeof(servc_scpcmdstr)-1] = '\0';
/* Raise attention service signal */
sclp_attention( priomsg ? SCCB_EVD_TYPE_PRIOR : SCCB_EVD_TYPE_OPCMD );
rc = 0;
/* Release the interrupt lock */
RELEASE_INTLOCK(NULL);
return rc;
} /* end function scp_command */
static void sclp_opcmd_event(SCCB_HEADER *sccb, U16 type)
{
static BYTE const1_template[] = {
0x13,0x10, /* MDS message unit */
0x00,0x25,0x13,0x11, /* MDS routine info */
0x0E,0x81, /* origin location name */
0x03,0x01,0x00, /* Net ID */
0x03,0x02,0x00, /* NAU Name */
0x06,0x03,0x00,0x00,0x00,0x00, /* Appl id */
0x0E,0x82, /* Destinition location name */
0x03,0x01,0x00, /* Net ID */
0x03,0x02,0x00, /* NAU Name */
0x06,0x03,0x00,0x00,0x00,0x00, /* Appl id */
0x05,0x90,0x00,0x00,0x00, /* Flags (MDS type = req) */
0x00,0x0C,0x15,0x49, /* Agent unit-of-work */
0x08,0x01, /* Requestor loc name */
0x03,0x01,0x00, /* Requestor Net ID */
0x03,0x02,0x00 /* Requestor Node ID */
};
static BYTE const2_template[] = {
0x12,0x12, /* CP-MSU */
0x00,0x12,0x15,0x4D, /* RTI */
0x0E,0x06, /* Name List */
0x06,0x10,0x00,0x03,0x00,0x00, /* Cascaded
resource list */
0x06,0x60,0xD6,0xC3,0xC6,0xC1, /* OAN (C'OCFA') */
0x00,0x04,0x80,0x70 /* Operate request */
};
static BYTE const3_template[] = {
0x13,0x20 /* Text data */
};
static BYTE const4_template = {
0x31 /* Self-defining */
};
static BYTE const5_template = {
0x30 /* Text data */
};
U16 sccb_len;
U16 evd_len;
int event_msglen;
int i;
SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1);
SCCB_EVD_BK *evd_bk = (SCCB_EVD_BK*)(evd_hdr+1);
BYTE *event_msg = (BYTE*)(evd_bk+1);
/* Get SCCB length */
FETCH_HW(sccb_len, sccb->length);
/* Command length */
event_msglen = (int)strlen(servc_scpcmdstr);
/* Calculate required EVD length */
evd_len = event_msglen + (int)sizeof(SCCB_EVD_HDR) + (int)sizeof(SCCB_EVD_BK);
/* Set response code X'75F0' if SCCB length exceeded */
if ((evd_len + sizeof(SCCB_HEADER)) > sccb_len)
{
sccb->reas = SCCB_REAS_EXCEEDS_SCCB;
sccb->resp = SCCB_RESP_EXCEEDS_SCCB;
return;
}
/* Zero all fields */
/* Update SCCB length field if variable request */
if (sccb->type & SCCB_TYPE_VARIABLE)
{
/* Set new SCCB length */
sccb_len = evd_len + sizeof(SCCB_HEADER);
STORE_HW(sccb->length, sccb_len);
sccb->type &= ~SCCB_TYPE_VARIABLE;
}
/* Set length in event header */
STORE_HW(evd_hdr->totlen, evd_len);
/* Set type in event header */
evd_hdr->type = type;
/* Set message length in event data block */
i = evd_len - sizeof(SCCB_EVD_HDR);
STORE_HW(evd_bk->msglen, i);
memcpy (evd_bk->const1, const1_template,
sizeof(const1_template));
i -= sizeof(const1_template) + 2;
STORE_HW(evd_bk->cplen, i);
memcpy (evd_bk->const2, const2_template,
sizeof(const2_template));
i -= sizeof(const2_template) + 2;
STORE_HW(evd_bk->tdlen, i);
memcpy (evd_bk->const3, const3_template,
sizeof(const3_template));
i -= sizeof(const3_template) + 2;
evd_bk->sdtlen = i;
evd_bk->const4 = const4_template;
i -= 2;
evd_bk->tmlen = i;
evd_bk->const5 = const5_template;
/* Copy and translate command */
for (i = 0; i < event_msglen; i++)
event_msg[i] = host_to_guest(servc_scpcmdstr[i]);
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
}
static void sclp_cpident(SCCB_HEADER *sccb)
{
SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb + 1);
SCCB_CPI_BK *cpi_bk = (SCCB_CPI_BK*)(evd_hdr + 1);
int i;
char systype[9], sysname[9], sysplex[9];
U64 syslevel;
if(*(cpi_bk->system_type))
set_systype(cpi_bk->system_type);
if(*(cpi_bk->system_name))
set_sysname(cpi_bk->system_name);
if(*(cpi_bk->sysplex_name))
set_sysplex(cpi_bk->sysplex_name);
for(i = 0; i < 8; i++)
{
systype[i] = guest_to_host(cpi_bk->system_type[i]);
sysname[i] = guest_to_host(cpi_bk->system_name[i]);
sysplex[i] = guest_to_host(cpi_bk->sysplex_name[i]);
}
systype[8] = sysname[8] = sysplex[8] = 0;
for(i = 7; i >= 0 && systype[i] == ' '; i--)
systype[i] = 0;
for(i = 7; i >= 0 && sysname[i] == ' '; i--)
sysname[i] = 0;
for(i = 7; i >= 0 && sysplex[i] == ' '; i--)
sysplex[i] = 0;
FETCH_DW(syslevel,cpi_bk->system_level);
WRMSG(HHC00004, "I",systype,sysname,sysplex,syslevel);
#if defined(ENABLE_BUILTIN_SYMBOLS)
{
char buf[128];
MSGBUF(buf, "%"I64_FMT"X", syslevel );
set_symbol("SYSTYPE", systype);
set_symbol("SYSNAME", sysname);
set_symbol("SYSPLEX", sysplex);
set_symbol("SYSLEVEL", buf);
}
#endif
#if defined(OPTION_LPP_RESTRICT)
losc_check(systype);
#endif /*defined(OPTION_LPP_RESTRICT)*/
/* Indicate Event Processed */
evd_hdr->flag |= SCCB_EVD_FLAG_PROC;
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
}
/*-------------------------------------------------------------------*/
/* Test whether SCP is enabled for QUIESCE signal */
/* */
/* This function tests whether the SCP is willing to be notified */
/* of a system shutdown via the SCLP_READ_EVENT_DATA service call. */
/* */
/* Return code: */
/* Zero = SCP not receiving quiesce event notification */
/* Non-zero = SCP ready to receive quiesce event notification */
/*-------------------------------------------------------------------*/
int can_signal_quiesce()
{
return SCLP_RECV_ENABLED(SIGQ);
}
/*-------------------------------------------------------------------*/
/* Test whether SCP is enabled to receive Operator Commands */
/* */
/* This function tests whether the SCP is willing to receive */
/* an operator command via the SCLP_READ_EVENT_DATA service call. */
/* */
/* Return code: */
/* Zero = SCP not receiving Operator Commands */
/* Non-zero = SCP ready to receive Operator Commands */
/*-------------------------------------------------------------------*/
int can_send_command()
{
return SCLP_RECV_ENABLED(OPCMD);
}
/*-------------------------------------------------------------------*/
/* Send QUIESCE signal to SCP */
/* */
/* This function is called during system shutdown to notify the SCP */
/* that a shutdown event is occurring. The shutdown event is queued */
/* for processing by the SCLP_READ_EVENT_DATA service call, and a */
/* service signal interrupt is made pending. */
/* */
/* Input: */
/* count and unit values to be returned by SCLP_READ_EVENT_DATA */
/*-------------------------------------------------------------------*/
int signal_quiesce (U16 count, BYTE unit)
{
/* Error if disabled for commands */
if (!SCLP_RECV_ENABLED(SIGQ))
{
WRMSG (HHC00002, "E", "quiesce signals" );
return -1;
}
/* Obtain the interrupt lock */
OBTAIN_INTLOCK(NULL);
/* Save delay values for signal shutdown event read */
servc_signal_quiesce_count = count;
servc_signal_quiesce_unit = unit;
sclp_attention(SCCB_EVD_TYPE_SIGQ);
/* Release the interrupt lock */
RELEASE_INTLOCK(NULL);
return 0;
} /* end function signal_quiesce */
static void sclp_sigq_event(SCCB_HEADER *sccb)
{
U16 sccb_len;
U16 evd_len;
SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1);
SCCB_SGQ_BK *sgq_bk = (SCCB_SGQ_BK*)(evd_hdr+1);
FETCH_HW(sccb_len, sccb->length);
evd_len = sizeof(SCCB_EVD_HDR) + sizeof(SCCB_SGQ_BK);
/* Set response code X'75F0' if SCCB length exceeded */
if ((evd_len + sizeof(SCCB_HEADER)) > sccb_len)
{
sccb->reas = SCCB_REAS_EXCEEDS_SCCB;
sccb->resp = SCCB_RESP_EXCEEDS_SCCB;
return;
}
/* Zero all fields */
memset (evd_hdr, 0, evd_len);
/* Update SCCB length field if variable request */
if (sccb->type & SCCB_TYPE_VARIABLE)
{
/* Set new SCCB length */
sccb_len = evd_len + sizeof(SCCB_HEADER);
STORE_HW(sccb->length, sccb_len);
sccb->type &= ~SCCB_TYPE_VARIABLE;
}
/* Set length in event header */
STORE_HW(evd_hdr->totlen, evd_len);
/* Set type in event header */
evd_hdr->type = SCCB_EVD_TYPE_SIGQ;
STORE_HW(sgq_bk->count, servc_signal_quiesce_count);
sgq_bk->unit = servc_signal_quiesce_unit;
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
}
#if defined(_FEATURE_INTEGRATED_3270_CONSOLE)
/*-------------------------------------------------------------------*/
/* Write data to the SYSG console */
/* */
/* The datastream to be written to the SYSG console is in the SCCB */
/* immediately following the Event Data Header. It consists of a */
/* one-byte local 3270 CCW command code, followed by a 3270 WCC, */
/* followed by 3270 orders and data. */
/* */
/* Input: */
/* sccb Address of SCCB */
/* evd_hdr Address of event data header within SCCB */
/* Output: */
/* Reason and response codes are set in the SCCB */
/* */
/*-------------------------------------------------------------------*/
static void sclp_sysg_write(SCCB_HEADER *sccb)
{
SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1);
U16 evd_len; /* SCCB event data length */
U16 sysg_len; /* SYSG output data length */
DEVBLK *dev; /* -> SYSG console devblk */
BYTE *sysg_data; /* -> SYSG output data */
BYTE unitstat; /* Unit status */
BYTE more = 0; /* Flag for device handler */
U32 residual; /* Residual data count */
BYTE cmdcode; /* 3270 read/write command */
/* Calculate the address and length of the 3270 datastream */
FETCH_HW(evd_len,evd_hdr->totlen);
sysg_data = (BYTE*)(evd_hdr+1);
sysg_len = evd_len - sizeof(SCCB_EVD_HDR);
/* The first data byte is the 3270 command code */
cmdcode = *sysg_data;
/* Look for the SYSG console device block */
dev = sysblk.sysgdev;
if (dev == NULL)
{
PTT_ERR("*SERVC",(U32)cmdcode,(U32)sysg_len,0);
/* Set response code X'05F0' in SCCB header */
sccb->reas = SCCB_REAS_IMPROPER_RSC;
sccb->resp = SCCB_RESP_REJECT;
return;
}
/* If it is a read CCW then save the command until READ_EVENT_DATA */
if (IS_CCW_READ(cmdcode))
{
servc_sysg_cmdcode = cmdcode;
/* Indicate Event Processed */
evd_hdr->flag |= SCCB_EVD_FLAG_PROC;
/* Generate a service call interrupt to trigger READ_EVENT_DATA */
sclp_attn_async(SCCB_EVD_TYPE_SYSG);
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
return;
}
else
{
servc_sysg_cmdcode = 0x00;
/* Execute the 3270 command in data block */
/* dev->hnd->exec points to loc3270_execute_ccw */
(dev->hnd->exec) (dev, /*ccw opcode*/ cmdcode,
/*flags*/ CCW_FLAGS_SLI, /*chained*/0,
/*count*/ sysg_len - 1,
/*prevcode*/ 0, /*ccwseq*/ 0, /*iobuf*/ sysg_data+1,
&more, &unitstat, &residual);
/* Indicate Event Processed */
evd_hdr->flag |= SCCB_EVD_FLAG_PROC;
/* If unit check occured, set response code X'0040' */
if (unitstat & CSW_UC)
{
PTT_ERR("*SERVC",(U32)more,(U32)unitstat,residual);
/* Set response code X'0040' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_BACKOUT;
return;
}
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
}
}
/*-------------------------------------------------------------------*/
/* Read data from the SYSG console */
/* */
/* If the SYSG console has data to send, copy it into the SCCB */
/* immediately following the Event Data Header. The data consists */
/* of a 3270 AID byte, followed by a two-byte 3270 cursor address, */
/* followed by 3270 orders and data. */
/* */
/* Output: */
/* Data, reason and response codes are set in the SCCB */
/* */
/*-------------------------------------------------------------------*/
static void sclp_sysg_poll(SCCB_HEADER *sccb)
{
SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1);
U16 sccblen; /* SCCB total length */
U16 evd_len; /* SCCB event data length */
U16 sysg_len; /* SYSG input data length */
DEVBLK *dev; /* -> SYSG console devblk */
BYTE *sysg_data; /* -> SYSG input data */
BYTE *sysg_cmd; /* -> SYSG input data */
BYTE unitstat; /* Unit status */
BYTE more = 0; /* Flag for device handler */
U32 residual; /* Residual data count */
dev = sysblk.sysgdev;
if (dev != NULL)
{
/* Zeroize the event data header */
memset (evd_hdr, 0, sizeof(SCCB_EVD_HDR));
/* Calculate maximum data length */
FETCH_HW(sccblen, sccb->length);
evd_len = sccblen - sizeof(SCCB_HEADER);
sysg_data = (BYTE*)(evd_hdr+1);
sysg_len = evd_len - sizeof(SCCB_EVD_HDR);
/* Insert flag byte before the 3270 input data */
sysg_cmd = sysg_data;
sysg_len-=1;
sysg_data+=1;
/* Execute previously saved 3270 read command */
if (servc_sysg_cmdcode)
{
*sysg_cmd = 0x00;
/* Execute a 3270 read-modified command */
/* dev->hnd->exec points to loc3270_execute_ccw */
(dev->hnd->exec) (dev, /*ccw opcode*/ servc_sysg_cmdcode,
/*flags*/ CCW_FLAGS_SLI, /*chained*/0,
/*count*/ sysg_len,
/*prevcode*/ 0, /*ccwseq*/ 0, /*iobuf*/ sysg_data,
&more, &unitstat, &residual);
servc_sysg_cmdcode = 0;
/* Set response code X'0040' if unit check occurred */
if (unitstat & CSW_UC)
{
PTT_ERR("*SERVC",(U32)more,(U32)unitstat,residual);
/* Set response code X'0040' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_BACKOUT;
return;
}
/* Set response code X'75F0' if SCCB length exceeded */
if (more)
{
PTT_ERR("*SERVC",(U32)more,(U32)unitstat,residual);
sccb->reas = SCCB_REAS_EXCEEDS_SCCB;
sccb->resp = SCCB_RESP_EXCEEDS_SCCB;
return;
}
/* Calculate actual length read */
sysg_len -= residual;
evd_len = sizeof(SCCB_EVD_HDR) + sysg_len + 1;
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
}
else
{
evd_len = sizeof(SCCB_EVD_HDR) + 1;
*sysg_cmd = 0x80;
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
}
/* Update SCCB length field if variable request */
if (sccb->type & SCCB_TYPE_VARIABLE)
{
/* Set new SCCB length */
sccblen = evd_len + sizeof(SCCB_HEADER);
STORE_HW(sccb->length, sccblen);
sccb->type &= ~SCCB_TYPE_VARIABLE;
}
/* Set length in event header */
STORE_HW(evd_hdr->totlen, evd_len);
/* Set type in event header */
evd_hdr->type = SCCB_EVD_TYPE_SYSG;
}
}
/*-------------------------------------------------------------------*/
/* Handle attention interrupt from the SYSG console */
/* */
/* This function is called by console.c when it receives input */
/* from the SYSG console. It sets the SYSG read flag and raises */
/* a service signal external interrupt, which should prompt the */
/* SCP to issue a SCLP_READ_EVENT_DATA service call to retrieve */
/* the input data. */
/*-------------------------------------------------------------------*/
SERV_DLL_IMPORT
void sclp_sysg_attention()
{
OBTAIN_INTLOCK(NULL);
sclp_attn_async(SCCB_EVD_TYPE_SYSG);
RELEASE_INTLOCK(NULL);
}
#endif /*defined(_FEATURE_INTEGRATED_3270_CONSOLE)*/
#if defined(_FEATURE_INTEGRATED_ASCII_CONSOLE)
static int sclp_sysa_write(SCCB_HEADER *sccb)
{
SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1);
U16 evd_len;
U16 sysa_len;
BYTE *sysa_data;
int i;
logmsg(_("SYSA write:"));
FETCH_HW(evd_len,evd_hdr->totlen);
sysa_data = (BYTE*)(evd_hdr+1);
sysa_len = evd_len - sizeof(SCCB_EVD_HDR);
for(i = 0; i < sysa_len; i++)
{
if(!(i & 15))
logmsg("\n %4.4X:", i);
logmsg(" %2.2X", sysa_data[i]);
}
if(i & 15)
logmsg("\n");
/* Indicate Event Processed */
evd_hdr->flag |= SCCB_EVD_FLAG_PROC;
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE; // maybe this needs to be INFO
//sclp_attention(SCCB_EVD_TYPE_VT220);
return 0; // write ok
}
static int sclp_sysa_poll(SCCB_HEADER *sccb)
{
SCCB_EVD_HDR *evd_hdr = (SCCB_EVD_HDR*)(sccb+1);
UNREFERENCED(sccb);
UNREFERENCED(evd_hdr);
logmsg(_("VT220 poll\n"));
}
#endif /*defined(_FEATURE_INTEGRATED_ASCII_CONSOLE)*/
/*-------------------------------------------------------------------*/
/* Suspend and resume functions */
/*-------------------------------------------------------------------*/
#define SR_SYS_SERVC_RECVMASK ( SR_SYS_SERVC | 0x001 )
#define SR_SYS_SERVC_SENDMASK ( SR_SYS_SERVC | 0x002 )
#define SR_SYS_SERVC_PENDING ( SR_SYS_SERVC | 0x003 )
#define SR_SYS_SERVC_SCPCMD ( SR_SYS_SERVC | 0x004 )
#define SR_SYS_SERVC_SQC ( SR_SYS_SERVC | 0x005 )
#define SR_SYS_SERVC_SQU ( SR_SYS_SERVC | 0x006 )
#define SR_SYS_SERVC_PARM ( SR_SYS_SERVC | 0x007 )
int servc_hsuspend(void *file)
{
SR_WRITE_VALUE(file, SR_SYS_SERVC_RECVMASK, servc_cp_recv_mask, sizeof(servc_cp_recv_mask));
SR_WRITE_VALUE(file, SR_SYS_SERVC_SENDMASK, servc_cp_send_mask, sizeof(servc_cp_send_mask));
SR_WRITE_VALUE(file, SR_SYS_SERVC_PENDING, servc_attn_pending, sizeof(servc_attn_pending));
SR_WRITE_STRING(file, SR_SYS_SERVC_SCPCMD, servc_scpcmdstr);
SR_WRITE_VALUE(file, SR_SYS_SERVC_SQC, servc_signal_quiesce_count,
sizeof(servc_signal_quiesce_count));
SR_WRITE_VALUE(file, SR_SYS_SERVC_SQU, servc_signal_quiesce_unit,
sizeof(servc_signal_quiesce_unit));
SR_WRITE_VALUE(file, SR_SYS_SERVC_PARM, sysblk.servparm,
sizeof(sysblk.servparm));
return 0;
}
int servc_hresume(void *file)
{
size_t key, len;
sclp_reset();
do {
SR_READ_HDR(file, key, len);
switch (key) {
case SR_SYS_SERVC_RECVMASK:
SR_READ_VALUE(file, len, &servc_cp_recv_mask, sizeof(servc_cp_recv_mask));
break;
case SR_SYS_SERVC_SENDMASK:
SR_READ_VALUE(file, len, &servc_cp_send_mask, sizeof(servc_cp_send_mask));
break;
case SR_SYS_SERVC_PENDING:
SR_READ_VALUE(file, len, &servc_attn_pending, sizeof(servc_attn_pending));
break;
case SR_SYS_SERVC_SCPCMD:
if ( len <= sizeof(servc_scpcmdstr) )
SR_READ_STRING(file, servc_scpcmdstr, len);
else
SR_READ_SKIP(file, len);
break;
case SR_SYS_SERVC_SQC:
SR_READ_VALUE(file, len, &servc_signal_quiesce_count,
sizeof(servc_signal_quiesce_count));
break;
case SR_SYS_SERVC_SQU:
SR_READ_VALUE(file, len, &servc_signal_quiesce_unit,
sizeof(servc_signal_quiesce_unit));
break;
case SR_SYS_SERVC_PARM:
SR_READ_VALUE(file, len, &sysblk.servparm, sizeof(sysblk.servparm));
break;
default:
SR_READ_SKIP(file, len);
break;
}
} while ((key & SR_SYS_MASK) == SR_SYS_SERVC);
return 0;
}
#endif /*!defined(_SERVICE_C)*/
// #endif /*FEATURE_SYSTEM_CONSOLE*/
#if defined(FEATURE_SERVICE_PROCESSOR)
/*-------------------------------------------------------------------*/
/* Architecture-dependent service processor bit strings */
/*-------------------------------------------------------------------*/
BYTE ARCH_DEP(scpinfo_ifm)[8] = {
0
| SCCB_IFM0_CHANNEL_PATH_INFORMATION
| SCCB_IFM0_CHANNEL_PATH_SUBSYSTEM_COMMAND
// | SCCB_IFM0_CHANNEL_PATH_RECONFIG
// | SCCB_IFM0_CPU_INFORMATION
#ifdef FEATURE_CPU_RECONFIG
| SCCB_IFM0_CPU_RECONFIG
#endif /*FEATURE_CPU_RECONFIG*/
,
0
// | SCCB_IFM1_SIGNAL_ALARM
// | SCCB_IFM1_WRITE_OPERATOR_MESSAGE
// | SCCB_IFM1_STORE_STATUS_ON_LOAD
// | SCCB_IFM1_RESTART_REASONS
// | SCCB_IFM1_INSTRUCTION_ADDRESS_TRACE_BUFFER
| SCCB_IFM1_LOAD_PARAMETER
,
0
// | SCCB_IFM2_REAL_STORAGE_INCREMENT_RECONFIG
// | SCCB_IFM2_REAL_STORAGE_ELEMENT_INFO
// | SCCB_IFM2_REAL_STORAGE_ELEMENT_RECONFIG
// | SCCB_IFM2_COPY_AND_REASSIGN_STORAGE
#ifdef FEATURE_EXPANDED_STORAGE
| SCCB_IFM2_EXTENDED_STORAGE_USABILITY_MAP
#endif /*FEATURE_EXPANDED_STORAGE*/
// | SCCB_IFM2_EXTENDED_STORAGE_ELEMENT_INFO
// | SCCB_IFM2_EXTENDED_STORAGE_ELEMENT_RECONFIG
,
0
#if defined(FEATURE_VECTOR_FACILITY) && defined(FEATURE_CPU_RECONFIG)
| SCCB_IFM3_VECTOR_FEATURE_RECONFIG
#endif /*FEATURE_VECTOR_FACILITY*/
#ifdef FEATURE_SYSTEM_CONSOLE
| SCCB_IFM3_READ_WRITE_EVENT_FEATURE
#endif /*FEATURE_SYSTEM_CONSOLE*/
// | SCCB_IFM3_READ_RESOURCE_GROUP_INFO
,
0, 0, 0, 0 };
BYTE ARCH_DEP(scpinfo_cfg)[6] = {
0
#if defined(FEATURE_HYPERVISOR)
// | SCCB_CFG0_LOGICALLY_PARTITIONED
#endif /*defined(FEATURE_HYPERVISOR)*/
#ifdef FEATURE_SUPPRESSION_ON_PROTECTION
| SCCB_CFG0_SUPPRESSION_ON_PROTECTION
#endif /*FEATURE_SUPPRESSION_ON_PROTECTION*/
// | SCCB_CFG0_INITIATE_RESET
#if defined(FEATURE_CHSC)
| SCCB_CFG0_STORE_CHANNEL_SUBSYS_CHARACTERISTICS
#endif /*defined(FEATURE_CHSC)*/
#if defined(FEATURE_MOVE_PAGE_FACILITY_2)
| SCCB_CFG0_MVPG_FOR_ALL_GUESTS
#endif /*defined(FEATURE_MOVE_PAGE_FACILITY_2)*/
#if defined(FEATURE_FAST_SYNC_DATA_MOVER)
/* The Fast Sync Data Mover facility is simply a flag which
indicates that the MVPG instruction performs faster than
the Asynchronous Data Mover facility (see GA22-1030-03) */
| SCCB_CFG0_FAST_SYNCHRONOUS_DATA_MOVER
#endif /*defined(FEATURE_FAST_SYNC_DATA_MOVER)*/
,
0
// | SCCB_CFG1_CSLO
,
0
// | SCCB_CFG2_DEVICE_ACTIVE_ONLY_MEASUREMENT
#ifdef FEATURE_CALLED_SPACE_IDENTIFICATION
| SCCB_CFG2_CALLED_SPACE_IDENTIFICATION
#endif /*FEATURE_CALLED_SPACE_IDENTIFICATION*/
#ifdef FEATURE_CHECKSUM_INSTRUCTION
| SCCB_CFG2_CHECKSUM_INSTRUCTION
#endif /*FEATURE_CHECKSUM_INSTRUCTION*/
,
0
#if defined(FEATURE_RESUME_PROGRAM)
| SCCB_CFG3_RESUME_PROGRAM
#endif /*defined(FEATURE_RESUME_PROGRAM)*/
#if defined(FEATURE_PERFORM_LOCKED_OPERATION)
| SCCB_CFG3_PERFORM_LOCKED_OPERATION
#endif /*defined(FEATURE_PERFORM_LOCKED_OPERATION)*/
#ifdef FEATURE_IMMEDIATE_AND_RELATIVE
| SCCB_CFG3_IMMEDIATE_AND_RELATIVE
#endif /*FEATURE_IMMEDIATE_AND_RELATIVE*/
#ifdef FEATURE_COMPARE_AND_MOVE_EXTENDED
| SCCB_CFG3_COMPARE_AND_MOVE_EXTENDED
#endif /*FEATURE_COMPARE_AND_MOVE_EXTENDED*/
#ifdef FEATURE_BRANCH_AND_SET_AUTHORITY
| SCCB_CFG3_BRANCH_AND_SET_AUTHORITY
#endif /*FEATURE_BRANCH_AND_SET_AUTHORITY*/
#if defined(FEATURE_BASIC_FP_EXTENSIONS)
| SCCB_CFG3_EXTENDED_FLOATING_POINT
#endif /*defined(FEATURE_BASIC_FP_EXTENSIONS)*/
/*ZZ*/ | SCCB_CFG3_EXTENDED_LOGICAL_COMPUTATION_FACILITY
,
0
#ifdef FEATURE_EXTENDED_TOD_CLOCK
| SCCB_CFG4_EXTENDED_TOD_CLOCK
#endif /*FEATURE_EXTENDED_TOD_CLOCK*/
#if defined(FEATURE_EXTENDED_TRANSLATION)
| SCCB_CFG4_EXTENDED_TRANSLATION
#endif /*defined(FEATURE_EXTENDED_TRANSLATION)*/
#if defined(FEATURE_LOAD_REVERSED)
| SCCB_CFG4_LOAD_REVERSED_FACILITY
#endif /*defined(FEATURE_LOAD_REVERSED)*/
#if defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)
| SCCB_CFG4_EXTENDED_TRANSLATION_FACILITY2
#endif /*defined(FEATURE_EXTENDED_TRANSLATION_FACILITY_2)*/
#if defined(FEATURE_STORE_SYSTEM_INFORMATION)
| SCCB_CFG4_STORE_SYSTEM_INFORMATION
#endif /*FEATURE_STORE_SYSTEM_INFORMATION*/
// | SCCB_CFG4_LPAR_CLUSTERING
| SCCB_CFG4_IFA_FACILITY
,
0
#if defined(FEATURE_SENSE_RUNNING_STATUS)
| SCCB_CFG5_SENSE_RUNNING_STATUS
#endif /*FEATURE_SENSE_RUNNING_STATUS*/
};
BYTE ARCH_DEP(scpinfo_cfg11) =
0
#if defined(FEATURE_PER3)
| SCCB_CFGB_PER_3
#endif
| SCCB_CFGB_LIST_DIRECTED_IPL;
BYTE ARCH_DEP(scpinfo_cpf)[12] = {
0
#if defined(FEATURE_INTERPRETIVE_EXECUTION)
#if defined(_370) && !defined(FEATURE_ESAME)
| SCCB_CPF0_SIE_370_MODE
#endif /*defined(_370) && !defined(FEATURE_ESAME)*/
| SCCB_CPF0_SIE_XA_MODE
#endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/
// | SCCB_CPF0_SIE_SET_II_370_MODE
#if defined(FEATURE_IO_ASSIST)
| SCCB_CPF0_SIE_SET_II_XA_MODE
#endif /*defined(FEATURE_IO_ASSIST)*/
#if defined(FEATURE_INTERPRETIVE_EXECUTION)
| SCCB_CPF0_SIE_NEW_INTERCEPT_FORMAT
#endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/
#if defined(FEATURE_STORAGE_KEY_ASSIST)
| SCCB_CPF0_STORAGE_KEY_ASSIST
#endif /*defined(FEATURE_STORAGE_KEY_ASSIST)*/
#if defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)
| SCCB_CPF0_MULTIPLE_CONTROLLED_DATA_SPACE
#endif /*defined(_FEATURE_MULTIPLE_CONTROLLED_DATA_SPACE)*/
,
0
#if defined(FEATURE_IO_ASSIST)
| SCCB_CPF1_IO_INTERPRETATION_LEVEL_2
#endif /*defined(FEATURE_IO_ASSIST)*/
#if defined(FEATURE_INTERPRETIVE_EXECUTION)
| SCCB_CPF1_GUEST_PER_ENHANCED
#endif /*defined(FEATURE_INTERPRETIVE_EXECUTION)*/
// | SCCB_CPF1_SIGP_INTERPRETATION_ASSIST
#if defined(FEATURE_STORAGE_KEY_ASSIST)
| SCCB_CPF1_RCP_BYPASS_FACILITY
#endif /*defined(FEATURE_STORAGE_KEY_ASSIST)*/
#if defined(FEATURE_REGION_RELOCATE)
| SCCB_CPF1_REGION_RELOCATE_FACILITY
#endif /*defined(FEATURE_REGION_RELOCATE)*/
#if defined(FEATURE_EXPEDITED_SIE_SUBSET)
| SCCB_CPF1_EXPEDITE_TIMER_PROCESSING
#endif /*defined(FEATURE_EXPEDITED_SIE_SUBSET)*/
,
0
#if defined(FEATURE_CRYPTO)
| SCCB_CPF2_CRYPTO_FEATURE_ACCESSED
#endif /*defined(FEATURE_CRYPTO)*/
#if defined(FEATURE_EXPEDITED_SIE_SUBSET)
| SCCB_CPF2_EXPEDITE_RUN_PROCESSING
#endif /*defined(FEATURE_EXPEDITED_SIE_SUBSET)*/
,
0
#ifdef FEATURE_PRIVATE_SPACE
| SCCB_CPF3_PRIVATE_SPACE_FEATURE
| SCCB_CPF3_FETCH_ONLY_BIT
#endif /*FEATURE_PRIVATE_SPACE*/
#if defined(FEATURE_PER2)
| SCCB_CPF3_PER2_INSTALLED
#endif /*defined(FEATURE_PER2)*/
,
0
#if defined(FEATURE_PER2)
| SCCB_CPF4_OMISION_GR_ALTERATION_370
#endif /*defined(FEATURE_PER2)*/
,
0
#if defined(FEATURE_WAITSTATE_ASSIST)
| SCCB_CPF5_GUEST_WAIT_STATE_ASSIST
#endif /*defined(FEATURE_WAITSTATE_ASSIST)*/
,
0, 0, 0, 0, 0, 0
} ;
U32 ARCH_DEP(sclp_recv_mask) = 0
| EVDMASK(MSG)
| EVDMASK(PRIOR)
#if defined(FEATURE_SCEDIO)
| EVDMASK(SCEDIO)
#endif /*defined(FEATURE_SCEDIO)*/
#if defined(FEATURE_HARDWARE_LOADER)
| EVDMASK(HWL)
| EVDMASK(SDIAS)
#endif /*defined(FEATURE_HARDWARE_LOADER)*/
#if defined(FEATURE_INTEGRATED_ASCII_CONSOLE)
| EVDMASK(VT220)
#endif /*defined(FEATURE_INTEGRATED_ASCII_CONSOLE)*/
#if defined(FEATURE_INTEGRATED_3270_CONSOLE)
| EVDMASK(SYSG)
#endif /*defined(FEATURE_INTEGRATED_3270_CONSOLE)*/
| EVDMASK(CPIDENT)
;
U32 ARCH_DEP(sclp_send_mask) = 0
| EVDMASK(OPCMD)
| EVDMASK(STATECH)
| EVDMASK(PRIOR)
| EVDMASK(SIGQ)
#if defined(FEATURE_SCEDIO)
| EVDMASK(SCEDIO)
#endif /*defined(FEATURE_SCEDIO)*/
#if defined(_FEATURE_HARDWARE_LOADER)
| EVDMASK(HWL)
| EVDMASK(SDIAS)
#endif /*defined(_FEATURE_HARDWARE_LOADER)*/
#if defined(FEATURE_INTEGRATED_ASCII_CONSOLE)
| EVDMASK(VT220)
#endif /*defined(FEATURE_INTEGRATED_ASCII_CONSOLE)*/
#if defined(FEATURE_INTEGRATED_3270_CONSOLE)
| EVDMASK(SYSG)
#endif /*defined(FEATURE_INTEGRATED_3270_CONSOLE)*/
| EVDMASK(CPCMD)
;
/*-------------------------------------------------------------------*/
/* B220 SERVC - Service Call [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(service_call)
{
U32 r1, r2; /* Values of R fields */
U32 sclp_command; /* SCLP command code */
U32 sccb_real_addr; /* SCCB real address */
int i; /* Array subscripts */
U32 realmb; /* Real storage size in MB */
U32 sccb_absolute_addr; /* Absolute address of SCCB */
U32 sccblen; /* Length of SCCB */
SCCB_HEADER *sccb; /* -> SCCB header */
SCCB_SCP_INFO *sccbscp; /* -> SCCB SCP information */
SCCB_CPU_INFO *sccbcpu; /* -> SCCB CPU information */
#if defined(FEATURE_MPF_INFO)
SCCB_MPF_INFO *sccbmpf; /* -> SCCB MPF information */
#endif /*defined(FEATURE_MPF_INFO)*/
#ifdef FEATURE_CHANNEL_SUBSYSTEM
SCCB_CHP_INFO *sccbchp; /* -> SCCB channel path info */
#else
SCCB_CHSET_INFO *sccbchp; /* -> SCCB channel path info */
#endif
SCCB_CSI_INFO *sccbcsi; /* -> SCCB channel subsys inf*/
U16 offset; /* Offset from start of SCCB */
#ifdef FEATURE_CHANNEL_SUBSYSTEM
DEVBLK *dev; /* Used to find CHPIDs */
U32 chpbyte; /* Offset to byte for CHPID */
U32 chpbit; /* Bit number for CHPID */
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/
#ifdef FEATURE_SYSTEM_CONSOLE
SCCB_EVENT_MASK*evd_mask; /* Event mask */
SCCB_EVD_HDR *evd_hdr; /* Event header */
U16 evd_len; /* Length of event data */
SCCB_MCD_BK *mcd_bk; /* Message Control Data */
U16 mcd_len; /* Length of MCD */
SCCB_OBJ_HDR *obj_hdr; /* Object Header */
U16 obj_len; /* Length of Object */
U16 obj_type; /* Object type */
SCCB_MTO_BK *mto_bk; /* Message Text Object */
BYTE *event_msg; /* Message Text pointer */
int event_msglen; /* Message Text length */
BYTE message[4089]; /* Maximum event data buffer
length plus one for \0 */
U32 masklen; /* Length of event mask */
U32 old_cp_recv_mask; /* Masks before write event */
U32 old_cp_send_mask; /* mask command */
#endif /*FEATURE_SYSTEM_CONSOLE*/
#ifdef FEATURE_EXPANDED_STORAGE
SCCB_XST_MAP *sccbxmap; /* Xstore usability map */
U32 xstincnum; /* Number of expanded storage
increments */
U32 xstblkinc; /* Number of expanded storage
blocks per increment */
BYTE *xstmap; /* Xstore bitmap, zero means
available */
#endif /*FEATURE_EXPANDED_STORAGE*/
RRE(inst, regs, r1, r2);
PRIV_CHECK(regs);
SIE_INTERCEPT(regs);
PTT_INF("SERVC",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
/* R1 is SCLP command word */
sclp_command = regs->GR_L(r1);
/* R2 is real address of service call control block */
sccb_real_addr = regs->GR_L(r2);
/* Obtain the absolute address of the SCCB */
sccb_absolute_addr = APPLY_PREFIXING(sccb_real_addr, regs->PX);
/* Program check if SCCB is not on a doubleword boundary */
if ( sccb_absolute_addr & 0x00000007 )
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
/* Program check if SCCB is outside main storage */
if ( sccb_absolute_addr > regs->mainlim )
ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
/* Point to service call control block */
sccb = (SCCB_HEADER*)(regs->mainstor + sccb_absolute_addr);
/* Load SCCB length from header */
FETCH_HW(sccblen, sccb->length);
/* Set the main storage reference bit */
STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_REF;
/* Program check if end of SCCB falls outside main storage */
if ( sccb_absolute_addr + sccblen > regs->mainlim + 1)
ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);
/* Obtain lock if immediate response is not requested */
if (!(sccb->flag & SCCB_FLAG_SYNC)
|| (sclp_command & SCLP_COMMAND_CLASS) == 0x01)
{
/* Obtain the interrupt lock */
OBTAIN_INTLOCK(regs);
/* If a service signal is pending then return condition
code 2 to indicate that service processor is busy */
if (IS_IC_SERVSIG && (sysblk.servparm & SERVSIG_ADDR))
{
RELEASE_INTLOCK(regs);
regs->psw.cc = 2;
return;
}
}
/* Test SCLP command word */
switch (sclp_command & SCLP_COMMAND_MASK) {
case SCLP_READ_IFL_INFO:
/* READ_IFL_INFO is only valid for processor type IFL */
if(sysblk.ptyp[regs->cpuad] != SCCB_PTYP_IFL)
goto invalidcmd;
else
goto read_scpinfo;
case SCLP_READ_SCP_INFO:
/* READ_SCP_INFO is only valid for processor type CP */
if(sysblk.ptyp[regs->cpuad] != SCCB_PTYP_CP)
{
#ifdef OPTION_MSGCLR
WRCMSG("<pnl,color(lightred,black)>", HHC00005, "W");
#else
WRMSG(HHC00005, "W");
#endif
goto docheckstop;
/*
* Replace the following 2 lines with
* goto invalidcmd
* if this behavior is not satisfactory
* ISW 20081221
*/
}
read_scpinfo:
/* Set the main storage change bit */
STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE;
/* Set response code X'0100' if SCCB crosses a page boundary */
if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) !=
((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK))
{
sccb->reas = SCCB_REAS_NOT_PGBNDRY;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Set response code X'0300' if SCCB length
is insufficient to contain SCP info */
if ( sccblen < sizeof(SCCB_HEADER) + sizeof(SCCB_SCP_INFO)
+ (sizeof(SCCB_CPU_INFO) * sysblk.maxcpu))
{
sccb->reas = SCCB_REAS_TOO_SHORT;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Point to SCCB data area following SCCB header */
sccbscp = (SCCB_SCP_INFO*)(sccb+1);
memset (sccbscp, 0, sizeof(SCCB_SCP_INFO));
/* Set main storage size in SCCB */
realmb = sysblk.mainsize >> 20;
STORE_HW(sccbscp->realinum, realmb);
sccbscp->realiszm = 1;
sccbscp->realbszk = 4;
STORE_HW(sccbscp->realiint, 1);
#if defined(_900) || defined(FEATURE_ESAME)
/* SIE supports the full address range */
sccbscp->maxvm = 0;
/* realiszm is valid */
STORE_FW(sccbscp->grzm, 0);
/* Number of storage increments installed in esame mode */
STORE_DW(sccbscp->grnmx, realmb);
#endif /*defined(_900) || defined(FEATURE_ESAME)*/
#ifdef FEATURE_EXPANDED_STORAGE
/* Set expanded storage size in SCCB */
xstincnum = sysblk.xpndsize /
(XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT);
STORE_FW(sccbscp->xpndinum, xstincnum);
xstblkinc = XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT;
STORE_FW(sccbscp->xpndsz4K, xstblkinc);
#endif /*FEATURE_EXPANDED_STORAGE*/
#ifdef FEATURE_VECTOR_FACILITY
/* Set the Vector section size in the SCCB */
STORE_HW(sccbscp->vectssiz, VECTOR_SECTION_SIZE);
/* Set the Vector partial sum number in the SCCB */
STORE_HW(sccbscp->vectpsum, VECTOR_PARTIAL_SUM_NUMBER);
#endif /*FEATURE_VECTOR_FACILITY*/
/* Set CPU array count and offset in SCCB */
STORE_HW(sccbscp->numcpu, sysblk.maxcpu);
offset = sizeof(SCCB_HEADER) + sizeof(SCCB_SCP_INFO);
STORE_HW(sccbscp->offcpu, offset);
#if defined(FEATURE_MPF_INFO)
/* Set MPF array count and offset in SCCB */
STORE_HW(sccbscp->nummpf, sysblk.maxcpu-1);
#endif /*defined(FEATURE_MPF_INFO)*/
offset += (U16)sizeof(SCCB_CPU_INFO) * sysblk.maxcpu;
STORE_HW(sccbscp->offmpf, offset);
/* Set HSA array count and offset in SCCB */
STORE_HW(sccbscp->numhsa, 0);
#if defined(FEATURE_MPF_INFO)
offset += (U16)sizeof(SCCB_MPF_INFO) * sysblk.maxcpu-1;
#endif /*defined(FEATURE_MPF_INFO)*/
STORE_HW(sccbscp->offhsa, offset);
/* Build the MPF information array after the CPU info */
/* Move IPL load parameter to SCCB */
get_loadparm (sccbscp->loadparm);
/* Set installed features bit mask in SCCB */
memcpy(sccbscp->ifm, ARCH_DEP(scpinfo_ifm), sizeof(sccbscp->ifm));
memcpy(sccbscp->cfg, ARCH_DEP(scpinfo_cfg), sizeof(sccbscp->cfg));
/* sccbscp->cfg11 = ARCH_DEP(scpinfo_cfg11); */
if( 0
#if defined(_FEATURE_HYPERVISOR)
|| FACILITY_ENABLED(LOGICAL_PARTITION,regs)
#endif /*defined(_FEATURE_HYPERVISOR)*/
#if defined(_FEATURE_EMULATE_VM)
|| FACILITY_ENABLED(VIRTUAL_MACHINE,regs)
#endif /*defined(_FEATURE_EMULATE_VM)*/
)
sccbscp->cfg[0] |= SCCB_CFG0_LOGICALLY_PARTITIONED;
#if defined(_900) || defined(FEATURE_ESAME)
if(FACILITY_ENABLED(ESAME_INSTALLED,regs))
sccbscp->cfg[5] |= SCCB_CFG5_ESAME;
#endif /*defined(_900) || defined(FEATURE_ESAME)*/
;
/* Build the CPU information array after the SCP info */
sccbcpu = (SCCB_CPU_INFO*)(sccbscp+1);
for (i = 0; i < sysblk.maxcpu; i++, sccbcpu++)
{
memset (sccbcpu, 0, sizeof(SCCB_CPU_INFO));
sccbcpu->cpa = i;
sccbcpu->tod = 0;
memcpy(sccbcpu->cpf, ARCH_DEP(scpinfo_cpf), sizeof(sccbcpu->cpf));
sccbcpu->ptyp = sysblk.ptyp[i];
#if defined(FEATURE_CRYPTO)
// sccbcpu->ksid = SCCB_KSID_CRYPTO_UNIT_ID;
#endif /*defined(FEATURE_CRYPTO)*/
#ifdef FEATURE_VECTOR_FACILITY
if(IS_CPU_ONLINE(i) && sysblk.regs[i]->vf->online)
sccbcpu->cpf[2] |= SCCB_CPF2_VECTOR_FEATURE_INSTALLED;
if(IS_CPU_ONLINE(i) && sysblk.regs[i]->vf->online)
sccbcpu->cpf[2] |= SCCB_CPF2_VECTOR_FEATURE_CONNECTED;
if(!IS_CPU_ONLINE(i))
sccbcpu->cpf[2] |= SCCB_CPF2_VECTOR_FEATURE_STANDBY_STATE;
#endif /*FEATURE_VECTOR_FACILITY*/
}
#if defined(FEATURE_MPF_INFO)
/* Define machine capacity */
STORE_FW(sccbscp->rcci, 10000);
/* Fill in the MP Factors array */
sccbmpf = (SCCB_MPF_INFO*)(sccbcpu);
get_mpfactors((BYTE*)sccbmpf);
#endif /*defined(FEATURE_MPF_INFO)*/
/* Set response code X'0010' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_INFO;
break;
docheckstop:
ARCH_DEP(checkstop_config)();
RELEASE_INTLOCK(regs);
longjmp(regs->progjmp,SIE_NO_INTERCEPT);
UNREACHABLE_CODE();
case SCLP_READ_CHP_INFO:
/* Set the main storage change bit */
STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE;
/* Set response code X'0100' if SCCB crosses a page boundary */
if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) !=
((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK))
{
sccb->reas = SCCB_REAS_NOT_PGBNDRY;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Set response code X'0300' if SCCB length
is insufficient to contain channel path info */
if ( sccblen < sizeof(SCCB_HEADER) + sizeof(SCCB_CHP_INFO))
{
sccb->reas = SCCB_REAS_TOO_SHORT;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
#ifdef FEATURE_S370_CHANNEL
/* Point to SCCB data area following SCCB header */
sccbchp = (SCCB_CHSET_INFO*)(sccb+1);
memset (sccbchp, 0, sizeof(SCCB_CHSET_INFO));
#else
/* Point to SCCB data area following SCCB header */
sccbchp = (SCCB_CHP_INFO*)(sccb+1);
memset (sccbchp, 0, sizeof(SCCB_CHP_INFO));
#endif
#ifdef FEATURE_CHANNEL_SUBSYSTEM
/* Identify CHPIDs installed, standby, and online */
for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
{
for (i = 0; i < 8; i++)
{
chpbyte = dev->pmcw.chpid[i] / 8;
chpbit = dev->pmcw.chpid[i] % 8;
if( ((0x80 >> i) & dev->pmcw.pim))
{
sccbchp->installed[chpbyte] |= 0x80 >> chpbit;
if (dev->pmcw.flag5 & PMCW5_V)
sccbchp->online[chpbyte] |= 0x80 >> chpbit;
else
sccbchp->standby[chpbyte] |= 0x80 >> chpbit;
}
}
}
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/
#ifdef FEATURE_S370_CHANNEL
/* For S/370, initialize identifiers for channel set 0A */
for (i = 0; i < 16; i++)
{
sccbchp->chanset0a[2*i] = 0x80;
sccbchp->chanset0a[2*i+1] = i;
} /* end for(i) */
/* Set the channel set configuration byte */
sccbchp->csconfig = 0xC0;
#endif /*FEATURE_S370_CHANNEL*/
/* Set response code X'0010' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_INFO;
break;
case SCLP_READ_CSI_INFO:
/* Set the main storage change bit */
STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE;
/* Set response code X'0100' if SCCB crosses a page boundary */
if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) !=
((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK))
{
sccb->reas = SCCB_REAS_NOT_PGBNDRY;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Set response code X'0300' if SCCB length
is insufficient to contain channel path info */
if ( sccblen < sizeof(SCCB_HEADER) + sizeof(SCCB_CSI_INFO))
{
sccb->reas = SCCB_REAS_TOO_SHORT;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Point to SCCB data area following SCCB header */
sccbcsi = (SCCB_CSI_INFO*)(sccb+1);
memset (sccbcsi, 0, sizeof(SCCB_CSI_INFO));
sccbcsi->csif[0] = 0
#if defined(FEATURE_CANCEL_IO_FACILITY)
| SCCB_CSI0_CANCEL_IO_REQUEST_FACILITY
#endif /*defined(FEATURE_CANCEL_IO_FACILITY)*/
| SCCB_CSI0_CONCURRENT_SENSE_FACILITY
;
/* Set response code X'0010' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_INFO;
break;
#ifdef FEATURE_SYSTEM_CONSOLE
case SCLP_WRITE_EVENT_DATA:
/* Set the main storage change bit */
STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE;
/* Set response code X'0100' if SCCB crosses a page boundary */
if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) !=
((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK))
{
sccb->reas = SCCB_REAS_NOT_PGBNDRY;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Point to SCCB data area following SCCB header */
evd_hdr = (SCCB_EVD_HDR*)(sccb+1);
FETCH_HW(evd_len,evd_hdr->totlen);
switch(evd_hdr->type) {
case SCCB_EVD_TYPE_MSG:
case SCCB_EVD_TYPE_PRIOR:
/* Point to the Message Control Data Block */
mcd_bk = (SCCB_MCD_BK*)(evd_hdr+1);
FETCH_HW(mcd_len,mcd_bk->length);
obj_hdr = (SCCB_OBJ_HDR*)(mcd_bk+1);
while (mcd_len > sizeof(SCCB_MCD_BK))
{
FETCH_HW(obj_len,obj_hdr->length);
if (obj_len == 0)
{
sccb->reas = SCCB_REAS_BUFF_LEN_ERR;
sccb->resp = SCCB_RESP_BUFF_LEN_ERR;
break;
}
FETCH_HW(obj_type,obj_hdr->type);
if (obj_type == SCCB_OBJ_TYPE_MESSAGE)
{
mto_bk = (SCCB_MTO_BK*)(obj_hdr+1);
event_msg = (BYTE*)(mto_bk+1);
event_msglen = obj_len -
(sizeof(SCCB_OBJ_HDR) + sizeof(SCCB_MTO_BK));
if (event_msglen < 0)
{
sccb->reas = SCCB_REAS_BUFF_LEN_ERR;
sccb->resp = SCCB_RESP_BUFF_LEN_ERR;
break;
}
/* Print line unless it is a response prompt */
if (!(mto_bk->ltflag[0] & SCCB_MTO_LTFLG0_PROMPT))
{
for (i = 0; i < event_msglen; i++)
{
message[i] = isprint(guest_to_host(event_msg[i])) ?
guest_to_host(event_msg[i]) : 0x20;
}
message[i] = '\0';
#ifdef OPTION_MSGCLR
if(evd_hdr->type == SCCB_EVD_TYPE_MSG)
{
if(mto_bk->presattr[3] == SCCB_MTO_PRATTR3_HIGH)
#ifdef OPTION_SCP_MSG_PREFIX
WRCMSG("<pnl,color(lightyellow,black),keep>", HHC00001, "I", message);
else
WRCMSG("<pnl,color(green,black)>", HHC00001, "I", message);
}
else
WRCMSG("<pnl,color(lightred,black),keep>", HHC00001, "I", message);
#else
logmsg("<pnl,color(lightyellow,black),keep>%s\n", message);
else
logmsg("<pnl,color(green,black)>%s\n", message);
}
else
logmsg("<pnl,color(lightred,black),keep>%s\n", message);
#endif /* OPTION_SCP_MSG_PREFIX */
#else
#ifdef OPTION_SCP_MSG_PREFIX
WRMSG(HHC00001, "I", message);
#else
logmsg("%s\n",message);
#endif /* OPTION_SCP_MSG_PREFIX */
#endif
}
}
mcd_len -= obj_len;
obj_hdr=(SCCB_OBJ_HDR *)((BYTE*)obj_hdr + obj_len);
}
/* Indicate Event Processed */
evd_hdr->flag |= SCCB_EVD_FLAG_PROC;
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
break;
case SCCB_EVD_TYPE_CPIDENT:
sclp_cpident(sccb);
break;
#if defined(FEATURE_SCEDIO)
case SCCB_EVD_TYPE_SCEDIO:
ARCH_DEP(sclp_scedio_request)(sccb);
break;
#endif /*defined(FEATURE_SCEDIO)*/
#if defined(_FEATURE_HARDWARE_LOADER)
case SCCB_EVD_TYPE_HWL:
ARCH_DEP(sclp_hwl_request)(sccb);
break;
case SCCB_EVD_TYPE_SDIAS:
ARCH_DEP(sclp_sdias_request)(sccb);
break;
#endif /*defined(_FEATURE_HARDWARE_LOADER)*/
#if defined(FEATURE_INTEGRATED_3270_CONSOLE)
case SCCB_EVD_TYPE_SYSG:
sclp_sysg_write(sccb);
break;
#endif /*defined(FEATURE_INTEGRATED_3270_CONSOLE)*/
#if defined(FEATURE_INTEGRATED_ASCII_CONSOLE)
case SCCB_EVD_TYPE_VT220:
sclp_sysa_write(sccb);
break;
#endif /*defined(FEATURE_INTEGRATED_ASCII_CONSOLE)*/
default:
PTT_ERR("*SERVC",regs->GR_L(r1),regs->GR_L(r2),evd_hdr->type);
if( HDC3(debug_sclp_unknown_event, evd_hdr, sccb, regs) )
break;
/* Set response code X'73F0' in SCCB header */
sccb->reas = SCCB_REAS_SYNTAX_ERROR;
sccb->resp = SCCB_RESP_SYNTAX_ERROR;
break;
}
break;
case SCLP_READ_EVENT_DATA:
/* Set the main storage change bit */
STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE;
/* Set response code X'0100' if SCCB crosses a page boundary */
if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) !=
((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK))
{
sccb->reas = SCCB_REAS_NOT_PGBNDRY;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Point to SCCB data area following SCCB header */
evd_hdr = (SCCB_EVD_HDR*)(sccb+1);
if(SCLP_RECV_ENABLED(PRIOR) && sclp_attn_pending(SCCB_EVD_TYPE_PRIOR))
{
sclp_opcmd_event(sccb, SCCB_EVD_TYPE_PRIOR);
break;
}
if(SCLP_RECV_ENABLED(OPCMD) && sclp_attn_pending(SCCB_EVD_TYPE_OPCMD))
{
sclp_opcmd_event(sccb, SCCB_EVD_TYPE_OPCMD);
break;
}
#if defined(FEATURE_SCEDIO)
if(SCLP_RECV_ENABLED(SCEDIO) && sclp_attn_pending(SCCB_EVD_TYPE_SCEDIO))
{
ARCH_DEP(sclp_scedio_event)(sccb);
break;
}
#endif /*defined(FEATURE_SCEDIO)*/
#if defined(_FEATURE_HARDWARE_LOADER)
if(SCLP_RECV_ENABLED(HWL) && sclp_attn_pending(SCCB_EVD_TYPE_HWL))
{
ARCH_DEP(sclp_hwl_event)(sccb);
break;
}
if(SCLP_RECV_ENABLED(SDIAS) && sclp_attn_pending(SCCB_EVD_TYPE_SDIAS))
{
ARCH_DEP(sclp_sdias_event)(sccb);
break;
}
#endif /*defined(_FEATURE_HARDWARE_LOADER)*/
#if defined(FEATURE_INTEGRATED_3270_CONSOLE)
if(SCLP_RECV_ENABLED(SYSG) && sclp_attn_pending(SCCB_EVD_TYPE_SYSG))
{
sclp_sysg_poll(sccb);
break;
}
#endif /*defined(FEATURE_INTEGRATED_3270_CONSOLE)*/
#if defined(FEATURE_INTEGRATED_ASCII_CONSOLE)
if(SCLP_RECV_ENABLED(VT220) && sclp_attn_pending(SCCB_EVD_TYPE_VT220))
{
sclp_sysa_poll(sccb);
break;
}
#endif /*defined(FEATURE_INTEGRATED_ASCII_CONSOLE)*/
if(SCLP_RECV_ENABLED(SIGQ) && sclp_attn_pending(SCCB_EVD_TYPE_SIGQ))
{
sclp_sigq_event(sccb);
break;
}
PTT_ERR("*SERVC",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
if( HDC3(debug_sclp_event_data, evd_hdr, sccb, regs) )
break;
/* Set response code X'62F0' if events are pending but suppressed */
if(sclp_attn_pending(0))
{
sccb->reas = SCCB_REAS_EVENTS_SUP;
sccb->resp = SCCB_RESP_EVENTS_SUP;
break;
}
else
{
/* Set response code X'60F0' if no outstanding events */
sccb->reas = SCCB_REAS_NO_EVENTS;
sccb->resp = SCCB_RESP_NO_EVENTS;
}
break;
case SCLP_WRITE_EVENT_MASK:
/* Set the main storage change bit */
STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE;
/* Set response code X'0100' if SCCB crosses a page boundary */
if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) !=
((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK))
{
sccb->reas = SCCB_REAS_NOT_PGBNDRY;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Point to SCCB data area following SCCB header */
evd_mask = (SCCB_EVENT_MASK*)(sccb+1);
/* Get length of single mask field */
FETCH_HW(masklen, evd_mask->length);
/* Save old mask settings in order to suppress superflous messages */
old_cp_recv_mask = servc_cp_recv_mask & ARCH_DEP(sclp_send_mask) & SCCB_EVENT_CONS_RECV_MASK;
old_cp_send_mask = servc_cp_send_mask & ARCH_DEP(sclp_recv_mask) & SCCB_EVENT_CONS_SEND_MASK;
for (i = 0; i < 4; i++)
{
servc_cp_recv_mask <<= 8;
servc_cp_send_mask <<= 8;
if ((U32)i < masklen)
{
servc_cp_recv_mask |= evd_mask->masks[i+(0*masklen)];
servc_cp_send_mask |= evd_mask->masks[i+(1*masklen)];
}
}
if((servc_cp_recv_mask & ~ARCH_DEP(sclp_recv_mask))
|| (servc_cp_send_mask & ~ARCH_DEP(sclp_send_mask)))
HDC3(debug_sclp_unknown_event_mask, evd_mask, sccb, regs);
/* Write the events that we support back */
memset (&evd_mask->masks[2 * masklen], 0, 2 * masklen);
for (i = 0; (i < 4) && ((U32)i < masklen); i++)
{
evd_mask->masks[i+(2*masklen)] |= (ARCH_DEP(sclp_recv_mask) >> ((3-i)*8)) & 0xFF;
evd_mask->masks[i+(3*masklen)] |= (ARCH_DEP(sclp_send_mask) >> ((3-i)*8)) & 0xFF;
}
/* Issue message only when supported mask has changed */
if ((servc_cp_recv_mask & ARCH_DEP(sclp_send_mask) & SCCB_EVENT_CONS_RECV_MASK) != old_cp_recv_mask
|| (servc_cp_send_mask & ARCH_DEP(sclp_recv_mask) & SCCB_EVENT_CONS_SEND_MASK) != old_cp_send_mask)
{
if ((servc_cp_recv_mask & SCCB_EVENT_CONS_RECV_MASK) != 0
|| (servc_cp_send_mask & SCCB_EVENT_CONS_SEND_MASK) != 0)
WRMSG (HHC00006, "I", "active");
else
WRMSG (HHC00006, "I", "inactive");
}
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
break;
#endif /*FEATURE_SYSTEM_CONSOLE*/
#ifdef FEATURE_EXPANDED_STORAGE
case SCLP_READ_XST_MAP:
/* Set the main storage change bit */
STORAGE_KEY(sccb_absolute_addr, regs) |= STORKEY_CHANGE;
/* Set response code X'0100' if SCCB crosses a page boundary */
if ((sccb_absolute_addr & STORAGE_KEY_PAGEMASK) !=
((sccb_absolute_addr + sccblen - 1) & STORAGE_KEY_PAGEMASK))
{
sccb->reas = SCCB_REAS_NOT_PGBNDRY;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Calculate number of blocks per increment */
xstblkinc = XSTORE_INCREMENT_SIZE / XSTORE_PAGESIZE;
/* Set response code X'0300' if SCCB length
is insufficient to contain xstore info */
if ( sccblen < sizeof(SCCB_HEADER) + sizeof(SCCB_XST_MAP)
+ xstblkinc/8)
{
sccb->reas = SCCB_REAS_TOO_SHORT;
sccb->resp = SCCB_RESP_BLOCK_ERROR;
break;
}
/* Point to SCCB data area following SCCB header */
sccbxmap = (SCCB_XST_MAP*)(sccb+1);
/* Verify expanded storage increment number */
xstincnum = sysblk.xpndsize /
(XSTORE_INCREMENT_SIZE >> XSTORE_PAGESHIFT);
FETCH_FW(i, sccbxmap->incnum);
if ( i < 1 || (U32)i > xstincnum )
{
sccb->reas = SCCB_REAS_INVALID_RSC;
sccb->resp = SCCB_RESP_REJECT;
break;
}
/* Point to bitmap */
xstmap = (BYTE*)(sccbxmap+1);
/* Set all blocks available */
memset (xstmap, 0, xstblkinc/8);
/* Set response code X'0010' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_INFO;
break;
#endif /*FEATURE_EXPANDED_STORAGE*/
#ifdef FEATURE_CPU_RECONFIG
case SCLP_CONFIGURE_CPU:
i = (sclp_command & SCLP_RESOURCE_MASK) >> SCLP_RESOURCE_SHIFT;
/* Return invalid resource in parm if target does not exist */
if(i >= sysblk.maxcpu)
{
sccb->reas = SCCB_REAS_INVALID_RSCP;
sccb->resp = SCCB_RESP_REJECT;
break;
}
/* Add cpu to the configuration */
configure_cpu(i);
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
break;
case SCLP_DECONFIGURE_CPU:
i = (sclp_command & SCLP_RESOURCE_MASK) >> SCLP_RESOURCE_SHIFT;
/* Return invalid resource in parm if target does not exist */
if(i >= sysblk.maxcpu)
{
sccb->reas = SCCB_REAS_INVALID_RSCP;
sccb->resp = SCCB_RESP_REJECT;
break;
}
/* Take cpu out of the configuration */
deconfigure_cpu(i);
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
break;
#ifdef FEATURE_VECTOR_FACILITY
case SCLP_DISCONNECT_VF:
i = (sclp_command & SCLP_RESOURCE_MASK) >> SCLP_RESOURCE_SHIFT;
/* Return invalid resource in parm if target does not exist */
if(i >= sysblk.maxcpu || !IS_CPU_ONLINE(i))
{
sccb->reas = SCCB_REAS_INVALID_RSCP;
sccb->resp = SCCB_RESP_REJECT;
break;
}
if(sysblk.regs[i]->vf->online)
WRMSG(HHC00821, "I", PTYPSTR(i), i, "offline" );
/* Take the VF out of the configuration */
sysblk.regs[i]->vf->online = 0;
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
break;
case SCLP_CONNECT_VF:
i = (sclp_command & SCLP_RESOURCE_MASK) >> SCLP_RESOURCE_SHIFT;
/* Return invalid resource in parm if target does not exist */
if(i >= sysblk.maxcpu)
{
sccb->reas = SCCB_REAS_INVALID_RSCP;
sccb->resp = SCCB_RESP_REJECT;
break;
}
/* Return improper state if associated cpu is offline */
if(!IS_CPU_ONLINE(i))
{
sccb->reas = SCCB_REAS_IMPROPER_RSC;
sccb->resp = SCCB_RESP_REJECT;
break;
}
if(!sysblk.regs[i]->vf->online)
WRMSG(HHC00821, "I", PTYPSTR(i), i, "online" );
/* Mark the VF online to the CPU */
sysblk.regs[i]->vf->online = 1;
/* Set response code X'0020' in SCCB header */
sccb->reas = SCCB_REAS_NONE;
sccb->resp = SCCB_RESP_COMPLETE;
break;
#endif /*FEATURE_VECTOR_FACILITY*/
#endif /*FEATURE_CPU_RECONFIG*/
default:
invalidcmd:
PTT(PTT_CL_INF|PTT_CL_ERR,"*SERVC",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
if( HDC3(debug_sclp_unknown_command, sclp_command, sccb, regs) )
break;
/* Set response code X'01F0' for invalid SCLP command */
sccb->reas = SCCB_REAS_INVALID_CMD;
sccb->resp = SCCB_RESP_REJECT;
break;
} /* end switch(sclp_command) */
/* If immediate response is requested, return condition code 1 */
if ((sccb->flag & SCCB_FLAG_SYNC)
&& (sclp_command & SCLP_COMMAND_CLASS) != 0x01)
{
regs->psw.cc = 1;
return;
}
/* Set service signal external interrupt pending */
sysblk.servparm &= ~SERVSIG_ADDR;
sysblk.servparm |= sccb_absolute_addr;
ON_IC_SERVSIG;
/* Release the interrupt lock */
RELEASE_INTLOCK(regs);
/* Set condition code 0 */
regs->psw.cc = 0;
RETURN_INTCHECK(regs);
} /* end function service_call */
#endif /*defined(FEATURE_SERVICE_PROCESSOR)*/
#if !defined(_GEN_ARCH)
#if defined(_ARCHMODE2)
#define _GEN_ARCH _ARCHMODE2
#include "service.c"
#endif
#if defined(_ARCHMODE3)
#undef _GEN_ARCH
#define _GEN_ARCH _ARCHMODE3
#include "service.c"
#endif
#endif /*!defined(_GEN_ARCH)*/