Files
org-hyperion-cules/qdio.c
Jan Jaeger ef664c68e8 Add QDR struct
git-svn-id: file:///home/jj/hercules.svn/trunk@7214 956126f8-22a0-4046-8f4a-272fa8102e63
2010-12-27 15:16:21 +00:00

141 lines
3.3 KiB
C

/* QDIO.C (c) Copyright Jan Jaeger, 2003-2010 */
/* Queued Direct Input Output */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
// $Id$
/* This module contains the Signal Adapter instruction */
#include "hstdinc.h"
#if !defined(_HENGINE_DLL_)
#define _HENGINE_DLL_
#endif
#if !defined(_QDIO_C_)
#define _QDIO_C_
#endif
#include "hercules.h"
#include "opcode.h"
#include "inline.h"
#undef PTIO
#define PTIO(_class, _name) \
PTT(PTT_CL_ ## _class,_name,regs->GR_L(1),(U32)(effective_addr2 & 0xffffffff),regs->psw.IA_L)
#if defined(FEATURE_QUEUED_DIRECT_IO)
/*-------------------------------------------------------------------*/
/* B274 SIGA - Signal Adapter [S] */
/*-------------------------------------------------------------------*/
DEF_INST(signal_adapter)
{
int b2;
RADR effective_addr2;
DEVBLK *dev; /* -> device block */
S(inst, regs, b2, effective_addr2);
PRIV_CHECK(regs);
SIE_INTERCEPT(regs);
PTIO(IO,"SIGA");
/* Specification exception if invalid function code */
if(regs->GR_L(0) > SIGA_FC_MAX)
ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);
/* Program check if the ssid including lcss is invalid */
SSID_CHECK(regs);
/* Locate the device block for this subchannel */
dev = find_device_by_subchan (regs->GR_L(1));
/* Condition code 3 if subchannel does not exist,
is not valid, or is not enabled or is not a QDIO subchannel */
if (dev == NULL
|| (dev->pmcw.flag5 & PMCW5_V) == 0
|| (dev->pmcw.flag5 & PMCW5_E) == 0
|| (dev->pmcw.flag4 & PMCW4_Q) == 0)
{
PTIO(ERR,"*SIGA");
#if defined(_FEATURE_QUEUED_DIRECT_IO_ASSIST)
SIE_INTERCEPT(regs);
#endif
regs->psw.cc = 3;
return;
}
/* Obtain the device lock */
obtain_lock (&dev->lock);
/* Check that device is QDIO active */
if ((dev->scsw.flag2 & SCSW2_Q) == 0)
{
PTIO(ERR,"*SIGA");
release_lock (&dev->lock);
regs->psw.cc = 1;
return;
}
switch(regs->GR_L(0)) {
case SIGA_FC_R:
if(dev->hnd->siga_r)
regs->psw.cc = (dev->hnd->siga_r) (dev, regs->GR_L(2) );
else
{
PTIO(ERR,"*SIGA");
regs->psw.cc = 3;
}
break;
case SIGA_FC_W:
if(dev->hnd->siga_w)
regs->psw.cc = (dev->hnd->siga_w) (dev, regs->GR_L(2) );
else
{
PTIO(ERR,"*SIGA");
regs->psw.cc = 3;
}
break;
case SIGA_FC_S:
/* No signalling required for sync requests as we emulate
a real machine */
regs->psw.cc = 0;
break;
default:
PTIO(ERR,"*SIGA");
}
release_lock (&dev->lock);
}
#endif /*defined(FEATURE_QUEUED_DIRECT_IO)*/
#if !defined(_GEN_ARCH)
#if defined(_ARCHMODE2)
#define _GEN_ARCH _ARCHMODE2
#include "qdio.c"
#endif
#if defined(_ARCHMODE3)
#undef _GEN_ARCH
#define _GEN_ARCH _ARCHMODE3
#include "qdio.c"
#endif
#endif /*!defined(_GEN_ARCH)*/