示例#1
0
static int ARCH_DEP(chsc_get_conf_info) (CHSC_REQ *chsc_req, CHSC_RSP *chsc_rsp)
{
U16 req_len, rsp_len;

CHSC_REQ12 *chsc_req12 = (CHSC_REQ12 *)(chsc_req);
CHSC_RSP12 *chsc_rsp12 = (CHSC_RSP12 *)(chsc_rsp+1);

    /* Fetch length of request field */
    FETCH_HW(req_len, chsc_req12->length);

    rsp_len = sizeof(CHSC_RSP) + sizeof(CHSC_RSP12);

    memset(chsc_rsp12, 0, sizeof(CHSC_RSP12) );

    STORE_HW(chsc_rsp12->len1,80);
    STORE_FW(chsc_rsp12->info1,0x10);
    STORE_FW(chsc_rsp12->info2,0x10);
    STORE_FW(chsc_rsp12->info3,0xFF);
 
    STORE_FW(chsc_rsp12->test,0xE3C5E2E3);

    /* 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;

}
示例#2
0
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);
        }
    }
示例#3
0
static 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, lcss;

CHSC_REQ4 *chsc_req4 = (CHSC_REQ4 *)(chsc_req);
CHSC_RSP4 *chsc_rsp4 = (CHSC_RSP4 *)(chsc_rsp+1);

    FETCH_HW(f_sch,chsc_req4->f_sch);
    FETCH_HW(l_sch,chsc_req4->l_sch);
    FETCH_HW(lcss,chsc_req4->ssidfmt);
    lcss &= CHSC_REQ4_SSID;
    lcss >>= 4;

    /* 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, 0, sizeof(CHSC_RSP4) );
        if((dev = find_device_by_subchan((LCSS_TO_SSID(lcss) << 16)|sch)))
        {
            int n;
            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);
            if(dev->fla[0])
                chsc_rsp4->fla_valid_mask = dev->pmcw.pim;
            for(n = 0; n < 7; n++)
                if(dev->pmcw.pim & (0x80 >> n))
                    STORE_HW(chsc_rsp4->fla[n], dev->fla[n]);
        }
    }
示例#4
0
/*-------------------------------------------------------------------*/
void get_mpfactors(BYTE *dest)
{
/*-------------------------------------------------------------------*/
/* The new z10 machine will use a denominator of 65535 for better    */
/* granularity. But this will mess up old software. We will stick    */
/* to the old value of 100. Bernard Feb 26, 2010.                    */
/*-------------------------------------------------------------------*/
#define  MPFACTOR_DENOMINATOR   100   
#define  MPFACTOR_PERCENT       95

    static U16 mpfactors[MAX_CPU_ENGINES-1] = {0};
    static BYTE didthis = 0;

    if (!didthis)
    {
        /* First time: initialize array... */
        U32 mpfactor = MPFACTOR_DENOMINATOR;
        size_t i;
        for (i=0; i < arraysize( mpfactors ); i++)
        {
            /* Calculate the value of each subsequent entry
               as percentage of the previous entry's value. */
            mpfactor = (mpfactor * MPFACTOR_PERCENT) / 100;
            STORE_HW( &mpfactors[i], (U16) mpfactor );
        }
        didthis = 1;
    }

    /* Return the requested information... */
    memcpy( dest, &mpfactors[0], (MAX_CPU-1) * sizeof(U16) );
}
示例#5
0
/*-------------------------------------------------------------------*/
void get_mpfactors(BYTE *dest)
{
/*-------------------------------------------------------------------*/
/* The new z10 machine will use a denominator of 65535 for better    */
/* granularity. But this will mess up old software. We will stick    */
/* to the old value of 100. Bernard Feb 26, 2010.                    */
/*                                                                   */
/* Calculations will be done in a higher precision to prevent early  */
/* truncation and degradation of the factors. To achieve this, the   */
/* factors are calculated * 256. When storing the values, the        */
/* individual values are rounded up by 128 and then divided by 256   */
/* for the store operation.                                          */
/*                                                                   */
/* Once the number of host logical CPUs is reached, subsequent MP    */
/* factors are no longer adjusted.                                   */
/*                                                                   */
/* MPFACTOR_DENOMINATOR must be 100, 255, or 65535.                  */
/*                                                                   */
/* It is recommended that MPFACTOR_PERCENT remain at 95 (95%).       */
/*-------------------------------------------------------------------*/
#define  MPFACTOR_DENOMINATOR     100
#define  MPFACTOR_PERCENT          95

    static U16 mpfactors[MAX_CPU_ENGINES-1] = {0};
    static BYTE didthis = 0;

    if (!didthis)
    {
        /* First time: initialize array... */
        size_t  limit = get_RealCPCount();
        size_t  i;
        U32     mpfactor = MPFACTOR_DENOMINATOR << 8;
        U16     result = 0;
        U16     resmin = 1;

        switch (MPFACTOR_DENOMINATOR)
        {
            default: /* resmin =   1; break; */
            case   100: resmin =   1; break;
            case   255: resmin = 101; break;
            case 65535: resmin = 256; break;
        }

        for (i=0; i < arraysize(mpfactors); i++)
        {
            /* Calculate the value of each subsequent entry as a
             * percentage of the previous entry's value for the real
             * defined CPU entries.
             */
            if (i < limit)
            {
                mpfactor = (mpfactor * MPFACTOR_PERCENT) / 100;
                result = (mpfactor + 128) >> 8;
                result = MAX(result, resmin);
            }
            STORE_HW( &mpfactors[i], result );
        }
示例#6
0
文件: trace.c 项目: mstram/spinhawk
/*-------------------------------------------------------------------*/
CREG ARCH_DEP(trace_br) (int amode, VADR ia, REGS *regs)
{
RADR raddr;
RADR ag;
int  size;

#if defined(FEATURE_ESAME)
    if(amode && ia > 0xFFFFFFFFULL)
    {
        TRACE_F3_BR *tte;
        size = sizeof(TRACE_F3_BR);
        raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs);
        tte = (void*)(regs->mainstor + raddr);
        tte->format = TRACE_F3_BR_FMT;
        tte->fmt2 = TRACE_F3_BR_FM2;
        STORE_HW(tte->resv,0);
        STORE_DW(tte->newia64,ia);
    }
    else
#endif /*defined(FEATURE_ESAME)*/
    if(amode)
    {
        TRACE_F2_BR *tte;
        size = sizeof(TRACE_F2_BR);
        raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs);
        tte = (void*)(regs->mainstor + raddr);
        STORE_FW(tte->newia31,ia | 0x80000000);
    }
    else
    {
        TRACE_F1_BR *tte;
        size = sizeof(TRACE_F1_BR);
        raddr = ARCH_DEP(get_trace_entry) (&ag, size, regs);
        tte = (void*)(regs->mainstor + raddr);
        STORE_FW(tte->newia24,ia & 0x00FFFFFF);
    }
    
    return ARCH_DEP(set_trace_entry) (ag, raddr, size, regs);
    
} /* end function ARCH_DEP(trace_br) */
示例#7
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(sclp_scedio_event) (SCCB_HEADER *sccb)
{
SCCB_EVD_HDR    *evd_hdr = (SCCB_EVD_HDR*)(sccb + 1);
U16 sccb_len;
U16 evd_len;

    if( ARCH_DEP(scedio_request)(SCLP_READ_EVENT_DATA, evd_hdr) )
    {
        /* Update SCCB length field if variable request */
        if (sccb->type & SCCB_TYPE_VARIABLE)
        {
            FETCH_HW(evd_len, evd_hdr->totlen);
            sccb_len = evd_len + sizeof(SCCB_HEADER);
            STORE_HW(sccb->length, sccb_len);
            sccb->type &= ~SCCB_TYPE_VARIABLE;
        }

        /* Set response code X'0020' in SCCB header */
        sccb->reas = SCCB_REAS_NONE;
        sccb->resp = SCCB_RESP_COMPLETE;
    }

}
示例#8
0
static void  CTCT_Read( DEVBLK* pDEVBLK,   U32   sCount,
                        BYTE*   pIOBuf,    BYTE* pUnitStat,
                        U32*    pResidual, BYTE* pMore )
{
    PCTCIHDR    pFrame   = NULL;       // -> Frame header
    PCTCISEG    pSegment = NULL;       // -> Segment in buffer
    fd_set      rfds;                  // Read FD_SET
    int         iRetVal;               // Return code from 'select'
    int         iLength  = 0;

    static struct timeval tv;          // Timeout time for 'select'


    // Limit how long we should wait for data to come in
    FD_ZERO( &rfds );
    FD_SET( pDEVBLK->fd, &rfds );

    tv.tv_sec  = CTC_READ_TIMEOUT_SECS;
    tv.tv_usec = 0;

    iRetVal = select( pDEVBLK->fd + 1, &rfds, NULL, NULL, &tv );

    switch( iRetVal )
    {
    case 0:
        *pUnitStat = CSW_CE | CSW_DE | CSW_UC | CSW_SM;
        pDEVBLK->sense[0] = 0;
        return;

    case -1:
        if( HSO_errno == HSO_EINTR )
            return;

        WRMSG(HHC00973, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->filename,
              strerror( HSO_errno ) );

        pDEVBLK->sense[0] = SENSE_EC;
        *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
        return;

    default:
        break;
    }

    // Read an IP packet from the TUN device
    iLength = read_socket( pDEVBLK->fd, pDEVBLK->buf, pDEVBLK->bufsize );

    // Check for other error condition
    if( iLength < 0 )
    {
        WRMSG(HHC00973, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->filename,
              strerror( HSO_errno ) );
        pDEVBLK->sense[0] = SENSE_EC;
        *pUnitStat = CSW_CE | CSW_DE | CSW_UC;
        return;
    }

    // Trace the packet received from the TUN device
    if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
    {
        WRMSG(HHC00913, "I", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, iLength, "TUN" );
        packet_trace( pDEVBLK->buf, iLength, '<' );
    }

    // Fix-up Frame pointer
    pFrame = (PCTCIHDR)pIOBuf;

    // Fix-up Segment pointer
    pSegment = (PCTCISEG)( pIOBuf + sizeof( CTCIHDR ) );

    // Initialize segment
    memset( pSegment, 0, iLength + sizeof( CTCISEG ) );

    // Update next frame offset
    STORE_HW( pFrame->hwOffset,
              (U16)(iLength + sizeof( CTCIHDR ) + sizeof( CTCISEG )) );

    // Store segment length
    STORE_HW( pSegment->hwLength, (U16)(iLength + sizeof( CTCISEG )) );

    // Store Frame type
    STORE_HW( pSegment->hwType, ETH_TYPE_IP );

    // Copy data
    memcpy( pSegment->bData, pDEVBLK->buf, iLength );

    // Fix-up frame pointer and terminate block
    pFrame = (PCTCIHDR)( pIOBuf + sizeof( CTCIHDR ) +
                         sizeof( CTCISEG ) + iLength );
    STORE_HW( pFrame->hwOffset, 0x0000 );

    // Calculate #of bytes returned including two slack bytes
    iLength += sizeof( CTCIHDR ) + sizeof( CTCISEG ) + 2;

    if( sCount < (U32)iLength )
    {
        *pMore     = 1;
        *pResidual = 0;

        iLength    = sCount;
    }
    else
    {
        *pMore      = 0;
        *pResidual -= iLength;
    }

    // Set unit status
    *pUnitStat = CSW_CE | CSW_DE;
}
示例#9
0
/*-------------------------------------------------------------------*/
static void
convert_ckd_file (IFD ifd, char *ifname, int itrklen, BYTE *itrkbuf,
                int repl, int quiet,
                char *ofname, int fseqn, U16 devtype, U32 heads,
                U32 trksize, BYTE *obuf, U32 start, U32 end,
                U32 volcyls, BYTE *volser)
{
int             rc;                     /* Return code               */
int             ofd;                    /* Output file descriptor    */
CKDDASD_DEVHDR  devhdr;                 /* Output device header      */
CKDDASD_TRKHDR *trkhdr;                 /* -> Output track header    */
CKDDASD_RECHDR *rechdr;                 /* -> Output record header   */
U32             cyl;                    /* Cylinder number           */
U32             head;                   /* Head number               */
int             fileseq;                /* CKD header sequence number*/
int             highcyl;                /* CKD header high cyl number*/
BYTE           *opos;                   /* -> Byte in output buffer  */
BYTE            klen;                   /* Key length                */
U16             dlen;                   /* Data length               */
BYTE            rec;                    /* Record number             */
BYTE           *iptr;                   /* -> Byte in input buffer   */
BYTE           *kptr;                   /* -> Key in input buffer    */
BYTE           *dptr;                   /* -> Data in input buffer   */
int             ilen;                   /* Bytes left in input buffer*/
H30CKD_TRKHDR  *ith;                    /* -> Input track header     */
U32             ihc, ihh;               /* Input trk header cyl,head */
U32             offset;                 /* Current input file offset */
char            pathname[MAX_PATH];     /* file path in host format  */

    UNREFERENCED(volser);

    /* Set file sequence number to zero if this is the only file */
    if (fseqn == 1 && end + 1 == volcyls)
        fileseq = 0;
    else
        fileseq = fseqn;

    /* Set high cylinder number to zero if this is the last file */
    if (end + 1 == volcyls)
        highcyl = 0;
    else
        highcyl = end;

    /* Create the AWSCKD image file */
    hostpath(pathname, (char *)ofname, sizeof(pathname));
    ofd = hopen(pathname,
                O_WRONLY | O_CREAT | O_BINARY | (repl ? 0 : O_EXCL),
                S_IRUSR | S_IWUSR | S_IRGRP);

    if (ofd < 0)
    {
        fprintf (stderr, "%s open error: %s\n",
                ofname, strerror(errno));
        EXIT(8);
    }

    /* Create the device header */
    memset(&devhdr, 0, CKDDASD_DEVHDR_SIZE);
    memcpy(devhdr.devid, "CKD_P370", 8);
    devhdr.heads[3] = (heads >> 24) & 0xFF;
    devhdr.heads[2] = (heads >> 16) & 0xFF;
    devhdr.heads[1] = (heads >> 8) & 0xFF;
    devhdr.heads[0] = heads & 0xFF;
    devhdr.trksize[3] = (trksize >> 24) & 0xFF;
    devhdr.trksize[2] = (trksize >> 16) & 0xFF;
    devhdr.trksize[1] = (trksize >> 8) & 0xFF;
    devhdr.trksize[0] = trksize & 0xFF;
    devhdr.devtype = devtype & 0xFF;
    devhdr.fileseq = fileseq;
    devhdr.highcyl[1] = (highcyl >> 8) & 0xFF;
    devhdr.highcyl[0] = highcyl & 0xFF;

    /* Write the device header */
    rc = write (ofd, &devhdr, CKDDASD_DEVHDR_SIZE);
    if (rc < CKDDASD_DEVHDR_SIZE)
    {
        fprintf (stderr, "%s device header write error: %s\n",
                ofname, errno ? strerror(errno) : "incomplete");
        EXIT(1);
    }

    /* Write each cylinder */
    for (cyl = start; cyl <= end; cyl++)
    {
        /* Display progress message every 10 cylinders */
        if ((cyl % 10) == 0)
        {
#ifdef EXTERNALGUI
            if (extgui)
                fprintf (stderr, "CYL=%u\n", cyl);
            else
#endif /*EXTERNALGUI*/
            if (quiet == 0)
                fprintf (stderr, "Writing cylinder %u\r", cyl);
        }

        for (head = 0; head < heads; head++)
        {
            /* Calculate the current offset in the file */
            offset = ((cyl*heads)+head)*itrklen;

            /* Read the input track image (except cyl 0 head 0 
               already read by the open_input_image procedure) */
            if (cyl > 0 || head > 0)
            {
                read_input_data (ifd, ifname,
                                 itrkbuf, itrklen,
                                 offset);
            } /* end if(cyl>0||head>0) */

            /* Validate the track header */
            ith = (H30CKD_TRKHDR*)itrkbuf;
            FETCH_HW (ihc, ith->cyl);
            FETCH_HW (ihh, ith->head);
            if (ihc != cyl || ihh != head)
            {
                fprintf (stderr,
                        "Invalid track header found at offset %8.8X\n"
                        "in input file %s\n"
                        "Expected cyl=%4.4X head=%4.4X\n"
                        "   Found cyl=%4.4X head=%4.4X\n",
                        offset, ifname,
                        cyl, head, ihc, ihh);
                EXIT(8);
            }
             
            /* Clear the output track image to zeroes */
            memset (obuf, 0, trksize);

            /* Build the output track header */
            trkhdr = (CKDDASD_TRKHDR*)obuf;
            trkhdr->bin = 0;
            STORE_HW (trkhdr->cyl, cyl);
            STORE_HW (trkhdr->head, head);
            opos = obuf + CKDDASD_TRKHDR_SIZE;

            /* Copy each record from the input buffer */
            iptr = itrkbuf + H30CKD_TRKHDR_SIZE;
            ilen = itrklen - H30CKD_TRKHDR_SIZE;
            while (1)
            {
                /* Locate the next input record */
                rc = find_input_record (itrkbuf, &iptr, &ilen,
                        &klen, &kptr, &dlen, &dptr,
                        &ihc, &ihh, &rec);

                /* Exit at end of track */
                if (rc == 1) break;

                /* Error if invalid record header detected */
                if (rc > 1)
                {
                    fprintf (stderr,
                            "Invalid record header (reason %d)\n"
                            "at offset %4.4X"
                            " in track at cyl %4.4X head %4.4X\n"
                            "at offset %8.8X in input file %s\n",
                            rc, (unsigned int)(iptr-itrkbuf), cyl, head,
                            offset, ifname);
                    EXIT(9);
                }

                /* Build AWSCKD record header in output buffer */
                rechdr = (CKDDASD_RECHDR*)opos;
                opos += CKDDASD_RECHDR_SIZE;
                STORE_HW (rechdr->cyl, ihc);
                STORE_HW (rechdr->head, ihh);
                rechdr->rec = rec;
                rechdr->klen = klen;
                STORE_HW (rechdr->dlen, dlen);

                /* Copy key and data to output buffer */
                if (klen != 0)
                {
                    memcpy (opos, kptr, klen);
                    opos += klen;
                }
                if (dlen != 0)
                {
                    memcpy (opos, dptr, dlen);
                    opos += dlen;
                }

            } /* end while */

            /* Build the end of track marker */
            memcpy (opos, eighthexFF, 8);

            /* Write the track to the file */
            rc = write (ofd, obuf, trksize);
            if (rc < 0 || (U32)rc < trksize)
            {
                fprintf (stderr,
                        "%s cylinder %u head %u write error: %s\n",
                        ofname, cyl, head,
                        errno ? strerror(errno) : "incomplete");
                EXIT(1);
            }

        } /* end for(head) */

    } /* end for(cyl) */

    /* Close the AWSCKD image file */
    rc = close (ofd);
    if (rc < 0)
    {
        fprintf (stderr, "%s close error: %s\n",
                ofname, strerror(errno));
        EXIT(10);
    }

    /* Display completion message */
    fprintf (stderr,
            "%u cylinders successfully written to file %s\n",
            cyl - start, ofname);

} /* end function convert_ckd_file */
示例#10
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(perform_external_interrupt) (REGS *regs)
{
PSA    *psa;                            /* -> Prefixed storage area  */
U16     cpuad;                          /* Originating CPU address   */
#if defined(FEATURE_VM_BLOCKIO)
#if defined(FEATURE_ESAME)
RADR    servpadr;      /* Address of 64-bit block I/O interrupt */
#endif
U16     servcode;      /* Service Signal or Block I/O Interrupt code */
#endif /* defined(FEATURE_VM_BLOCKIO) */

    /* External interrupt if console interrupt key was depressed */
    if ( OPEN_IC_INTKEY(regs) && !SIE_MODE(regs) )
    {
        WRMSG (HHC00840, "I");

        /* Reset interrupt key pending */
        OFF_IC_INTKEY;

        /* Generate interrupt key interrupt */
        ARCH_DEP(external_interrupt) (EXT_INTERRUPT_KEY_INTERRUPT, regs);
    }

    /* External interrupt if malfunction alert is pending */
    if (OPEN_IC_MALFALT(regs))
    {
        /* Find first CPU which generated a malfunction alert */
        for (cpuad = 0; regs->malfcpu[cpuad] == 0; cpuad++)
        {
            if (cpuad >= sysblk.maxcpu)
            {
                OFF_IC_MALFALT(regs);
                return;
            }
        } /* end for(cpuad) */

// /*debug*/ logmsg (_("External interrupt: Malfuction Alert from CPU %d\n"),
// /*debug*/    cpuad);

        /* Reset the indicator for the CPU which was found */
        regs->malfcpu[cpuad] = 0;

        /* Store originating CPU address at PSA+X'84' */
        psa = (void*)(regs->mainstor + regs->PX);
        STORE_HW(psa->extcpad,cpuad);

        /* Reset emergency signal pending flag if there are
           no other CPUs which generated emergency signal */
        OFF_IC_MALFALT(regs);
        while (++cpuad < sysblk.maxcpu)
        {
            if (regs->malfcpu[cpuad])
            {
                ON_IC_MALFALT(regs);
                break;
            }
        } /* end while */

        /* Generate emergency signal interrupt */
        ARCH_DEP(external_interrupt) (EXT_MALFUNCTION_ALERT_INTERRUPT, regs);
    }


    /* External interrupt if emergency signal is pending */
    if (OPEN_IC_EMERSIG(regs))
    {
        /* Find first CPU which generated an emergency signal */
        for (cpuad = 0; regs->emercpu[cpuad] == 0; cpuad++)
        {
            if (cpuad >= sysblk.maxcpu)
            {
                OFF_IC_EMERSIG(regs);
                return;
            }
        } /* end for(cpuad) */

// /*debug*/ logmsg (_("External interrupt: Emergency Signal from CPU %d\n"),
// /*debug*/    cpuad);

        /* Reset the indicator for the CPU which was found */
        regs->emercpu[cpuad] = 0;

        /* Store originating CPU address at PSA+X'84' */
        psa = (void*)(regs->mainstor + regs->PX);
        STORE_HW(psa->extcpad,cpuad);

        /* Reset emergency signal pending flag if there are
           no other CPUs which generated emergency signal */
        OFF_IC_EMERSIG(regs);
        while (++cpuad < sysblk.maxcpu)
        {
            if (regs->emercpu[cpuad])
            {
                ON_IC_EMERSIG(regs);
                break;
            }
        } /* end while */

        /* Generate emergency signal interrupt */
        ARCH_DEP(external_interrupt) (EXT_EMERGENCY_SIGNAL_INTERRUPT, regs);
    }

    /* External interrupt if external call is pending */
    if (OPEN_IC_EXTCALL(regs))
    {
//  /*debug*/logmsg (_("External interrupt: External Call from CPU %d\n"),
//  /*debug*/       regs->extccpu);

        /* Reset external call pending */
        OFF_IC_EXTCALL(regs);

        /* Store originating CPU address at PSA+X'84' */
        psa = (void*)(regs->mainstor + regs->PX);
        STORE_HW(psa->extcpad,regs->extccpu);

        /* Generate external call interrupt */
        ARCH_DEP(external_interrupt) (EXT_EXTERNAL_CALL_INTERRUPT, regs);
    }

    /* External interrupt if TOD clock exceeds clock comparator */
    if ( tod_clock(regs) > regs->clkc
        && OPEN_IC_CLKC(regs) )
    {
        if (CPU_STEPPING_OR_TRACING_ALL)
        {
            WRMSG (HHC00841, "I");
        }
        ARCH_DEP(external_interrupt) (EXT_CLOCK_COMPARATOR_INTERRUPT, regs);
    }

    /* External interrupt if CPU timer is negative */
    if ( CPU_TIMER(regs) < 0
        && OPEN_IC_PTIMER(regs) )
    {
        if (CPU_STEPPING_OR_TRACING_ALL)
        {
            WRMSG (HHC00842, "I", CPU_TIMER(regs) << 8);
        }
        ARCH_DEP(external_interrupt) (EXT_CPU_TIMER_INTERRUPT, regs);
    }

    /* External interrupt if interval timer interrupt is pending */
#if defined(FEATURE_INTERVAL_TIMER)
    if (OPEN_IC_ITIMER(regs)
#if defined(_FEATURE_SIE)
        && !(SIE_STATB(regs, M, ITMOF))
#endif /*defined(_FEATURE_SIE)*/
        )
    {
        if (CPU_STEPPING_OR_TRACING_ALL)
        {
            WRMSG (HHC00843, "I");
        }
        OFF_IC_ITIMER(regs);
        ARCH_DEP(external_interrupt) (EXT_INTERVAL_TIMER_INTERRUPT, regs);
    }

#if defined(FEATURE_ECPSVM)
    if ( OPEN_IC_ECPSVTIMER(regs) )
    {
        OFF_IC_ECPSVTIMER(regs);
        ARCH_DEP(external_interrupt) (EXT_VINTERVAL_TIMER_INTERRUPT,regs);
    }
#endif /*FEATURE_ECPSVM*/
#endif /*FEATURE_INTERVAL_TIMER*/

    /* External interrupt if service signal is pending */
    if ( OPEN_IC_SERVSIG(regs) && !SIE_MODE(regs) )
    {

#if defined(FEATURE_VM_BLOCKIO)
        
        /* Note: Both Block I/O and Service Signal are enabled by the */
        /* the same CR0 bit.  Hence they are handled in the same code */
        switch(sysblk.servcode)
        {
        case EXT_BLOCKIO_INTERRUPT:  /* VM Block I/O Interrupt */

           if (sysblk.biodev->ccwtrace)
           {
           WRMSG (HHC00844, "I",
                SSID_TO_LCSS(sysblk.biodev->ssid),
                sysblk.biodev->devnum,
                sysblk.servcode,
                sysblk.bioparm,
                sysblk.biostat,
                sysblk.biosubcd
                );
           }

           servcode = EXT_BLOCKIO_INTERRUPT;

#if defined(FEATURE_ESAME)
/* Real address used to store the 64-bit interrupt parameter */
#define VM_BLOCKIO_INT_PARM 0x11B8
           if (sysblk.biosubcd == 0x07)
           {
           /* 8-byte interrupt parm */
           
               if (CPU_STEPPING_OR_TRACING_ALL)
               {
                  char buf[40];
                  MSGBUF(buf, "%16.16X", (unsigned) sysblk.bioparm);
                  WRMSG (HHC00845,"I", buf);
               }

               /* Set the main storage reference and change bits   */
               /* for 64-bit interruption parameter.               */
               /* Note: This is handled for the first 4K page in   */
               /* ARCH_DEP(external_interrupt), but not for the    */
               /* the second 4K page used for the 64-bit interrupt */
               /* parameter.                                       */

               /* Point to 2nd page of PSA in main storage */
               servpadr=APPLY_PREFIXING(VM_BLOCKIO_INT_PARM,regs->PX);

               STORAGE_KEY(servpadr, regs) 
                     |= (STORKEY_REF | STORKEY_CHANGE);

#if 0
               /* Store the 64-bit interrupt parameter */
               logmsg (_("Saving 64-bit Block I/O interrupt parm at "
                         "%16.16X: %16.16X\n"),
                         servpadr,
                         sysblk.bioparm
                      );
#endif

               STORE_DW(regs->mainstor + servpadr,sysblk.bioparm);
               psa = (void*)(regs->mainstor + regs->PX);
           }
           else
           {
#endif  /* defined(FEATURE_ESAME) */

           /* 4-byte interrupt parm */

              if (CPU_STEPPING_OR_TRACING_ALL)
              {
                 char buf[40];
                 MSGBUF(buf, "%8.8X", (U32) sysblk.bioparm);
                 WRMSG (HHC00845,"I", buf);
              }

              /* Store Block I/O parameter at PSA+X'80' */
              psa = (void*)(regs->mainstor + regs->PX);
              STORE_FW(psa->extparm,(U32)sysblk.bioparm);

#if defined(FEATURE_ESAME)
           }
#endif

           /* Store sub-interruption code and status at PSA+X'84' */
           STORE_HW(psa->extcpad,(sysblk.biosubcd<<8)|sysblk.biostat);
           
           /* Reset interruption data */
           sysblk.bioparm  = 0;
           sysblk.biosubcd = 0;
           sysblk.biostat  = 0;
           
           break;

        case EXT_SERVICE_SIGNAL_INTERRUPT: /* Service Signal */
        default:
             servcode = EXT_SERVICE_SIGNAL_INTERRUPT;
             
            /* Apply prefixing if the parameter is a storage address */
            if ( (sysblk.servparm & SERVSIG_ADDR) )
                sysblk.servparm =
                     APPLY_PREFIXING (sysblk.servparm, regs->PX);

             if (CPU_STEPPING_OR_TRACING_ALL)
             {
                 WRMSG (HHC00846,"I", sysblk.servparm);
             }

             /* Store service signal parameter at PSA+X'80' */
             psa = (void*)(regs->mainstor + regs->PX);
             STORE_FW(psa->extparm,sysblk.servparm);

        }  /* end switch(sysblk.servcode) */
        /* Reset service parameter */
        sysblk.servparm = 0;

        /* Reset service code */
        sysblk.servcode = 0;

        /* Reset service signal pending */
        OFF_IC_SERVSIG;

        /* Generate service signal interrupt */
        ARCH_DEP(external_interrupt) (servcode, regs);
             
#else /* defined(FEATURE_VM_BLOCKIO) */

        /* Apply prefixing if the parameter is a storage address */
        if ( (sysblk.servparm & SERVSIG_ADDR) )
            sysblk.servparm =
                APPLY_PREFIXING (sysblk.servparm, regs->PX);

        if (CPU_STEPPING_OR_TRACING_ALL)
        {
            WRMSG (HHC00846,"I", sysblk.servparm);
        }

        /* Store service signal parameter at PSA+X'80' */
        psa = (void*)(regs->mainstor + regs->PX);
        STORE_FW(psa->extparm,sysblk.servparm);

        /* Reset service parameter */
        sysblk.servparm = 0;

        /* Reset service signal pending */
        OFF_IC_SERVSIG;
        
        /* Generate service signal interrupt */
        ARCH_DEP(external_interrupt) (EXT_SERVICE_SIGNAL_INTERRUPT, regs);

#endif /* defined(FEATURE_VM_BLOCKIO) */

    }  /* end OPEN_IC_SERVSIG(regs) */

} /* end function perform_external_interrupt */
示例#11
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(diag204_call) (int r1, int r2, REGS *regs)
{
DIAG204_HDR       *hdrinfo;            /* Header                     */
DIAG204_PART      *partinfo;           /* Partition info             */
DIAG204_PART_CPU  *cpuinfo;            /* CPU info                   */
#if defined(FEATURE_EXTENDED_DIAG204)
DIAG204_X_HDR      *hdrxinfo;          /* Header                     */
DIAG204_X_PART     *partxinfo;         /* Partition info             */
DIAG204_X_PART_CPU *cpuxinfo;          /* CPU info                   */
U64               tdis;       
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/
RADR              abs;                 /* abs addr of data area      */
U64               dreg;                /* work doubleword            */
int               i;                   /* loop counter               */
struct rusage     usage;               /* RMF type data              */
static U64        diag204tod;          /* last diag204 tod           */
#if defined(FEATURE_PHYSICAL_DIAG204)
static BYTE       physical[8] =
              {0xD7,0xC8,0xE8,0xE2,0xC9,0xC3,0xC1,0xD3}; /* PHYSICAL */
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

    /* Test DIAG204 command word */
    switch (regs->GR_L(r2)) {

    case 0x04:

        abs = APPLY_PREFIXING (GR_A(r1,regs), regs->PX);

        /* Program check if RMF data is not on a page boundary */
        if ( (abs & PAGEFRAME_BYTEMASK) != 0x000)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        /* Program check if RMF data area is outside main storage */
        if ( abs > regs->mainlim )
            ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

        /* Point to DIAG 204 data area */
        hdrinfo = (DIAG204_HDR*)(regs->mainstor + abs);

        /* Mark page referenced */
        STORAGE_KEY(abs, regs) |= STORKEY_REF | STORKEY_CHANGE;

        /* save last diag204 tod */
        dreg = diag204tod;

        /* Retrieve the TOD clock value and shift out the epoch */
        diag204tod = tod_clock(regs) << 8;

        memset(hdrinfo, 0, sizeof(DIAG204_HDR));
        hdrinfo->numpart = 1;
#if defined(FEATURE_PHYSICAL_DIAG204)
        hdrinfo->flags = DIAG204_PHYSICAL_PRESENT;
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/
        STORE_HW(hdrinfo->physcpu,sysblk.cpus);
        STORE_HW(hdrinfo->offown,sizeof(DIAG204_HDR));
        STORE_DW(hdrinfo->diagstck,dreg);

        /* hercules partition */
        partinfo = (DIAG204_PART*)(hdrinfo + 1);
        memset(partinfo, 0, sizeof(DIAG204_PART));
        partinfo->partnum = 1; /* Hercules partition */
        partinfo->virtcpu = sysblk.cpus;
        get_lparname(partinfo->partname);

        /* hercules cpu's */
        getrusage(RUSAGE_SELF,&usage);
        cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU));
              STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuinfo->index=sysblk.ptyp[i];
              STORE_HW(cpuinfo->weight,100);
              dreg = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuinfo->totdispatch,dreg);

              dreg = (U64)(usage.ru_utime.tv_sec)* 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuinfo->effdispatch,dreg);

              cpuinfo += 1;
          }

#if defined(FEATURE_PHYSICAL_DIAG204)
        /* lpar management */
        getrusage(RUSAGE_CHILDREN,&usage);
        partinfo = (DIAG204_PART*)cpuinfo;
        memset(partinfo, 0, sizeof(DIAG204_PART));
        partinfo->partnum = 0; /* Physical machine */
        partinfo->virtcpu = sysblk.cpus;
        memcpy(partinfo->partname,physical,sizeof(physical));

        /* report all emulated physical cpu's */
        getrusage(RUSAGE_SELF,&usage);
        cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU));
              STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuinfo->weight,100);

              dreg = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuinfo->totdispatch,dreg);

              dreg = (U64)(usage.ru_utime.tv_sec) * 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuinfo->effdispatch,dreg);

              cpuinfo += 1;
          }
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

        regs->GR_L(r2) = 0;

        break;

#if defined(FEATURE_EXTENDED_DIAG204)
    /* Extended subcode 5 returns the size of the data areas provided by extended subcodes 6 and 7 */
    case 0x00010005:
        i = sizeof(DIAG204_X_HDR) + ((sizeof(DIAG204_X_PART) + (sysblk.maxcpu * sizeof(DIAG204_X_PART_CPU))) * 2);
        regs->GR_L(r2+1) = (i + PAGEFRAME_BYTEMASK) / PAGEFRAME_PAGESIZE;
        regs->GR_L(r2) = 0;

        break;

    /* Provide extended information */
    case 0x00010006:
        /* We fall through as we do not have any secondary cpus (that we know of) */

    /* Provide extended information, including information about secondary CPUs */
    case 0x00010007:
        /* Program check if RMF data is not on a page boundary */
        if ( (regs->GR_L(r1) & PAGEFRAME_BYTEMASK) != 0x000)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        /* Obtain absolute address of main storage block,
           check protection, and set reference and change bits */
        hdrxinfo = (DIAG204_X_HDR*)MADDR (GR_A(r1,regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey);

        /* save last diag204 tod */
        dreg = diag204tod;

        /* Retrieve the TOD clock value and shift out the epoch */
        diag204tod = tod_clock(regs) << 8;

        memset(hdrxinfo, 0, sizeof(DIAG204_X_HDR));
        hdrxinfo->numpart = 1;
#if defined(FEATURE_PHYSICAL_DIAG204)
        hdrxinfo->flags = DIAG204_X_PHYSICAL_PRESENT;
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/
        STORE_HW(hdrxinfo->physcpu,sysblk.cpus);
        STORE_HW(hdrxinfo->offown,sizeof(DIAG204_X_HDR));
        STORE_DW(hdrxinfo->diagstck1,(dreg >> 8));
        STORE_DW(hdrxinfo->diagstck2,( 0x0000000001000000ULL | (regs->cpuad << 16) | regs->todpr));

        /* hercules partition */
        partxinfo = (DIAG204_X_PART*)(hdrxinfo + 1);
        memset(partxinfo, 0, sizeof(DIAG204_PART));
        partxinfo->partnum = 1; /* Hercules partition */
        partxinfo->virtcpu = sysblk.cpus;
        get_lparname(partxinfo->partname);
        get_sysname(partxinfo->cpcname);
        get_systype(partxinfo->osname);
        STORE_DW(partxinfo->cssize,sysblk.mainsize);
        STORE_DW(partxinfo->essize,sysblk.xpndsize);
        get_sysplex(partxinfo->gr_name);

        /* hercules cpu's */
        getrusage(RUSAGE_SELF,&usage);
        cpuxinfo = (DIAG204_X_PART_CPU*)(partxinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU));
              STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuxinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuxinfo->weight,100);
              
              tdis = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000;
              tdis = (tdis + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus;
              tdis <<= 12;
              STORE_DW(cpuxinfo->totdispatch,tdis);

              dreg = (U64)(usage.ru_utime.tv_sec)* 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuxinfo->effdispatch,dreg);

              STORE_HW(cpuxinfo->minweight,1000);
              STORE_HW(cpuxinfo->curweight,1000);
              STORE_HW(cpuxinfo->maxweight,1000);

              STORE_DW(cpuxinfo->onlinetime, diag204tod - sysblk.todstart);
              STORE_DW(cpuxinfo->waittime, (diag204tod - sysblk.todstart) - tdis);

              STORE_HW(cpuxinfo->pmaweight,1000);
              STORE_HW(cpuxinfo->polarweight,1000);

              cpuxinfo += 1;
          }


#if defined(FEATURE_PHYSICAL_DIAG204)
        /* lpar management */
        partxinfo = (DIAG204_X_PART*)cpuxinfo;
        memset(partxinfo, 0, sizeof(DIAG204_X_PART));
        partxinfo->partnum = 0; /* Physical machine */
        partxinfo->virtcpu = sysblk.cpus;
        memcpy(partxinfo->partname,physical,sizeof(physical));

        /* report all emulated physical cpu's */
        getrusage(RUSAGE_CHILDREN,&usage);
        cpuxinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU));
              STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuxinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuxinfo->weight,100);
              
              tdis = (U64)(usage.ru_utime.tv_sec + usage.ru_stime.tv_sec) * 1000000;
              tdis = (tdis + (usage.ru_utime.tv_usec + usage.ru_stime.tv_usec)) / sysblk.cpus;
              tdis <<= 12;
              STORE_DW(cpuxinfo->totdispatch,tdis);

              dreg = (U64)(usage.ru_utime.tv_sec)* 1000000;
              dreg = (dreg + (usage.ru_utime.tv_usec)) / sysblk.cpus;
              dreg <<= 12;
              STORE_DW(cpuxinfo->effdispatch,dreg);

              STORE_HW(cpuxinfo->minweight,1000);
              STORE_HW(cpuxinfo->curweight,1000);
              STORE_HW(cpuxinfo->maxweight,1000);

              STORE_DW(cpuxinfo->onlinetime, diag204tod - sysblk.todstart);
              STORE_DW(cpuxinfo->waittime, (diag204tod - sysblk.todstart) - tdis);

              STORE_HW(cpuxinfo->pmaweight,1000);
              STORE_HW(cpuxinfo->polarweight,1000);

              cpuxinfo += 1;
          }
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

        regs->GR_L(r2) = 0;

        break;
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/

    default:
        PTT(PTT_CL_ERR,"*DIAG204",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
        regs->GR_L(r2) = 4;

    } /*switch(regs->GR_L(r2))*/

} /* end function diag204_call */
示例#12
0
/*-------------------------------------------------------------------*/
static int ARCH_DEP(scedio_request)(U32 sclp_command, SCCB_EVD_HDR *evd_hdr)
{
SCCB_SCEDIO_BK  *scedio_bk = (SCCB_SCEDIO_BK*)(evd_hdr + 1);
SCCB_SCEDIOV_BK *scediov_bk;
SCCB_SCEDIOR_BK *scedior_bk;
int rc;


static struct {
    SCCB_SCEDIO_BK scedio_bk;
    union {
        SCCB_SCEDIOV_BK v;
        SCCB_SCEDIOR_BK r;
        } io;
    } static_scedio_bk ;

static int scedio_pending;

    if(sclp_command == SCLP_READ_EVENT_DATA)
    {
    int pending_req = scedio_pending;
    U16 evd_len;

        /* Return no data if the scedio thread is still active */
        if(scedio_tid)
            return 0;

        /* Update the scedio_bk copy in the SCCB */
        if(scedio_pending)
        {
            /* Zero all fields */
            memset (evd_hdr, 0, sizeof(SCCB_EVD_HDR));

            /* Set type in event header */
            evd_hdr->type = SCCB_EVD_TYPE_SCEDIO;

            /* Store scedio header */
            *scedio_bk = static_scedio_bk.scedio_bk;

            /* Calculate event response length */
            evd_len = sizeof(SCCB_EVD_HDR) + sizeof(SCCB_SCEDIO_BK);

            switch(scedio_bk->flag1) {
            case SCCB_SCEDIO_FLG1_IOR:
                scedior_bk = (SCCB_SCEDIOR_BK*)(scedio_bk + 1);
                *scedior_bk = static_scedio_bk.io.r;
                evd_len += sizeof(SCCB_SCEDIOR_BK);
                break;
            case SCCB_SCEDIO_FLG1_IOV:
                scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1);
                *scediov_bk = static_scedio_bk.io.v ;
                evd_len += sizeof(SCCB_SCEDIOV_BK);
                break;
            default:
                PTT(PTT_CL_ERR,"*SERVC",(U32)evd_hdr->type,(U32)scedio_bk->flag1,scedio_bk->flag3);
            }

            /* Set length in event header */
            STORE_HW(evd_hdr->totlen, evd_len);
        }


        /* Reset the pending flag */
        scedio_pending = 0;

        /* Return true if a request was pending */
        return pending_req;

    }
    else
    {
#if !defined(NO_SIGABEND_HANDLER)
        switch(scedio_bk->flag1) {
            case SCCB_SCEDIO_FLG1_IOV:
                scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1);
                switch(scediov_bk->type) {
                    case SCCB_SCEDIOV_TYPE_INIT:
                        /* Kill the scedio thread if it is active */
                        if( scedio_tid )
                        {
                            OBTAIN_INTLOCK(NULL);
                            signal_thread(scedio_tid, SIGKILL);
                            scedio_tid = 0;
                            scedio_pending = 0;
                            RELEASE_INTLOCK(NULL);
                        }
                        break;
                }
                break;
        }
#endif

        /* Take a copy of the scedio_bk in the SCCB */
        static_scedio_bk.scedio_bk = *scedio_bk;
        switch(scedio_bk->flag1) {
        case SCCB_SCEDIO_FLG1_IOR:
            scedior_bk = (SCCB_SCEDIOR_BK*)(scedio_bk + 1);
            static_scedio_bk.io.r = *scedior_bk;
            break;
        case SCCB_SCEDIO_FLG1_IOV:
            scediov_bk = (SCCB_SCEDIOV_BK*)(scedio_bk + 1);
            static_scedio_bk.io.v = *scediov_bk;
            break;
        default:
            PTT(PTT_CL_ERR,"*SERVC",(U32)evd_hdr->type,(U32)scedio_bk->flag1,scedio_bk->flag3);
        }

        /* Create the scedio thread */
        rc = create_thread(&scedio_tid, &sysblk.detattr,
            ARCH_DEP(scedio_thread), &static_scedio_bk, "scedio_thread");
        if (rc)
        {
            WRMSG(HHC00102, "E", strerror(rc));
            return -1;
        }
        scedio_pending = 1;
    }

    return 0;
}
示例#13
0
void  CTCI_Read( DEVBLK* pDEVBLK,   U16   sCount,
                 BYTE*   pIOBuf,    BYTE* pUnitStat,
                 U16*    pResidual, BYTE* pMore )
{
    PCTCBLK     pCTCBLK  = (PCTCBLK)pDEVBLK->dev_data;
    PCTCIHDR    pFrame   = NULL;
    size_t      iLength  = 0;
    int         rc       = 0;

    for ( ; ; )
    {
        obtain_lock( &pCTCBLK->Lock );

        if( !pCTCBLK->fDataPending )
        {
            struct timespec waittime;
            struct timeval  now;

            release_lock( &pCTCBLK->Lock );

            gettimeofday( &now, NULL );

            waittime.tv_sec  = now.tv_sec  + CTC_READ_TIMEOUT_SECS;
            waittime.tv_nsec = now.tv_usec * 1000;

            obtain_lock( &pCTCBLK->EventLock );
            rc = timed_wait_condition( &pCTCBLK->Event,
                                       &pCTCBLK->EventLock,
                                       &waittime );
            release_lock( &pCTCBLK->EventLock );

            if( rc == ETIMEDOUT || rc == EINTR )
            {
                // check for halt condition
                if( pDEVBLK->scsw.flag2 & SCSW2_FC_HALT ||
                    pDEVBLK->scsw.flag2 & SCSW2_FC_CLEAR )
                {
                    if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep )
                        logmsg( _("HHCCT040I %4.4X: Halt or Clear Recognized\n"),
                                pDEVBLK->devnum );

                    *pUnitStat = CSW_CE | CSW_DE;
                    *pResidual = sCount;
                    return;
                }

                continue;
            }

            obtain_lock( &pCTCBLK->Lock );
        }

        // Sanity check
        if( pCTCBLK->iFrameOffset == 0 )
        {
            release_lock( &pCTCBLK->Lock );
            continue;
        }

        // Fix-up frame pointer and terminate block
        pFrame = (PCTCIHDR)( pCTCBLK->bFrameBuffer +
                  sizeof( CTCIHDR ) +
                  pCTCBLK->iFrameOffset );

        STORE_HW( pFrame->hwOffset, 0x0000 );

        // (fix for day-1 bug offered by Vince Weaver [[email protected]])
//      iLength = pCTCBLK->iFrameOffset + sizeof( CTCIHDR ) + 2;
        iLength = pCTCBLK->iFrameOffset + sizeof( CTCIHDR );

        if( sCount < iLength )
        {
            *pMore     = 1;
            *pResidual = 0;

            iLength    = sCount;
        }
        else
        {
            *pMore      = 0;
            *pResidual -= iLength;
        }

        *pUnitStat = CSW_CE | CSW_DE;

        memcpy( pIOBuf, pCTCBLK->bFrameBuffer, iLength );

        if( pCTCBLK->fDebug )
        {
            logmsg( _("HHCCT041I %4.4X: CTC Received Frame (%d bytes):\n"),
                    pDEVBLK->devnum, iLength );
            packet_trace( pCTCBLK->bFrameBuffer, iLength );
        }

        // Reset frame buffer
        pCTCBLK->iFrameOffset  = 0;
        pCTCBLK->fDataPending  = 0;

        release_lock( &pCTCBLK->Lock );

        return;
    }
}
示例#14
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(load_ipl) (U16 lcss, U16 devnum, int cpu, int clear)
{
REGS   *regs;                           /* -> Regs                   */
DEVBLK *dev;                            /* -> Device control block   */
int     i;                              /* Array subscript           */
BYTE    unitstat;                       /* IPL device unit status    */
BYTE    chanstat;                       /* IPL device channel status */
int rc;

    /* Get started */
    if ((rc = ARCH_DEP(common_load_begin) (cpu, clear)) )
        return rc;

    /* Ensure CPU is online */
    if (!IS_CPU_ONLINE(cpu))
    {
        char buf[80];
        MSGBUF(buf, "CP%02.2X Offline", devnum);
        WRMSG (HHC00810, "E", PTYPSTR(sysblk.pcpu), sysblk.pcpu, buf);
        return -1;
    }

    /* The actual IPL proper starts here... */

    regs = sysblk.regs[cpu];    /* Point to IPL CPU's registers */
    /* Point to the device block for the IPL device */
    dev = find_device_by_devnum (lcss,devnum);
    if (dev == NULL)
    {
        char buf[80];
        MSGBUF(buf, "device %4.4X not found", devnum);
        WRMSG (HHC00810, "E", PTYPSTR(sysblk.pcpu), sysblk.pcpu, buf);
        HDC1(debug_cpu_state, regs);
        return -1;
    }

    if(sysblk.haveiplparm)
    {
        for(i=0;i<16;i++)
        {
            regs->GR_L(i)=fetch_fw(&sysblk.iplparmstring[i*4]);
        }
        sysblk.haveiplparm=0;
    }

    /* Set Main Storage Reference and Update bits */
    STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE);
    sysblk.main_clear = sysblk.xpnd_clear = 0;

    /* Build the IPL CCW at location 0 */
    regs->psa->iplpsw[0] = 0x02;              /* CCW command = Read */
    regs->psa->iplpsw[1] = 0;                 /* Data address = zero */
    regs->psa->iplpsw[2] = 0;
    regs->psa->iplpsw[3] = 0;
    regs->psa->iplpsw[4] = CCW_FLAGS_CC | CCW_FLAGS_SLI;
                                        /* CCW flags */
    regs->psa->iplpsw[5] = 0;                 /* Reserved byte */
    regs->psa->iplpsw[6] = 0;                 /* Byte count = 24 */
    regs->psa->iplpsw[7] = 24;

    /* Enable the subchannel for the IPL device */
    dev->pmcw.flag5 |= PMCW5_E;

    /* Build the operation request block */                    /*@IWZ*/
    memset (&dev->orb, 0, sizeof(ORB));                        /*@IWZ*/
    dev->busy = 1;

    RELEASE_INTLOCK(NULL);

    /* Execute the IPL channel program */
    ARCH_DEP(execute_ccw_chain) (dev);

    OBTAIN_INTLOCK(NULL);

    /* Clear the interrupt pending and device busy conditions */
    obtain_lock (&sysblk.iointqlk);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->ioint);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->pciioint);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->attnioint);
    release_lock(&sysblk.iointqlk);
    dev->busy = 0;
    dev->scsw.flag2 = 0;
    dev->scsw.flag3 = 0;

    /* Check that load completed normally */
    unitstat = dev->scsw.unitstat;
    chanstat = dev->scsw.chanstat;

    if (unitstat != (CSW_CE | CSW_DE) || chanstat != 0)
    {
        char buf[80];
        char buf2[16];

        memset(buf,0,sizeof(buf));
        for (i=0; i < (int)dev->numsense; i++)
        {
            MSGBUF(buf2, "%2.2X", dev->sense[i]);
            strlcat(buf, buf2, sizeof(buf) );
            if ((i & 3) == 3) strlcat(buf, " ", sizeof(buf));
        }
        {
            char buffer[256];
            MSGBUF(buffer, "architecture mode %s, csw status %2.2X%2.2X, sense %s",
                get_arch_mode_string((REGS *)0),
                unitstat, chanstat, buf);
            WRMSG (HHC00828, "E", PTYPSTR(sysblk.pcpu), sysblk.pcpu, buffer);
        }
        HDC1(debug_cpu_state, regs);
        return -1;
    }

#ifdef FEATURE_S370_CHANNEL
    /* Test the EC mode bit in the IPL PSW */
    if (regs->psa->iplpsw[1] & 0x08) {
        /* In EC mode, store device address at locations 184-187 */
        STORE_FW(regs->psa->ioid, dev->devnum);
    } else {
        /* In BC mode, store device address at locations 2-3 */
        STORE_HW(regs->psa->iplpsw + 2, dev->devnum);
    }
#endif /*FEATURE_S370_CHANNEL*/

#ifdef FEATURE_CHANNEL_SUBSYSTEM
    /* Set LPUM */
    dev->pmcw.lpum = 0x80;
    STORE_FW(regs->psa->ioid, (dev->ssid<<16)|dev->subchan);

    /* Store zeroes at locations 188-191 */
    memset (regs->psa->ioparm, 0, 4);
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/

    /* Save IPL device number, cpu number and lcss */
    sysblk.ipldev = devnum;
    sysblk.iplcpu = regs->cpuad;
    sysblk.ipllcss = lcss;
    sysblk.ipled = TRUE;

    /* Finish up... */
    return ARCH_DEP(common_load_finish) (regs);
} /* end function load_ipl */
示例#15
0
/*-------------------------------------------------------------------*/
void ARCH_DEP(diag204_call) (int r1, int r2, REGS *regs)
{
DIAG204_HDR       *hdrinfo;            /* Header                     */
DIAG204_PART      *partinfo;           /* Partition info             */
DIAG204_PART_CPU  *cpuinfo;            /* CPU info                   */
#if defined(FEATURE_EXTENDED_DIAG204)
DIAG204_X_HDR      *hdrxinfo;          /* Header                     */
DIAG204_X_PART     *partxinfo;         /* Partition info             */
DIAG204_X_PART_CPU *cpuxinfo;          /* CPU info                   */
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/
RADR              abs;                 /* abs addr of data area      */
int               i;                   /* loop counter               */
struct rusage     usage;               /* RMF type data              */
ETOD              ETOD;                /* Extended TOD clock         */
U64               uCPU[MAX_CPU_ENGINES];    /* User CPU time    (us) */
U64               tCPU[MAX_CPU_ENGINES];    /* Total CPU time   (us) */

#if defined(FEATURE_PHYSICAL_DIAG204)
static BYTE       physical[8] =
              {0xD7,0xC8,0xE8,0xE2,0xC9,0xC3,0xC1,0xD3}; /* PHYSICAL */
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

#if defined(FEATURE_EXTENDED_DIAG204)
U64               oCPU[MAX_CPU_ENGINES];    /* Online CPU time  (us) */
U64               wCPU[MAX_CPU_ENGINES];    /* Wait CPU time    (us) */
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/

    /* Test DIAG204 command word */
    switch (regs->GR_L(r2)) {

    case 0x04:

        abs = APPLY_PREFIXING (GR_A(r1,regs), regs->PX);

        /* Program check if RMF data is not on a page boundary */
        if ( (abs & PAGEFRAME_BYTEMASK) != 0x000)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        /* Program check if RMF data area is outside main storage */
        if ( abs > regs->mainlim )
            ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

        /* Point to DIAG 204 data area */
        hdrinfo = (DIAG204_HDR*)(regs->mainstor + abs);

        /* Mark page referenced */
        STORAGE_KEY(abs, regs) |= STORKEY_REF | STORKEY_CHANGE;

        /* Retrieve the TOD clock value */
        etod_clock(regs, &ETOD, ETOD_extended);

        /* Get processor time(s) and leave out non-CPU processes and
         * threads
         */
        for(i = 0; i < sysblk.maxcpu; ++i)
        {
            if (IS_CPU_ONLINE(i))
            {
                /* Get CPU times in microseconds */
                getrusage((int)sysblk.cputid[i], &usage);
                uCPU[i] = timeval2us(&usage.ru_utime);
                tCPU[i] = uCPU[i] + timeval2us(&usage.ru_stime);
            }
        }

        memset(hdrinfo, 0, sizeof(DIAG204_HDR));
        hdrinfo->numpart = 1;
#if defined(FEATURE_PHYSICAL_DIAG204)
        hdrinfo->flags = DIAG204_PHYSICAL_PRESENT;
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/
        STORE_HW(hdrinfo->physcpu,sysblk.cpus);
        STORE_HW(hdrinfo->offown,sizeof(DIAG204_HDR));
        STORE_DW(hdrinfo->diagstck,ETOD2tod(ETOD));

        /* hercules partition */
        partinfo = (DIAG204_PART*)(hdrinfo + 1);
        memset(partinfo, 0, sizeof(DIAG204_PART));
        partinfo->partnum = sysblk.lparnum;     /* Hercules partition */
        partinfo->virtcpu = sysblk.cpus;
        get_lparname(partinfo->partname);

        /* hercules cpu's */
        cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU));
              STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuinfo->index=sysblk.ptyp[i];
              STORE_HW(cpuinfo->weight,100);
              STORE_DW(cpuinfo->totdispatch,tCPU[i]);
              STORE_DW(cpuinfo->effdispatch, uCPU[i]);
              cpuinfo += 1;
          }

#if defined(FEATURE_PHYSICAL_DIAG204)
        /* LPAR management */
        /* FIXME: This section should report on the real CPUs, appearing
         *        and transformed for reporting purposes. This should
         *        also be properly reflected in STSI information.
         */
        partinfo = (DIAG204_PART*)cpuinfo;
        memset(partinfo, 0, sizeof(DIAG204_PART));
        partinfo->partnum = 0; /* Physical machine */
        partinfo->virtcpu = sysblk.cpus;
        memcpy(partinfo->partname,physical,sizeof(physical));

        /* report all emulated physical cpu's */
        cpuinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuinfo, 0, sizeof(DIAG204_PART_CPU));
              STORE_HW(cpuinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuinfo->weight,100);
              STORE_DW(cpuinfo->totdispatch, tCPU[i]);
              STORE_DW(cpuinfo->effdispatch, uCPU[i]);
              cpuinfo += 1;
          }
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

        regs->GR_L(r2) = 0;

        break;

#if defined(FEATURE_EXTENDED_DIAG204)
    /* Extended subcode 5 returns the size of the data areas provided by extended subcodes 6 and 7 */
    case 0x00010005:
        i = sizeof(DIAG204_X_HDR) + ((sizeof(DIAG204_X_PART) + (sysblk.maxcpu * sizeof(DIAG204_X_PART_CPU))) * 2);
        regs->GR_L(r2+1) = (i + PAGEFRAME_BYTEMASK) / PAGEFRAME_PAGESIZE;
        regs->GR_L(r2) = 0;

        break;

    /* Provide extended information */
    case 0x00010006:
        /* We fall through as we do not have any secondary cpus (that we know of) */

    /* Provide extended information, including information about secondary CPUs */
    case 0x00010007:
        /* Program check if RMF data is not on a page boundary */
        if ( (regs->GR_L(r1) & PAGEFRAME_BYTEMASK) != 0x000)
            ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

        /* Obtain absolute address of main storage block,
           check protection, and set reference and change bits */
        hdrxinfo = (DIAG204_X_HDR*)MADDR (GR_A(r1,regs), r1, regs, ACCTYPE_WRITE, regs->psw.pkey);

        /* Retrieve the TOD clock value */
        etod_clock(regs, &ETOD, ETOD_extended);

        /* Get processor time(s) and leave out non-CPU processes and
         * threads
         */
        for(i = 0; i < sysblk.maxcpu; ++i)
        {
            if (IS_CPU_ONLINE(i))
            {
                /* Get CPU times in microseconds */
                getrusage((int)sysblk.cputid[i], &usage);
                oCPU[i] = etod2us(ETOD.high - regs->tod_epoch - sysblk.cpucreateTOD[i]);
                uCPU[i] = timeval2us(&usage.ru_utime);
                tCPU[i] = uCPU[i] + timeval2us(&usage.ru_stime);
                wCPU[i] = tCPU[i] - uCPU[i];
            }
        }

        memset(hdrxinfo, 0, sizeof(DIAG204_X_HDR));
        hdrxinfo->numpart = 1;
#if defined(FEATURE_PHYSICAL_DIAG204)
        hdrxinfo->flags = DIAG204_X_PHYSICAL_PRESENT;
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/
        STORE_HW(hdrxinfo->physcpu,sysblk.cpus);
        STORE_HW(hdrxinfo->offown,sizeof(DIAG204_X_HDR));
        STORE_DW(hdrxinfo->diagstck1,ETOD.high);
        STORE_DW(hdrxinfo->diagstck2,ETOD.low);

        /* hercules partition */
        partxinfo = (DIAG204_X_PART*)(hdrxinfo + 1);
        memset(partxinfo, 0, sizeof(DIAG204_PART));
        partxinfo->partnum = sysblk.lparnum;    /* Hercules partition */
        partxinfo->virtcpu = sysblk.cpus;
        get_lparname(partxinfo->partname);
        get_sysname(partxinfo->cpcname);
        get_systype(partxinfo->osname);
        STORE_DW(partxinfo->cssize,sysblk.mainsize);
        STORE_DW(partxinfo->essize,sysblk.xpndsize);
        get_sysplex(partxinfo->gr_name);

        /* hercules cpu's */
        cpuxinfo = (DIAG204_X_PART_CPU*)(partxinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU));
              STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuxinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuxinfo->weight,100);

              STORE_DW(cpuxinfo->totdispatch, tCPU[i]);
              STORE_DW(cpuxinfo->effdispatch, uCPU[i]);

              STORE_HW(cpuxinfo->minweight,1000);
              STORE_HW(cpuxinfo->curweight,1000);
              STORE_HW(cpuxinfo->maxweight,1000);

              STORE_DW(cpuxinfo->onlinetime, oCPU[i]);
              STORE_DW(cpuxinfo->waittime,   wCPU[i]);

              STORE_HW(cpuxinfo->pmaweight,1000);
              STORE_HW(cpuxinfo->polarweight,1000);

              cpuxinfo += 1;
          }


#if defined(FEATURE_PHYSICAL_DIAG204)
        /* LPAR management */
        /* FIXME: This section should report on the real CPUs, appearing
         *        and transformed for reporting purposes. This should
         *        also be properly reflected in STSI information.
         */
        partxinfo = (DIAG204_X_PART*)cpuxinfo;
        memset(partxinfo, 0, sizeof(DIAG204_X_PART));
        partxinfo->partnum = 0; /* Physical machine */
        partxinfo->virtcpu = sysblk.cpus;
        memcpy(partxinfo->partname,physical,sizeof(physical));

        /* report all emulated physical cpu's */
        cpuxinfo = (DIAG204_PART_CPU*)(partinfo + 1);
        for(i = 0; i < sysblk.maxcpu; i++)
          if (IS_CPU_ONLINE(i))
          {
              memset(cpuxinfo, 0, sizeof(DIAG204_X_PART_CPU));
              STORE_HW(cpuxinfo->cpaddr,sysblk.regs[i]->cpuad);
              cpuxinfo->index = sysblk.ptyp[i];
              STORE_HW(cpuxinfo->weight,100);

              STORE_DW(cpuxinfo->totdispatch, tCPU[i]);
              STORE_DW(cpuxinfo->effdispatch, uCPU[i]);

              STORE_HW(cpuxinfo->minweight,1000);
              STORE_HW(cpuxinfo->curweight,1000);
              STORE_HW(cpuxinfo->maxweight,1000);

              STORE_DW(cpuxinfo->onlinetime, oCPU[i]);
              STORE_DW(cpuxinfo->waittime,   wCPU[i]);

              STORE_HW(cpuxinfo->pmaweight,1000);
              STORE_HW(cpuxinfo->polarweight,1000);

              cpuxinfo += 1;
          }
#endif /*defined(FEATURE_PHYSICAL_DIAG204)*/

        regs->GR_L(r2) = 0;

        break;
#endif /*defined(FEATURE_EXTENDED_DIAG204)*/

    default:
        PTT_ERR("*DIAG204",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
        regs->GR_L(r2) = 4;

    } /*switch(regs->GR_L(r2))*/

} /* end function diag204_call */
示例#16
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(load_ipl) (U16 lcss, U16 devnum, int cpu, int clear)
{
REGS   *regs;                           /* -> Regs                   */
DEVBLK *dev;                            /* -> Device control block   */
int     i;                              /* Array subscript           */
BYTE    unitstat;                       /* IPL device unit status    */
BYTE    chanstat;                       /* IPL device channel status */

    /* Get started */
    if (ARCH_DEP(common_load_begin) (cpu, clear) != 0)
        return -1;

    /* The actual IPL proper starts here... */

    regs = sysblk.regs[cpu];    /* Point to IPL CPU's registers */

    /* Point to the device block for the IPL device */
    dev = find_device_by_devnum (lcss,devnum);
    if (dev == NULL)
    {
        logmsg (_("HHCCP027E Device %4.4X not in configuration%s\n"),
                devnum,
                (sysblk.arch_mode == ARCH_370 ?
                  " or not conneceted to channelset" : ""));
        HDC1(debug_cpu_state, regs);
        return -1;
    }
#if defined(OPTION_IPLPARM)
    if(sysblk.haveiplparm)
    {
        for(i=0;i<16;i++)
        {
            regs->GR_L(i)=fetch_fw(&sysblk.iplparmstring[i*4]);
        }
        sysblk.haveiplparm=0;
    }
#endif

    /* Set Main Storage Reference and Update bits */
    STORAGE_KEY(regs->PX, regs) |= (STORKEY_REF | STORKEY_CHANGE);
    sysblk.main_clear = sysblk.xpnd_clear = 0;

    /* Build the IPL CCW at location 0 */
    regs->psa->iplpsw[0] = 0x02;              /* CCW command = Read */
    regs->psa->iplpsw[1] = 0;                 /* Data address = zero */
    regs->psa->iplpsw[2] = 0;
    regs->psa->iplpsw[3] = 0;
    regs->psa->iplpsw[4] = CCW_FLAGS_CC | CCW_FLAGS_SLI;
                                        /* CCW flags */
    regs->psa->iplpsw[5] = 0;                 /* Reserved byte */
    regs->psa->iplpsw[6] = 0;                 /* Byte count = 24 */
    regs->psa->iplpsw[7] = 24;

    /* Enable the subchannel for the IPL device */
    dev->pmcw.flag5 |= PMCW5_E;

    /* Build the operation request block */                    /*@IWZ*/
    memset (&dev->orb, 0, sizeof(ORB));                        /*@IWZ*/
    dev->busy = 1;

    RELEASE_INTLOCK(NULL);

    /* Execute the IPL channel program */
    ARCH_DEP(execute_ccw_chain) (dev);

    OBTAIN_INTLOCK(NULL);

    /* Clear the interrupt pending and device busy conditions */
    obtain_lock (&sysblk.iointqlk);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->ioint);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->pciioint);
    DEQUEUE_IO_INTERRUPT_QLOCKED(&dev->attnioint);
    release_lock(&sysblk.iointqlk);
    dev->busy = 0;
    dev->scsw.flag2 = 0;
    dev->scsw.flag3 = 0;

    /* Check that load completed normally */
#ifdef FEATURE_S370_CHANNEL
    unitstat = dev->csw[4];
    chanstat = dev->csw[5];
#endif /*FEATURE_S370_CHANNEL*/

#ifdef FEATURE_CHANNEL_SUBSYSTEM
    unitstat = dev->scsw.unitstat;
    chanstat = dev->scsw.chanstat;
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/

    if (unitstat != (CSW_CE | CSW_DE) || chanstat != 0) {
        logmsg (_("HHCCP029E %s mode IPL failed: CSW status=%2.2X%2.2X\n"
                  "           Sense="),
                get_arch_mode_string(regs), unitstat, chanstat);
        for (i=0; i < (int)dev->numsense; i++)
        {
            logmsg ("%2.2X", dev->sense[i]);
            if ((i & 3) == 3) logmsg(" ");
        }
        logmsg ("\n");
        HDC1(debug_cpu_state, regs);
        return -1;
    }

#ifdef FEATURE_S370_CHANNEL
    /* Test the EC mode bit in the IPL PSW */
    if (regs->psa->iplpsw[1] & 0x08) {
        /* In EC mode, store device address at locations 184-187 */
        STORE_FW(regs->psa->ioid, dev->devnum);
    } else {
        /* In BC mode, store device address at locations 2-3 */
        STORE_HW(regs->psa->iplpsw + 2, dev->devnum);
    }
#endif /*FEATURE_S370_CHANNEL*/

#ifdef FEATURE_CHANNEL_SUBSYSTEM
    /* Set LPUM */
    dev->pmcw.lpum = 0x80;
    STORE_FW(regs->psa->ioid, (dev->ssid<<16)|dev->subchan);

    /* Store zeroes at locations 188-191 */
    memset (regs->psa->ioparm, 0, 4);
#endif /*FEATURE_CHANNEL_SUBSYSTEM*/

    /* Save IPL device number, cpu number and lcss */
    sysblk.ipldev = devnum;
    sysblk.iplcpu = regs->cpuad;
    sysblk.ipllcss = lcss;

    /* Finish up... */
    return ARCH_DEP(common_load_finish) (regs);
} /* end function load_ipl */
示例#17
0
/*-------------------------------------------------------------------*/
static void ARCH_DEP(external_interrupt) (int code, REGS *regs)
{
RADR    pfx;
PSA     *psa;
int     rc;

    PTT(PTT_CL_SIG,"*EXTINT",code,regs->cpuad,regs->psw.IA_L);

#if defined(_FEATURE_SIE)
    /* Set the main storage reference and change bits */
    if(SIE_MODE(regs)
#if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
                       && !SIE_FEATB(regs, S, EXP_TIMER)
#endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
#if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
                       && !SIE_FEATB(regs, EC0, EXTA)
#endif
                                                            )
    {
        /* Point to SIE copy of PSA in state descriptor */
        psa = (void*)(regs->hostregs->mainstor + SIE_STATE(regs) + SIE_IP_PSA_OFFSET);
        STORAGE_KEY(SIE_STATE(regs), regs->hostregs) |= (STORKEY_REF | STORKEY_CHANGE);
    }
    else
#endif /*defined(_FEATURE_SIE)*/
    {
        /* Point to PSA in main storage */
        pfx = regs->PX;
#if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
        SIE_TRANSLATE(&pfx, ACCTYPE_SIE, regs);
#endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
        psa = (void*)(regs->mainstor + pfx);
        STORAGE_KEY(pfx, regs) |= (STORKEY_REF | STORKEY_CHANGE);
    }

    /* Store the interrupt code in the PSW */
    regs->psw.intcode = code;


    /* Zero extcpuad field unless extcall or ems signal or blockio */
    if(code != EXT_EXTERNAL_CALL_INTERRUPT
#if defined(FEATURE_VM_BLOCKIO)
    && code != EXT_BLOCKIO_INTERRUPT
#endif /* defined(FEATURE_VM_BLOCKIO) */
    && code != EXT_EMERGENCY_SIGNAL_INTERRUPT)
        STORE_HW(psa->extcpad,0);

#if defined(FEATURE_BCMODE)
    /* For ECMODE, store external interrupt code at PSA+X'86' */
    if ( ECMODE(&regs->psw) )
#endif /*defined(FEATURE_BCMODE)*/
        STORE_HW(psa->extint,code);

    if ( !SIE_MODE(regs)
#if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
                       || SIE_FEATB(regs, S, EXP_TIMER)
#endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
#if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
                       || SIE_FEATB(regs, EC0, EXTA)
#endif
       )
    {
        /* Store current PSW at PSA+X'18' */
        ARCH_DEP(store_psw) (regs, psa->extold);

        /* Load new PSW from PSA+X'58' */
        rc = ARCH_DEP(load_psw) (regs, psa->extnew);

        if ( rc )
        {
            RELEASE_INTLOCK(regs);
            ARCH_DEP(program_interrupt)(regs, rc);
        }
    }

#if defined(FEATURE_INTERVAL_TIMER)
    /* Ensure the interval timer is uptodate */
    ARCH_DEP(store_int_timer_nolock) (regs);
#endif
    RELEASE_INTLOCK(regs);


    if ( SIE_MODE(regs)
#if defined(_FEATURE_EXPEDITED_SIE_SUBSET)
                       && !SIE_FEATB(regs, S, EXP_TIMER)
#endif /*defined(_FEATURE_EXPEDITED_SIE_SUBSET)*/
#if defined(_FEATURE_EXTERNAL_INTERRUPT_ASSIST)
                       && !SIE_FEATB(regs, EC0, EXTA)
#endif
       )
        longjmp (regs->progjmp, SIE_INTERCEPT_EXT);
    else
        longjmp (regs->progjmp, SIE_NO_INTERCEPT);

} /* end function external_interrupt */
示例#18
0
/*-------------------------------------------------------------------*/
int ARCH_DEP(mssf_call) (int r1, int r2, REGS *regs)
{
U32     spccb_absolute_addr;            /* Absolute addr of SPCCB    */
U32     mssf_command;                   /* MSSF command word         */
U32               spccblen;            /* Length of SPCCB            */
SPCCB_HEADER      *spccb;              /* -> SPCCB header            */
SPCCB_CONFIG_INFO *spccbconfig;        /* -> SPCCB CONFIG info       */
SPCCB_CPU_INFO    *spccbcpu;           /* -> SPCCB CPU information   */
SPCCB_CHP_STATUS  *spccbchp;           /* -> SPCCB channel path info */
U16               offset;              /* Offset from start of SPCCB */
int               i;                   /* loop counter               */
DEVBLK            *dev;                /* Device block pointer       */

    /* R1 contains the real address of the SPCCB */
    spccb_absolute_addr = APPLY_PREFIXING (regs->GR_L(r1), regs->PX);

    /* R2 contains the service-processor-command word */
    mssf_command = regs->GR_L(r2);

    /* Program check if SPCCB is not on a doubleword boundary */
    if ( spccb_absolute_addr & 0x00000007 )
        ARCH_DEP(program_interrupt) (regs, PGM_SPECIFICATION_EXCEPTION);

    /* Program check if SPCCB is outside main storage */
    if ( spccb_absolute_addr > regs->mainlim )
        ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

//  /*debug*/logmsg("MSSF call %8.8X SPCCB=%8.8X\n",
//  /*debug*/       mssf_command, spccb_absolute_addr);

    /* Point to Service Processor Command Control Block */
    spccb = (SPCCB_HEADER*)(regs->mainstor + spccb_absolute_addr);

    /* Load SPCCB length from header */
    FETCH_HW(spccblen,spccb->length);

    /* Mark page referenced */
    STORAGE_KEY(spccb_absolute_addr, regs) |= STORKEY_REF;

    /* Program check if end of SPCCB falls outside main storage */
    if ( sysblk.mainsize - spccblen < spccb_absolute_addr )
        ARCH_DEP(program_interrupt) (regs, PGM_ADDRESSING_EXCEPTION);

    /* Obtain the interrupt lock */
    OBTAIN_INTLOCK(regs);

    /* If a service signal is pending then we cannot process the request */
    if( IS_IC_SERVSIG && (sysblk.servparm & SERVSIG_ADDR)) {
        RELEASE_INTLOCK(regs);
        return 2;   /* Service Processor Busy */
    }

    if( spccb_absolute_addr & 0x7ffff800 ) {
        spccb->resp[0] = SPCCB_REAS_NOT2KALIGN;
        spccb->resp[1] = SPCCB_RESP_NOT2KALIGN;
    } else
        /* Test MSSF command word */
        switch (mssf_command) {

        case MSSF_READ_CONFIG_INFO:

            /* Set response code X'01F0' if SPCCB length
               is insufficient to contain CONFIG info */
            if ( spccblen < 64 )
            {
                spccb->resp[0] = SPCCB_REAS_BADLENGTH;
                spccb->resp[1] = SPCCB_RESP_BADLENGTH;
            break;
            }

            /* Point to SPCCB data area following SPCCB header */
            spccbconfig = (SPCCB_CONFIG_INFO*)(spccb+1);
            memset (spccbconfig, 0, sizeof(SPCCB_CONFIG_INFO));

            /* Set main storage size in SPCCB */
            spccbconfig->totstori = sysblk.mainsize >> 20;
            spccbconfig->storisiz = 1;
            spccbconfig->hex04 = 0x04;
            spccbconfig->hex01 = 0x01;

            /* Set CPU array count and offset in SPCCB */
            STORE_HW(spccbconfig->toticpu,sysblk.maxcpu);
            offset = sizeof(SPCCB_HEADER) + sizeof(SPCCB_CONFIG_INFO);
            STORE_HW(spccbconfig->officpu,offset);

            /* Set HSA array count and offset in SPCCB */
            STORE_HW(spccbconfig->tothsa,0);
            offset += (U16)(sizeof(SPCCB_CPU_INFO) * sysblk.maxcpu);
            STORE_HW(spccbconfig->offhsa,offset);

            /* Move IPL load parameter to SPCCB */
            get_loadparm (spccbconfig->loadparm);

            /* Build the CPU information array after the SCP info */
            spccbcpu = (SPCCB_CPU_INFO*)(spccbconfig+1);
            for (i = 0; i < sysblk.maxcpu; i++, spccbcpu++)
            {
                memset( spccbcpu, 0, sizeof(SPCCB_CPU_INFO) );
                spccbcpu->cpuaddr = i;
                spccbcpu->todid = 0;
            }

            /* Set response code X'0010' in SPCCB header */
            spccb->resp[0] = SPCCB_REAS_COMPLETE;
            spccb->resp[1] = SPCCB_RESP_COMPLETE;

            break;

        case MSSF_READ_CHP_STATUS:

            /* Set response code X'0300' if SPCCB length
               is insufficient to contain channel path info */
            if ( spccblen < sizeof(SPCCB_HEADER) + sizeof(SPCCB_CHP_STATUS))
            {
                spccb->resp[0] = SPCCB_REAS_BADLENGTH;
                spccb->resp[1] = SPCCB_RESP_BADLENGTH;
                break;
            }

            /* Point to SPCCB data area following SPCCB header */
            spccbchp = (SPCCB_CHP_STATUS*)(spccb+1);
            memset( spccbchp, 0, sizeof(SPCCB_CHP_STATUS) );

            /* Identify CHPIDs used */
            for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
            {
                for (i = 0; i < 8; i++)
                {
                    if( ((0x80 >> i) & dev->pmcw.pim) )
                    {
                    BYTE chpid;
                        chpid = dev->pmcw.chpid[i];
                        spccbchp->installed[chpid / 8] |= 0x80 >> (chpid % 8);
                        spccbchp->assigned[chpid / 8] |= 0x80 >> (chpid % 8);
                        spccbchp->configured[chpid / 8] |= 0x80 >> (chpid % 8);
                    }
               }
            }

            /* Set response code X'0010' in SPCCB header */
            spccb->resp[0] = SPCCB_REAS_COMPLETE;
            spccb->resp[1] = SPCCB_RESP_COMPLETE;

            break;

        default:
            PTT(PTT_CL_ERR,"*DIAG080",regs->GR_L(r1),regs->GR_L(r2),regs->psw.IA_L);
            /* Set response code X'06F0' for invalid MSSF command */
            spccb->resp[0] = SPCCB_REAS_UNASSIGNED;
            spccb->resp[1] = SPCCB_RESP_UNASSIGNED;

            break;

        } /* end switch(mssf_command) */

    /* Mark page changed */
    STORAGE_KEY(spccb_absolute_addr, regs) |= STORKEY_CHANGE;

    /* Set service signal external interrupt pending */
    sysblk.servparm &= ~SERVSIG_ADDR;
    sysblk.servparm |= spccb_absolute_addr;
    ON_IC_SERVSIG; 

    /* Release the interrupt lock */
    RELEASE_INTLOCK(regs);

    /* Return condition code 0: Command initiated */
    return 0;

} /* end function mssf_call */
示例#19
0
// --------------------------------------------------------------------
// CTCI_EnqueueIPFrame
// --------------------------------------------------------------------
//
// Places the provided IP frame in the next available frame slot in
// the adapter buffer. For details regarding the actual buffer layout
// please refer to the comments preceding the CTCI_ReadThread function.
//
// Returns:
//
//  0 == Success
// -1 == Failure; errno = ENOBUFS:  No buffer space available
//                        EMSGSIZE: Message too long
//
static int  CTCI_EnqueueIPFrame( DEVBLK* pDEVBLK,
                                 BYTE*   pData, size_t iSize )
{
    PCTCIHDR pFrame;
    PCTCISEG pSegment;
    PCTCBLK  pCTCBLK = (PCTCBLK)pDEVBLK->dev_data;

    // Will frame NEVER fit into buffer??
    if( iSize > MAX_CTCI_FRAME_SIZE( pCTCBLK ) )
    {
        errno = EMSGSIZE;   // Message too long
        return -1;          // (-1==failure)
    }

    obtain_lock( &pCTCBLK->Lock );

    // Ensure we dont overflow the buffer
    if( ( pCTCBLK->iFrameOffset +         // Current buffer Offset
          sizeof( CTCIHDR ) +             // Size of Block Header
          sizeof( CTCISEG ) +             // Size of Segment Header
          iSize +                         // Size of Ethernet packet
          sizeof(pFrame->hwOffset) )      // Size of Block terminator
        > pCTCBLK->iMaxFrameBufferSize )  // Size of Frame buffer
    {
        release_lock( &pCTCBLK->Lock );
        errno = ENOBUFS;    // No buffer space available
        return -1;          // (-1==failure)
    }

    // Fix-up Frame pointer
    pFrame = (PCTCIHDR)pCTCBLK->bFrameBuffer;

    // Fix-up Segment pointer
    pSegment = (PCTCISEG)( pCTCBLK->bFrameBuffer +
                           sizeof( CTCIHDR ) +
                           pCTCBLK->iFrameOffset );

    // Initialize segment
    memset( pSegment, 0, iSize + sizeof( CTCISEG ) );

    // Increment offset
    pCTCBLK->iFrameOffset += sizeof( CTCISEG ) + iSize;

    // Update next frame offset
    STORE_HW( pFrame->hwOffset,
              pCTCBLK->iFrameOffset + sizeof( CTCIHDR ) );

    // Store segment length
    STORE_HW( pSegment->hwLength, sizeof( CTCISEG ) + iSize );

    // Store Frame type
    STORE_HW( pSegment->hwType, ETH_TYPE_IP );

    // Copy data
    memcpy( pSegment->bData, pData, iSize );

    // Mark data pending
    pCTCBLK->fDataPending = 1;

    release_lock( &pCTCBLK->Lock );

    obtain_lock( &pCTCBLK->EventLock );
    signal_condition( &pCTCBLK->Event );
    release_lock( &pCTCBLK->EventLock );

    return 0;       // (0==success)
}