/*-------------------------------------------------------------------*/ int http_command(int argc, char *argv[]) { int rc = 0; if ( !http_struct_init ) { memset(&http_serv,0,sizeof(HTTP_SERV)); initialize_condition( &http_serv.http_wait_shutdown ); initialize_lock( &http_serv.http_lock_shutdown ); initialize_lock( &http_lock_root ); http_struct_init = TRUE; } http_serv.httpstmtold = FALSE; if ( argc == 2 && CMD(argv[0],rootx,4) && ( ( strlen(argv[0]) == 5 && argv[2] != NULL && strcmp(argv[2],"httproot") == 0 ) || ( strlen(argv[0]) == 4 ) ) ) { if ( strlen(argv[0]) == 5 ) { http_serv.httpstmtold = TRUE; } obtain_lock( &http_lock_root ); if (http_serv.httproot) { free(http_serv.httproot); http_serv.httproot = NULL; } if ( strlen(argv[1]) > 0 ) { char pathname[MAX_PATH]; hostpath(pathname, argv[1], sizeof(pathname)); if ( pathname[strlen(pathname)-1] != PATHSEPC ) strlcat( pathname, PATHSEPS, sizeof(pathname) ); http_serv.httproot = strdup(pathname); } release_lock( &http_lock_root ); http_root(); if ( MLVL(VERBOSE) ) WRMSG(HHC02204, "I", http_serv.httpstmtold ? "httproot": "root", http_serv.httproot ? http_serv.httproot : "<not specified>"); if ( http_serv.httpstmtold ) http_startup(TRUE); rc = 0; } else if ( (argc == 2 || argc == 3 || argc == 5) && CMD(argv[0],portx,4) && ( ( strlen(argv[0]) == 5 && argv[5] != NULL && strcmp(argv[5],"httpport") == 0 ) || ( strlen(argv[0]) == 4 ) ) ) { if ( strlen(argv[0]) == 5 ) { http_serv.httpstmtold = TRUE; } if ( sysblk.httptid != 0 ) { WRMSG( HHC01812, "E" ); rc = -1; } else { char c; if (sscanf(argv[1], "%hu%c", &http_serv.httpport, &c) != 1 || http_serv.httpport == 0 || (http_serv.httpport < 1024 && http_serv.httpport != 80) ) { rc = -1; } if ( rc >= 0 && argc == 3 && CMD(argv[2],noauth,6) ) { http_serv.httpauth = 0; } else if ( rc >=0 && argc == 5 && CMD(argv[2],auth,4) ) { if ( strlen( argv[3] ) < 1 || strlen( argv[4] ) < 1 ) { WRMSG( HHC01814, "E" ); rc = -1; } else { if (http_serv.httpuser) free(http_serv.httpuser); http_serv.httpuser = strdup(argv[3]); if (http_serv.httppass) free(http_serv.httppass); http_serv.httppass = strdup(argv[4]); http_serv.httpauth = 1; } } else if ( argc != 2 || rc < 0 ) { WRMSG( HHC02299, "E", "http" ); rc = -1; } if ( rc >= 0 && MLVL(VERBOSE) ) { char msgbuf[128]; if ( http_serv.httpauth == 1 ) { MSGBUF( msgbuf, "port=%hu auth userid<%s> password<%s>", http_serv.httpport, ( http_serv.httpuser == NULL || strlen(http_serv.httpuser) == 0 ) ? "" : http_serv.httpuser, ( http_serv.httppass == NULL || strlen(http_serv.httppass) == 0 ) ? "" : http_serv.httppass ); } else MSGBUF( msgbuf, "port=%hu noauth", http_serv.httpport ); WRMSG( HHC02204, "I", http_serv.httpstmtold ? "httpport":"port", msgbuf ); if ( http_serv.httpstmtold ) http_startup(TRUE); } /* VERBOSE */ } } else if ( argc == 1 && CMD(argv[0],start,3) ) { if ( http_serv.httpport == 0 ) { WRMSG( HHC01815, "E", "not valid"); rc = -1; } else rc = http_startup(FALSE); } else if (argc == 1 && CMD(argv[0],stop,4)) { if ( sysblk.httptid != 0 ) { http_shutdown(NULL); WRMSG( HHC01805, "I" ); rc = 1; } else { http_serv.httpshutdown = TRUE; WRMSG( HHC01806, "W", "already stopped" ); rc = 1; } } else if ( argc == 0 ) { if ( sysblk.httptid != 0 ) { if ( http_serv.httpbinddone ) { WRMSG( HHC01809, "I" ); rc = 0; } else { WRMSG( HHC01813, "I" ); rc = 1; } } else { WRMSG( HHC01810, "I" ); rc = 1; } WRMSG(HHC01811, "I", http_get_root()); WRMSG(HHC01808, "I", http_get_port(), http_get_portauth()); } else { WRMSG( HHC02299, "E", "http" ); rc = -1; } return rc; }
// -------------------------------------------------------------------- // 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) }
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; } }
/*-------------------------------------------------------------------*/ int bind_device_ex (DEVBLK* dev, char* spec, ONCONNECT fn, void* arg ) { bind_struct* bs; int was_list_empty; int rc; if (!init_done) init_sockdev(); if (sysblk.shutdown) return 0; logdebug("bind_device (%4.4X, %s)\n", dev->devnum, spec); /* Error if device already bound */ if (dev->bs) { WRMSG (HHC01041, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->bs->spec); return 0; /* (failure) */ } /* Create a new bind_struct entry */ bs = malloc(sizeof(bind_struct)); if (!bs) { char buf[40]; MSGBUF( buf, "malloc(%d)", (int)sizeof(bind_struct)); WRMSG (HHC01000, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, buf, strerror(errno)); return 0; /* (failure) */ } memset(bs, 0, sizeof(bind_struct)); bs->fn = fn; bs->arg = arg; if (!(bs->spec = strdup(spec))) { WRMSG (HHC01000, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "strdup()", strerror(errno) ); free (bs); return 0; /* (failure) */ } /* Create a listening socket */ if (bs->spec[0] == '/') bs->sd = unix_socket (bs->spec); else bs->sd = inet_socket (bs->spec); if (bs->sd == -1) { /* (error message already issued) */ free( bs->spec ); free( bs ); return 0; /* (failure) */ } /* Chain device and bind_struct to each other */ dev->bs = bs; bs->dev = dev; /* Add the new entry to our list of bound devices and create the socket thread that will listen for connections (if it doesn't already exist) */ obtain_lock( &bind_lock ); was_list_empty = IsListEmpty( &bind_head ); InsertListTail( &bind_head, &bs->bind_link ); if ( was_list_empty ) { rc = create_thread( &sysblk.socktid, JOINABLE, socket_thread, NULL, "socket_thread" ); if (rc) { WRMSG(HHC00102, "E", strerror( rc ) ); RemoveListEntry( &bs->bind_link ); close_socket(bs->sd); free( bs->spec ); free( bs ); release_lock( &bind_lock ); return 0; /* (failure) */ } } SIGNAL_SOCKDEV_THREAD(); release_lock( &bind_lock ); WRMSG (HHC01042, "I", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->bs->spec); return 1; /* (success) */ }
/*-------------------------------------------------------------------*/ int unbind_device_ex (DEVBLK* dev, int forced) { bind_struct* bs; logdebug("unbind_device(%4.4X)\n", dev->devnum); /* Error if device not bound */ if (!(bs = dev->bs)) { WRMSG (HHC01043, "E", SSID_TO_LCSS(dev->ssid), dev->devnum); return 0; /* (failure) */ } /* Is anyone still connected? */ if (dev->fd != -1) { /* Yes. Should we forcibly disconnect them? */ if (forced) { /* Yes. Then do so... */ close_socket( dev->fd ); dev->fd = -1; WRMSG (HHC01044, "I", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->bs->clientip, dev->bs->clientname, dev->bs->spec); } else { /* No. Then fail the request. */ WRMSG (HHC01045, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, dev->bs->clientip, dev->bs->clientname, dev->bs->spec); return 0; /* (failure) */ } } /* Remove the entry from our list */ obtain_lock( &bind_lock ); RemoveListEntry( &bs->bind_link ); SIGNAL_SOCKDEV_THREAD(); release_lock( &bind_lock ); WRMSG (HHC01046, "I",SSID_TO_LCSS(dev->ssid), dev->devnum, bs->spec); if (bs->sd != -1) close_socket (bs->sd); /* Unchain device and bind_struct from each another */ dev->bs = NULL; bs->dev = NULL; /* Discard the entry */ if ( bs->clientname ) free( bs->clientname ); if ( bs->clientip ) free( bs->clientip ); bs->clientname = NULL; bs->clientip = NULL; free ( bs->spec ); free ( bs ); return 1; /* (success) */ }
/*-------------------------------------------------------------------*/ void socket_device_connection_handler (bind_struct* bs) { struct sockaddr_in client; /* Client address structure */ struct hostent* pHE; /* Addr of hostent structure */ socklen_t namelen; /* Length of client structure*/ char* clientip; /* Addr of client ip address */ char* clientname; /* Addr of client hostname */ DEVBLK* dev; /* Device Block pointer */ int csock; /* Client socket */ dev = bs->dev; logdebug("socket_device_connection_handler(dev=%4.4X)\n", dev->devnum); /* Accept the connection... */ csock = accept(bs->sd, 0, 0); if (csock == -1) { WRMSG (HHC01000, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, "accept()", strerror(HSO_errno)); return; } /* Determine the connected client's IP address and hostname */ namelen = sizeof(client); clientip = NULL; clientname = "<unknown>"; if (1 && getpeername(csock, (struct sockaddr*) &client, &namelen) == 0 && (clientip = inet_ntoa(client.sin_addr)) != NULL && (pHE = gethostbyaddr((unsigned char*)(&client.sin_addr), sizeof(client.sin_addr), AF_INET)) != NULL && pHE->h_name && *pHE->h_name ) { clientname = (char*) pHE->h_name; } if (!clientip) clientip = "<unknown>"; /* Obtain the device lock */ obtain_lock (&dev->lock); /* Reject if device is busy or interrupt pending */ if (dev->busy || IOPENDING(dev) || (dev->scsw.flag3 & SCSW3_SC_PEND)) { close_socket( csock ); WRMSG (HHC01037, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, clientname, clientip, bs->spec); release_lock (&dev->lock); return; } /* Reject new client if previous client still connected */ if (dev->fd != -1) { close_socket( csock ); WRMSG (HHC01038, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, clientname, clientip, bs->spec, bs->clientname, bs->clientip); release_lock (&dev->lock); return; } /* Indicate that a client is now connected to this device */ dev->fd = csock; if (bs->clientip) free(bs->clientip); if (bs->clientname) free(bs->clientname); bs->clientip = strdup(clientip); bs->clientname = strdup(clientname); /* Call the boolean onconnect callback */ if (bs->fn && !bs->fn( bs->arg )) { /* Callback says it can't accept it */ close_socket( dev->fd ); dev->fd = -1; WRMSG (HHC01039, "E", SSID_TO_LCSS(dev->ssid), dev->devnum, clientname, clientip, bs->spec); release_lock (&dev->lock); return; } WRMSG (HHC01040, "I", SSID_TO_LCSS(dev->ssid), dev->devnum, clientname, clientip, bs->spec); release_lock (&dev->lock); device_attention (dev, CSW_DE); }
/*---------------------------------------------------------------------------*/ static void hao_message(char *buf) { char work[HAO_WKLEN]; char cmd[HAO_WKLEN]; regmatch_t rm[HAO_MAXCAPT+1]; int i, j, k, numcapt; size_t n; char *p; /* copy and strip spaces */ hao_cpstrp(work, buf); /* strip the herc prefix */ while(!strncmp(work, "herc", 4)) hao_cpstrp(work, &work[4]); /* Ignore the message if we should (e.g. if one of our own!) */ if (hao_ignoremsg( work )) return; /* serialize */ obtain_lock(&ao_lock); /* check all defined rules */ for(i = 0; i < HAO_MAXRULE; i++) { if(ao_tgt[i] && ao_cmd[i]) /* complete rule defined in this slot? */ { /* does this rule match our message? */ if (regexec(&ao_preg[i], work, HAO_MAXCAPT+1, rm, 0) == 0) { /* count the capturing group matches */ for (j = 0; j <= HAO_MAXCAPT && rm[j].rm_so >= 0; j++); numcapt = j - 1; /* copy the command and process replacement patterns */ for (n=0, p=ao_cmd[i]; *p && n < sizeof(cmd)-1; ) { /* replace $$ by $ */ if (*p == '$' && p[1] == '$') { cmd[n++] = '$'; p += 2; continue; } /* replace $` by characters to the left of the match */ if (*p == '$' && p[1] == '`') { n += hao_subst(work, 0, rm[0].rm_so, cmd, n, sizeof(cmd)); p += 2; continue; } /* replace $' by characters to the right of the match */ if (*p == '$' && p[1] == '\'') { n += hao_subst(work, rm[0].rm_eo, strlen(work), cmd, n, sizeof(cmd)); p += 2; continue; } /* replace $1..$99 by the corresponding capturing group */ if (*p == '$' && isdigit(p[1])) { if (isdigit(p[2])) { j = (p[1]-'0') * 10 + (p[2]-'0'); k = 3; } else { j = p[1]-'0'; k = 2; } if (j > 0 && j <= numcapt) { n += hao_subst(work, rm[j].rm_so, rm[j].rm_eo, cmd, n, sizeof(cmd)); p += k; continue; } } /* otherwise copy one character */ cmd[n++] = *p++; } cmd[n] = '\0'; /* issue command for this rule */ WRMSG(HHC00081, "I", i, cmd); panel_command(cmd); } } } release_lock(&ao_lock); }
/*---------------------------------------------------------------------------*/ static void hao_cmd(char *arg) { int i; int j; /* serialize */ obtain_lock(&ao_lock); /* find the free slot */ for(i = 0; ao_cmd[i] && i < HAO_MAXRULE; i++); /* check for table full -> so tgt cmd expected */ if(i == HAO_MAXRULE) { release_lock(&ao_lock); WRMSG(HHC00071, "E", "command", HAO_MAXRULE); return; } /* check if target is given */ if(!ao_tgt[i]) { release_lock(&ao_lock); WRMSG(HHC00072, "E", "cmd", "tgt"); return; } /* check for empty cmd string */ if(!strlen(arg)) { release_lock(&ao_lock); WRMSG(HHC00073, "E", "command"); return; } /* check for hao command, prevent deadlock */ for(j = 0; !strncasecmp(&arg[j], "herc ", 4); j += 5); if(!strcasecmp(&arg[j], "hao") || !strncasecmp(&arg[j], "hao ", 4)) { release_lock(&ao_lock); WRMSG(HHC00078, "E"); return; } /* check for possible loop */ for(j = 0; j < HAO_MAXRULE; j++) { if(ao_tgt[j] && !regexec(&ao_preg[j], arg, 0, NULL, 0)) { release_lock(&ao_lock); WRMSG(HHC00076, "E", "command", "target", j); return; } } /* duplicate the string */ ao_cmd[i] = strdup(arg); /* check duplication */ if(!ao_cmd[i]) { release_lock(&ao_lock); WRMSG(HHC00075, "E", "strdup()", strerror(ENOMEM)); return; } release_lock(&ao_lock); WRMSG(HHC00077, "I", "command", i); }
/*---------------------------------------------------------------------------*/ static void hao_tgt(char *arg) { int i; int j; int rc; char work[HAO_WKLEN]; /* serialize */ obtain_lock(&ao_lock); /* find a free slot */ for(i = 0; ao_tgt[i] && i < HAO_MAXRULE; i++) /* check for table full */ if(i == HAO_MAXRULE) { release_lock(&ao_lock); WRMSG(HHC00071, "E", "target", HAO_MAXRULE); return; } /* check if not command is expected */ for(j = 0; j < HAO_MAXRULE; j++) { if(ao_tgt[j] && !ao_cmd[j]) { release_lock(&ao_lock); WRMSG(HHC00072, "E", "tgt", "cmd"); return; } } /* check for empty target */ if(!strlen(arg)) { release_lock(&ao_lock); WRMSG(HHC00073, "E", "target"); return; } /* check for duplicate targets */ for(j = 0; j < HAO_MAXRULE; j++) { if(ao_tgt[j] && !strcmp(arg, ao_tgt[j])) { release_lock(&ao_lock); WRMSG(HHC00074, "E", j); return; } } /* compile the target string */ rc = regcomp(&ao_preg[i], arg, REG_EXTENDED); /* check for error */ if(rc) { release_lock(&ao_lock); /* place error in work */ regerror(rc, (const regex_t *) &ao_preg[i], work, HAO_WKLEN); WRMSG(HHC00075, "E", "regcomp()", work); return; } /* check for possible loop */ for(j = 0; j < HAO_MAXRULE; j++) { if(ao_cmd[j] && !regexec(&ao_preg[i], ao_cmd[j], 0, NULL, 0)) { release_lock(&ao_lock); regfree(&ao_preg[i]); WRMSG(HHC00076, "E", "target", "command", i); return; } } /* duplicate the target */ ao_tgt[i] = strdup(arg); /* check duplication */ if(!ao_tgt[i]) { release_lock(&ao_lock); regfree(&ao_preg[i]); WRMSG(HHC00075, "E", "strdup()", strerror(ENOMEM)); return; } release_lock(&ao_lock); WRMSG(HHC00077, "I", "target", i); }
/*-------------------------------------------------------------------*/ 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 connected 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 */