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