Files
org-hyperion-cules/chsc.c
Jan Jaeger 14f8697c1f Add Logical Channel Subsystem (LCSS) support
git-svn-id: file:///home/jj/hercules.svn/trunk@3697 956126f8-22a0-4046-8f4a-272fa8102e63
2006-02-25 21:56:58 +00:00

251 lines
7.1 KiB
C

/* CHSC.C (c) Copyright Jan Jaeger, 2002-2006 */
/* Channel Subsystem Call */
/* Interpretive Execution - (c) Copyright Jan Jaeger, 1999-2006 */
/* z/Architecture support - (c) Copyright Jan Jaeger, 1999-2006 */
/*-------------------------------------------------------------------*/
/* This module implements channel subsystem interface functions */
/* for the Hercules ESA/390 emulator. */
/*-------------------------------------------------------------------*/
#include "hstdinc.h"
#if !defined(_HENGINE_DLL_)
#define _HENGINE_DLL_
#endif
#if !defined(_CHSC_C_)
#define _CHSC_C_
#endif
#include "hercules.h"
#include "opcode.h"
#include "inline.h"
#include "chsc.h"
#if defined(FEATURE_CHSC)
int ARCH_DEP(chsc_get_sch_desc) (CHSC_REQ *chsc_req, CHSC_RSP *chsc_rsp)
{
U16 req_len, sch, f_sch, l_sch, rsp_len;
CHSC_REQ4 *chsc_req4 = (CHSC_REQ4 *)(chsc_req);
CHSC_RSP4 *chsc_rsp4 = (CHSC_RSP4 *)(chsc_rsp);
#if 0
{ U16 resv1, resv2, resv3;
FETCH_HW(resv1,chsc_req4->resv1);
FETCH_HW(resv2,chsc_req4->resv2);
FETCH_HW(resv3,chsc_req4->resv3);
logmsg(D_("chsc_get_sch_desc: resv1=%4.4X resv2=%4.4X resv3=%4.4X\n"),resv1,resv2,resv3);
}
#endif
FETCH_HW(f_sch,chsc_req4->f_sch);
FETCH_HW(l_sch,chsc_req4->l_sch);
/* Fetch length of request field */
FETCH_HW(req_len, chsc_req4->length);
rsp_len = sizeof(CHSC_RSP) + ((1 + l_sch - f_sch) * sizeof(CHSC_RSP4));
if(l_sch < f_sch
|| rsp_len > (0x1000 - req_len)) {
/* Set response field length */
STORE_HW(chsc_rsp->length,sizeof(CHSC_RSP));
/* Store request error */
STORE_HW(chsc_rsp->rsp,CHSC_REQ_ERRREQ);
/* No reaon code */
STORE_FW(chsc_rsp->info,0);
return 0;
}
for(sch = f_sch; sch <= l_sch; sch++, chsc_rsp4++)
{
DEVBLK *dev;
memset(chsc_rsp4, 0x00, sizeof(CHSC_RSP4) );
// ZZ FIXME: Dunno how to put the proper lcss id in here...
if((dev = find_device_by_subchan(0x00010000|sch)))
{
chsc_rsp4->sch_val = 1;
if(dev->pmcw.flag5 & PMCW5_V)
chsc_rsp4->dev_val = 1;
chsc_rsp4->st = (dev->pmcw.flag25 & PMCW25_TYPE) >> 5;
chsc_rsp4->unit_addr = dev->devnum & 0xff;
STORE_HW(chsc_rsp4->devno,dev->devnum);
chsc_rsp4->path_mask = dev->pmcw.pim;
STORE_HW(chsc_rsp4->sch, sch);
memcpy(chsc_rsp4->chpid, dev->pmcw.chpid, 8);
}
}
/* Store response length */
STORE_HW(chsc_rsp->length,rsp_len);
/* Store request OK */
STORE_HW(chsc_rsp->rsp,CHSC_REQ_OK);
/* No reaon code */
STORE_FW(chsc_rsp->info,0);
return 0;
}
int ARCH_DEP(chsc_get_css_info) (CHSC_REQ *chsc_req, CHSC_RSP *chsc_rsp)
{
CHSC_RSP10 *chsc_rsp10;
U16 req_len, rsp_len;
UNREFERENCED(chsc_req);
chsc_rsp10 = (CHSC_RSP10 *)(chsc_rsp + 1);
/* Fetch length of request field */
FETCH_HW(req_len, chsc_req->length);
rsp_len = sizeof(CHSC_RSP) + sizeof(CHSC_RSP10);
if(rsp_len > (0x1000 - req_len)) {
/* Set response field length */
STORE_HW(chsc_rsp->length,sizeof(CHSC_RSP));
/* Store request error */
STORE_HW(chsc_rsp->rsp,CHSC_REQ_ERRREQ);
/* No reaon code */
STORE_FW(chsc_rsp->info,0);
return 0;
}
STORE_HW(chsc_rsp->length,rsp_len);
memset(chsc_rsp10->general_char, 0x00, sizeof(chsc_rsp10->general_char));
memset(chsc_rsp10->chsc_char, 0x00, sizeof(chsc_rsp10->chsc_char));
chsc_rsp10->general_char[0][0] = 0
#if defined(FEATURE_REGION_RELOCATE)
| 0x24
#endif
#if defined(FEATURE_CANCEL_IO_FACILITY)
| 0x02
#endif
;
#if defined(FEATURE_QUEUED_DIRECT_IO)
chsc_rsp10->general_char[1][1] = 0
| 0x40 /* Adapter Interruption Facility */
;
chsc_rsp10->chsc_char[3][1] = 0
| 0x10 /* Set Channel Subsystem Char */
| 0x08 /* Fast CHSCs */
;
chsc_rsp10->general_char[2][0] = 0
// | 0x10 /* OSA/FCP Thin interrupts */
;
chsc_rsp10->general_char[1][3] = 0
// | 0x80 /* AIF Time Delay Disablement Fac */
;
#endif /*defined(FEATURE_QUEUED_DIRECT_IO)*/
/* Store request OK */
STORE_HW(chsc_rsp->rsp,CHSC_REQ_OK);
/* No reaon code */
STORE_FW(chsc_rsp->info,0);
return 0;
}
/*-------------------------------------------------------------------*/
/* B25F CHSC - Channel Subsystem Call [RRE] */
/*-------------------------------------------------------------------*/
DEF_INST(channel_subsystem_call)
{
int r1, r2; /* register values */
VADR n; /* Unsigned work */
BYTE *mn; /* Unsigned work */
U16 req_len; /* Length of request */
U16 req; /* Request code */
CHSC_REQ *chsc_req; /* Request structure */
CHSC_RSP *chsc_rsp; /* Response structure*/
RRE(inst, regs, r1, r2);
PRIV_CHECK(regs);
SIE_INTERCEPT(regs);
n = regs->GR(r1) & ADDRESS_MAXWRAP(regs);
if(n & 0xFFF)
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
mn = MADDR(n, r1, regs, ACCTYPE_READ, regs->psw.pkey);
chsc_req = (CHSC_REQ*)(mn);
/* Fetch length of request field */
FETCH_HW(req_len, chsc_req->length);
chsc_rsp = (CHSC_RSP*)((BYTE*)chsc_req + req_len);
if((req_len < sizeof(CHSC_REQ))
|| (req_len > (0x1000 - sizeof(CHSC_RSP))))
ARCH_DEP(program_interrupt) (regs, PGM_OPERAND_EXCEPTION);
FETCH_HW(req,chsc_req->req);
ARCH_DEP(validate_operand) (n, r1, 0, ACCTYPE_WRITE, regs);
switch(req) {
case CHSC_REQ_SCHDESC:
regs->psw.cc = ARCH_DEP(chsc_get_sch_desc) (chsc_req, chsc_rsp);
break;
#if 0
case CHSC_REQ_CSSINFO:
regs->psw.cc = ARCH_DEP(chsc_get_css_info) (chsc_req, chsc_rsp);
break;
#endif
default:
if( HDC3(debug_chsc_unknown_request, chsc_rsp, chsc_req, regs) )
break;
/* Set response field length */
STORE_HW(chsc_rsp->length,sizeof(CHSC_RSP));
/* Store unsupported command code */
STORE_HW(chsc_rsp->rsp,CHSC_REQ_INVALID);
/* No reaon code */
STORE_FW(chsc_rsp->info,0);
regs->psw.cc = 0;
}
}
#endif /*defined(FEATURE_CHSC)*/
#if !defined(_GEN_ARCH)
#if defined(_ARCHMODE2)
#define _GEN_ARCH _ARCHMODE2
#include "chsc.c"
#endif
#if defined(_ARCHMODE3)
#undef _GEN_ARCH
#define _GEN_ARCH _ARCHMODE3
#include "chsc.c"
#endif
#endif /*!defined(_GEN_ARCH)*/