/* 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); 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) ); if((dev = find_device_by_subchan(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)*/