void cgibin_reg_control(WEBBLK *webblk) { int i; REGS *regs; regs = sysblk.regs[sysblk.pcpu]; if (!regs) regs = &sysblk.dummyregs; html_header(webblk); hprintf(webblk->sock, "<H2>Control Registers</H2>\n"); hprintf(webblk->sock, "<PRE>\n"); if(regs->arch_mode != ARCH_900) for (i = 0; i < 16; i++) hprintf(webblk->sock, "CR%2.2d=%8.8X%s", i, regs->CR_L(i), ((i & 0x03) == 0x03) ? "\n" : "\t"); else for (i = 0; i < 16; i++) hprintf(webblk->sock, "CR%1.1X=%16.16" I64_FMT "X%s", i, (U64)regs->CR_G(i), ((i & 0x03) == 0x03) ? "\n" : " "); hprintf(webblk->sock, "</PRE>\n"); html_footer(webblk); }
void cgibin_debug_registers(WEBBLK *webblk) { int i, cpu = 0; int select_gr, select_cr, select_ar; char *value; REGS *regs; if((value = cgi_variable(webblk,"cpu"))) cpu = atoi(value); if((value = cgi_variable(webblk,"select_gr")) && *value == 'S') select_gr = 1; else select_gr = 0; if((value = cgi_variable(webblk,"select_cr")) && *value == 'S') select_cr = 1; else select_cr = 0; if((value = cgi_variable(webblk,"select_ar")) && *value == 'S') select_ar = 1; else select_ar = 0; /* Validate cpu number */ if (cpu < 0 || cpu >= MAX_CPU || !IS_CPU_ONLINE(cpu)) for (cpu = 0; cpu < MAX_CPU; cpu++) if(IS_CPU_ONLINE(cpu)) break; if(cpu < MAX_CPU) regs = sysblk.regs[cpu]; else regs = sysblk.regs[sysblk.pcpu]; if (!regs) regs = &sysblk.dummyregs; if((value = cgi_variable(webblk,"alter_gr")) && *value == 'A') { for(i = 0; i < 16; i++) { char regname[16]; sprintf(regname,"alter_gr%d",i); if((value = cgi_variable(webblk,regname))) { if(regs->arch_mode != ARCH_900) sscanf(value,"%"I32_FMT"x",&(regs->GR_L(i))); else sscanf(value,"%"I64_FMT"x",&(regs->GR_G(i))); } } } if((value = cgi_variable(webblk,"alter_cr")) && *value == 'A') { for(i = 0; i < 16; i++) { char regname[16]; sprintf(regname,"alter_cr%d",i); if((value = cgi_variable(webblk,regname))) { if(regs->arch_mode != ARCH_900) sscanf(value,"%"I32_FMT"x",&(regs->CR_L(i))); else sscanf(value,"%"I64_FMT"x",&(regs->CR_G(i))); } } } if((value = cgi_variable(webblk,"alter_ar")) && *value == 'A') { for(i = 0; i < 16; i++) { char regname[16]; sprintf(regname,"alter_ar%d",i); if((value = cgi_variable(webblk,regname))) sscanf(value,"%x",&(regs->AR(i))); } } html_header(webblk); hprintf(webblk->sock,"<form method=post>\n" "<select type=submit name=cpu>\n"); for(i = 0; i < MAX_CPU; i++) if(IS_CPU_ONLINE(i)) hprintf(webblk->sock,"<option value=%d%s>CPU%4.4X</option>\n", i,i==cpu?" selected":"",i); hprintf(webblk->sock,"</select>\n" "<input type=submit name=selcpu value=\"Select\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_gr value=%c>\n" "<input type=hidden name=select_cr value=%c>\n" "<input type=hidden name=select_ar value=%c>\n", cpu, select_gr?'S':'H',select_cr?'S':'H',select_ar?'S':'H'); hprintf(webblk->sock,"Mode: %s\n",get_arch_mode_string(regs)); hprintf(webblk->sock,"</form>\n"); if(!select_gr) { hprintf(webblk->sock,"<form method=post>\n" "<input type=submit name=select_gr " "value=\"Select General Registers\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_cr value=%c>\n" "<input type=hidden name=select_ar value=%c>\n" "</form>\n",cpu,select_cr?'S':'H',select_ar?'S':'H'); } else { hprintf(webblk->sock,"<form method=post>\n" "<input type=submit name=select_gr " "value=\"Hide General Registers\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_cr value=%c>\n" "<input type=hidden name=select_ar value=%c>\n" "</form>\n",cpu,select_cr?'S':'H',select_ar?'S':'H'); hprintf(webblk->sock,"<form method=post>\n" "<table>\n"); for(i = 0; i < 16; i++) { if(regs->arch_mode != ARCH_900) hprintf(webblk->sock,"%s<td>GR%d</td><td><input type=text name=alter_gr%d size=8 " "value=%8.8X></td>\n%s", (i&3)==0?"<tr>\n":"",i,i,regs->GR_L(i),((i&3)==3)?"</tr>\n":""); else hprintf(webblk->sock,"%s<td>GR%d</td><td><input type=text name=alter_gr%d size=16 " "value=%16.16" I64_FMT "X></td>\n%s", (i&3)==0?"<tr>\n":"",i,i,(U64)regs->GR_G(i),((i&3)==3)?"</tr>\n":""); } hprintf(webblk->sock,"</table>\n" "<input type=submit name=refresh value=\"Refresh\">\n" "<input type=submit name=alter_gr value=\"Alter\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_gr value=S>\n" "<input type=hidden name=select_cr value=%c>\n" "<input type=hidden name=select_ar value=%c>\n" "</form>\n",cpu,select_cr?'S':'H',select_ar?'S':'H'); } if(!select_cr) { hprintf(webblk->sock,"<form method=post>\n" "<input type=submit name=select_cr " "value=\"Select Control Registers\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_gr value=%c>\n" "<input type=hidden name=select_ar value=%c>\n" "</form>\n",cpu,select_gr?'S':'H',select_ar?'S':'H'); } else { hprintf(webblk->sock,"<form method=post>\n" "<input type=submit name=select_cr " "value=\"Hide Control Registers\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_gr value=%c>\n" "<input type=hidden name=select_ar value=%c>\n" "</form>\n",cpu,select_gr?'S':'H',select_ar?'S':'H'); hprintf(webblk->sock,"<form method=post>\n" "<table>\n"); for(i = 0; i < 16; i++) { if(regs->arch_mode != ARCH_900) hprintf(webblk->sock,"%s<td>CR%d</td><td><input type=text name=alter_cr%d size=8 " "value=%8.8X></td>\n%s", (i&3)==0?"<tr>\n":"",i,i,regs->CR_L(i),((i&3)==3)?"</tr>\n":""); else hprintf(webblk->sock,"%s<td>CR%d</td><td><input type=text name=alter_cr%d size=16 " "value=%16.16" I64_FMT "X></td>\n%s", (i&3)==0?"<tr>\n":"",i,i,(U64)regs->CR_G(i),((i&3)==3)?"</tr>\n":""); } hprintf(webblk->sock,"</table>\n" "<input type=submit name=refresh value=\"Refresh\">\n" "<input type=submit name=alter_cr value=\"Alter\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_cr value=S>\n" "<input type=hidden name=select_gr value=%c>\n" "<input type=hidden name=select_ar value=%c>\n" "</form>\n",cpu,select_gr?'S':'H',select_ar?'S':'H'); } if(regs->arch_mode != ARCH_370) { if(!select_ar) { hprintf(webblk->sock,"<form method=post>\n" "<input type=submit name=select_ar " "value=\"Select Access Registers\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_gr value=%c>\n" "<input type=hidden name=select_cr value=%c>\n" "</form>\n",cpu,select_gr?'S':'H',select_cr?'S':'H'); } else { hprintf(webblk->sock,"<form method=post>\n" "<input type=submit name=select_ar " "value=\"Hide Access Registers\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_gr value=%c>\n" "<input type=hidden name=select_cr value=%c>\n" "</form>\n",cpu,select_gr?'S':'H',select_cr?'S':'H'); hprintf(webblk->sock,"<form method=post>\n" "<table>\n"); for(i = 0; i < 16; i++) { hprintf(webblk->sock,"%s<td>AR%d</td><td><input type=text name=alter_ar%d size=8 " "value=%8.8X></td>\n%s", (i&3)==0?"<tr>\n":"",i,i,regs->AR(i),((i&3)==3)?"</tr>\n":""); } hprintf(webblk->sock,"</table>\n" "<input type=submit name=refresh value=\"Refresh\">\n" "<input type=submit name=alter_ar value=\"Alter\">\n" "<input type=hidden name=cpu value=%d>\n" "<input type=hidden name=select_gr value=%c>\n" "<input type=hidden name=select_cr value=%c>\n" "<input type=hidden name=select_ar value=S>\n" "</form>\n",cpu,select_gr?'S':'H',select_cr?'S':'H'); } } html_footer(webblk); }
int suspend_cmd(int argc, char *argv[],char *cmdline) { char *fn = SR_DEFAULT_FILENAME; SR_FILE *file; CPU_BITMAP started_mask; struct timeval tv; time_t tt; int i, j, rc; REGS *regs; DEVBLK *dev; IOINT *ioq; BYTE psw[16]; UNREFERENCED(cmdline); if (argc > 2) { // "SR: too many arguments" WRMSG(HHC02000, "E"); return -1; } if (argc == 2) fn = argv[1]; file = SR_OPEN (fn, "wb"); if (file == NULL) { // "SR: error in function '%s': '%s'" WRMSG(HHC02001, "E","open()",strerror(errno)); return -1; } TRACE("SR: Begin Suspend Processing...\n"); /* Save CPU state and stop all CPU's */ TRACE("SR: Stopping All CPUs...\n"); OBTAIN_INTLOCK(NULL); started_mask = sysblk.started_mask; while (sysblk.started_mask) { for (i = 0; i < sysblk.maxcpu; i++) { if (IS_CPU_ONLINE(i)) { sysblk.regs[i]->cpustate = CPUSTATE_STOPPING; ON_IC_INTERRUPT(sysblk.regs[i]); signal_condition(&sysblk.regs[i]->intcond); } } RELEASE_INTLOCK(NULL); usleep (1000); OBTAIN_INTLOCK(NULL); } RELEASE_INTLOCK(NULL); /* Wait for I/O queue to clear out */ TRACE("SR: Waiting for I/O Queue to clear...\n"); #ifdef OPTION_FISHIO SLEEP (2); #else obtain_lock (&sysblk.ioqlock); while (sysblk.ioq) { release_lock (&sysblk.ioqlock); usleep (1000); obtain_lock (&sysblk.ioqlock); } release_lock (&sysblk.ioqlock); #endif /* Wait for active I/Os to complete */ TRACE("SR: Waiting for Active I/Os to Complete...\n"); for (i = 1; i < 5000; i++) { dev = sr_active_devices(); if (dev == NULL) break; if (i % 500 == 0) { // "SR: waiting for device %04X" WRMSG(HHC02002, "W", dev->devnum); } usleep (10000); } if (dev != NULL) { // "SR: device %04X still busy, proceeding anyway" WRMSG(HHC02003, "W",dev->devnum); } /* Write header */ TRACE("SR: Writing File Header...\n"); SR_WRITE_STRING(file, SR_HDR_ID, SR_ID); SR_WRITE_STRING(file, SR_HDR_VERSION, VERSION); gettimeofday(&tv, NULL); tt = tv.tv_sec; SR_WRITE_STRING(file, SR_HDR_DATE, ctime(&tt)); /* Write system data */ TRACE("SR: Saving System Data...\n"); SR_WRITE_STRING(file,SR_SYS_ARCH_NAME,arch_name[sysblk.arch_mode]); SR_WRITE_VALUE (file,SR_SYS_STARTED_MASK,started_mask,sizeof(started_mask)); SR_WRITE_VALUE (file,SR_SYS_MAINSIZE,sysblk.mainsize,sizeof(sysblk.mainsize)); TRACE("SR: Saving MAINSTOR...\n"); SR_WRITE_BUF (file,SR_SYS_MAINSTOR,sysblk.mainstor,sysblk.mainsize); SR_WRITE_VALUE (file,SR_SYS_SKEYSIZE,(sysblk.mainsize/STORAGE_KEY_UNITSIZE),sizeof(U32)); TRACE("SR: Saving Storage Keys...\n"); SR_WRITE_BUF (file,SR_SYS_STORKEYS,sysblk.storkeys,sysblk.mainsize/STORAGE_KEY_UNITSIZE); SR_WRITE_VALUE (file,SR_SYS_XPNDSIZE,sysblk.xpndsize,sizeof(sysblk.xpndsize)); TRACE("SR: Saving Expanded Storage...\n"); SR_WRITE_BUF (file,SR_SYS_XPNDSTOR,sysblk.xpndstor,4096*sysblk.xpndsize); SR_WRITE_VALUE (file,SR_SYS_CPUID,sysblk.cpuid,sizeof(sysblk.cpuid)); SR_WRITE_VALUE (file,SR_SYS_IPLDEV,sysblk.ipldev,sizeof(sysblk.ipldev)); SR_WRITE_VALUE (file,SR_SYS_IPLCPU,sysblk.iplcpu,sizeof(sysblk.iplcpu)); SR_WRITE_VALUE (file,SR_SYS_MBO,sysblk.mbo,sizeof(sysblk.mbo)); SR_WRITE_VALUE (file,SR_SYS_MBK,sysblk.mbk,sizeof(sysblk.mbk)); SR_WRITE_VALUE (file,SR_SYS_MBM,sysblk.mbm,sizeof(sysblk.mbm)); SR_WRITE_VALUE (file,SR_SYS_MBD,sysblk.mbd,sizeof(sysblk.mbd)); for (ioq = sysblk.iointq; ioq; ioq = ioq->next) if (ioq->pcipending) { SR_WRITE_VALUE(file,SR_SYS_PCIPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16)); SR_WRITE_VALUE(file,SR_SYS_PCIPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum)); } else if (ioq->attnpending) { SR_WRITE_VALUE(file,SR_SYS_ATTNPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16)); SR_WRITE_VALUE(file,SR_SYS_ATTNPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum)); } else { SR_WRITE_VALUE(file,SR_SYS_IOPENDING_LCSS, SSID_TO_LCSS(ioq->dev->ssid),sizeof(U16)); SR_WRITE_VALUE(file,SR_SYS_IOPENDING, ioq->dev->devnum,sizeof(ioq->dev->devnum)); } for (i = 0; i < 8; i++) SR_WRITE_VALUE(file,SR_SYS_CHP_RESET+i,sysblk.chp_reset[i],sizeof(sysblk.chp_reset[0])); SR_WRITE_VALUE (file,SR_SYS_SERVPARM,sysblk.servparm,sizeof(sysblk.servparm)); SR_WRITE_VALUE (file,SR_SYS_SIGINTREQ,sysblk.sigintreq,1); SR_WRITE_STRING(file,SR_SYS_LOADPARM,str_loadparm()); SR_WRITE_VALUE (file,SR_SYS_INTS_STATE,sysblk.ints_state,sizeof(sysblk.ints_state)); SR_WRITE_HDR(file, SR_DELIMITER, 0); /* Save service console state */ TRACE("SR: Saving Service Console State...\n"); SR_WRITE_HDR(file, SR_SYS_SERVC, 0); servc_hsuspend(file); SR_WRITE_HDR(file, SR_DELIMITER, 0); /* Save clock state */ TRACE("SR: Saving Clock State...\n"); SR_WRITE_HDR(file, SR_SYS_CLOCK, 0); clock_hsuspend(file); SR_WRITE_HDR(file, SR_DELIMITER, 0); /* Write CPU data */ for (i = 0; i < sysblk.maxcpu; i++) { if (!IS_CPU_ONLINE(i)) continue; TRACE("SR: Saving CPU %d Data...\n", i); regs = sysblk.regs[i]; SR_WRITE_VALUE(file, SR_CPU, i, sizeof(i)); SR_WRITE_VALUE(file, SR_CPU_ARCHMODE, regs->arch_mode,sizeof(regs->arch_mode)); SR_WRITE_VALUE(file, SR_CPU_PX, regs->PX_G,sizeof(regs->PX_G)); copy_psw (regs, psw); SR_WRITE_BUF(file, SR_CPU_PSW, psw, 16); for (j = 0; j < 16; j++) SR_WRITE_VALUE(file, SR_CPU_GR+j, regs->GR_G(j),sizeof(regs->GR_G(0))); for (j = 0; j < 16; j++) SR_WRITE_VALUE(file, SR_CPU_CR+j, regs->CR_G(j),sizeof(regs->CR_G(0))); for (j = 0; j < 16; j++) SR_WRITE_VALUE(file, SR_CPU_AR+j, regs->ar[j],sizeof(regs->ar[0])); for (j = 0; j < 32; j++) SR_WRITE_VALUE(file, SR_CPU_FPR+j, regs->fpr[j],sizeof(regs->fpr[0])); SR_WRITE_VALUE(file, SR_CPU_FPC, regs->fpc, sizeof(regs->fpc)); SR_WRITE_VALUE(file, SR_CPU_DXC, regs->dxc, sizeof(regs->dxc)); SR_WRITE_VALUE(file, SR_CPU_MC, regs->MC_G, sizeof(regs->MC_G)); SR_WRITE_VALUE(file, SR_CPU_EA, regs->EA_G, sizeof(regs->EA_G)); SR_WRITE_VALUE(file, SR_CPU_PTIMER, cpu_timer(regs), sizeof(S64)); SR_WRITE_VALUE(file, SR_CPU_CLKC, regs->clkc, sizeof(regs->clkc)); SR_WRITE_VALUE(file, SR_CPU_CHANSET, regs->chanset, sizeof(regs->chanset)); SR_WRITE_VALUE(file, SR_CPU_TODPR, regs->todpr, sizeof(regs->todpr)); SR_WRITE_VALUE(file, SR_CPU_MONCLASS, regs->monclass, sizeof(regs->monclass)); SR_WRITE_VALUE(file, SR_CPU_EXCARID, regs->excarid, sizeof(regs->excarid)); SR_WRITE_VALUE(file, SR_CPU_BEAR, regs->bear, sizeof(regs->bear)); SR_WRITE_VALUE(file, SR_CPU_OPNDRID, regs->opndrid, sizeof(regs->opndrid)); SR_WRITE_VALUE(file, SR_CPU_CHECKSTOP, regs->checkstop, 1); SR_WRITE_VALUE(file, SR_CPU_HOSTINT, regs->hostint, 1); SR_WRITE_VALUE(file, SR_CPU_EXECFLAG, regs->execflag, 1); // SR_WRITE_VALUE(file, SR_CPU_INSTVALID, regs->instvalid, 1); SR_WRITE_VALUE(file, SR_CPU_PERMODE, regs->permode, 1); SR_WRITE_VALUE(file, SR_CPU_LOADSTATE, regs->loadstate, 1); SR_WRITE_VALUE(file, SR_CPU_INVALIDATE, regs->invalidate, 1); SR_WRITE_VALUE(file, SR_CPU_SIGPRESET, regs->sigpreset, 1); SR_WRITE_VALUE(file, SR_CPU_SIGPIRESET, regs->sigpireset, 1); SR_WRITE_VALUE(file, SR_CPU_INTS_STATE, regs->ints_state, sizeof(regs->ints_state)); SR_WRITE_VALUE(file, SR_CPU_INTS_MASK, regs->ints_mask, sizeof(regs->ints_mask)); for (j = 0; j < sysblk.maxcpu; j++) SR_WRITE_VALUE(file, SR_CPU_MALFCPU+j, regs->malfcpu[j], sizeof(regs->malfcpu[0])); for (j = 0; j < sysblk.maxcpu; j++) SR_WRITE_VALUE(file, SR_CPU_EMERCPU+j, regs->emercpu[j], sizeof(regs->emercpu[0])); SR_WRITE_VALUE(file, SR_CPU_EXTCCPU, regs->extccpu, sizeof(regs->extccpu)); SR_WRITE_HDR(file, SR_DELIMITER, 0); } /* Write Device data */ for (dev = sysblk.firstdev; dev; dev = dev->nextdev) { if (!(dev->pmcw.flag5 & PMCW5_V)) continue; TRACE("SR: Saving Device %4.4X...\n", dev->devnum); /* These fields must come first so the device could be attached */ SR_WRITE_VALUE(file, SR_DEV, dev->devnum, sizeof(dev->devnum)); SR_WRITE_VALUE(file, SR_DEV_LCSS, SSID_TO_LCSS(dev->ssid), sizeof(U16)); SR_WRITE_VALUE(file, SR_DEV_ARGC, dev->argc, sizeof(dev->argc)); for (i = 0; i < dev->argc; i++) if (dev->argv[i]) { SR_WRITE_STRING(file, SR_DEV_ARGV, dev->argv[i]); } else { SR_WRITE_STRING(file, SR_DEV_ARGV, ""); } SR_WRITE_STRING(file, SR_DEV_TYPNAME, dev->typname); /* Common device fields */ SR_WRITE_BUF (file, SR_DEV_ORB, &dev->orb, sizeof(ORB)); SR_WRITE_BUF (file, SR_DEV_PMCW, &dev->pmcw, sizeof(PMCW)); SR_WRITE_BUF (file, SR_DEV_SCSW, &dev->scsw, sizeof(SCSW)); SR_WRITE_BUF (file, SR_DEV_PCISCSW, &dev->pciscsw, sizeof(SCSW)); SR_WRITE_BUF (file, SR_DEV_ATTNSCSW, &dev->attnscsw, sizeof(SCSW)); SR_WRITE_BUF (file, SR_DEV_CSW, dev->csw, 8); SR_WRITE_BUF (file, SR_DEV_PCICSW, dev->pcicsw, 8); SR_WRITE_BUF (file, SR_DEV_ATTNCSW, dev->attncsw, 8); SR_WRITE_BUF (file, SR_DEV_ESW, &dev->esw, sizeof(ESW)); SR_WRITE_BUF (file, SR_DEV_ECW, dev->ecw, 32); SR_WRITE_BUF (file, SR_DEV_SENSE, dev->sense, 32); SR_WRITE_VALUE(file, SR_DEV_PGSTAT, dev->pgstat, sizeof(dev->pgstat)); SR_WRITE_BUF (file, SR_DEV_PGID, dev->pgid, 11); /* By Adrian - SR_DEV_DRVPWD */ SR_WRITE_BUF (file, SR_DEV_DRVPWD, dev->drvpwd, 11); SR_WRITE_VALUE(file, SR_DEV_BUSY, dev->busy, 1); SR_WRITE_VALUE(file, SR_DEV_RESERVED, dev->reserved, 1); SR_WRITE_VALUE(file, SR_DEV_SUSPENDED, dev->suspended, 1); SR_WRITE_VALUE(file, SR_DEV_PCIPENDING, dev->pcipending, 1); SR_WRITE_VALUE(file, SR_DEV_ATTNPENDING, dev->attnpending, 1); SR_WRITE_VALUE(file, SR_DEV_PENDING, dev->pending, 1); SR_WRITE_VALUE(file, SR_DEV_STARTPENDING, dev->startpending, 1); SR_WRITE_VALUE(file, SR_DEV_CRWPENDING, dev->crwpending, 1); SR_WRITE_VALUE(file, SR_DEV_CCWADDR, dev->ccwaddr, sizeof(dev->ccwaddr)); SR_WRITE_VALUE(file, SR_DEV_IDAPMASK, dev->idapmask, sizeof(dev->idapmask)); SR_WRITE_VALUE(file, SR_DEV_IDAWFMT, dev->idawfmt, sizeof(dev->idawfmt)); SR_WRITE_VALUE(file, SR_DEV_CCWFMT, dev->ccwfmt, sizeof(dev->ccwfmt)); SR_WRITE_VALUE(file, SR_DEV_CCWKEY, dev->ccwkey, sizeof(dev->ccwkey)); /* Device type specific data */ SR_WRITE_VALUE(file, SR_DEV_DEVTYPE, dev->devtype, sizeof(dev->devtype)); if (dev->hnd->hsuspend) { rc = (dev->hnd->hsuspend) (dev, file); if (rc < 0) goto sr_error_exit; } SR_WRITE_HDR(file, SR_DELIMITER, 0); } TRACE("SR: Writing EOF\n"); SR_WRITE_HDR(file, SR_EOF, 0); SR_CLOSE (file); TRACE("SR: Suspend Complete; shutting down...\n"); /* Shutdown */ do_shutdown(); return 0; sr_error_exit: // "SR: error processing file '%s'" WRMSG(HHC02004, "E", fn); SR_CLOSE (file); return -1; }