/*--------------------------------------------------------------------*/ DLL_EXPORT void mpc_display_ptp_th_etc( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, BYTE bDir, int iLimit ) { MPC_RRH* pMPC_RRH; int iForRRH; U32 uOffRRH; U16 uNumRRH; /* Display MPC_TH. */ mpc_display_th( pDEVBLK, pMPC_TH, bDir ); /* Get the number of MPC_RRHs and the displacement from */ /* the start of the MPC_TH to the first (or only) MPC_RRH. */ FETCH_HW( uNumRRH, pMPC_TH->numrrh ); FETCH_FW( uOffRRH, pMPC_TH->offrrh ); /* Process each of the MPC_RRHs. */ for( iForRRH = 1; iForRRH <= uNumRRH; iForRRH++ ) { /* Point to the first or subsequent MPC_RRH. */ pMPC_RRH = (MPC_RRH*)((BYTE*)pMPC_TH + uOffRRH); /* Display the MPC_RRH etc. */ if( pMPC_RRH->proto == PROTOCOL_LAYER2 && pMPC_RRH->type == RRH_TYPE_CM ) { /* Display MPC_RRH and following packet data. */ mpc_display_rrh_and_pkt( pDEVBLK, pMPC_TH, pMPC_RRH, bDir, iLimit ); } else if( pMPC_RRH->proto == PROTOCOL_LAYER2 && pMPC_RRH->type == RRH_TYPE_IPA ) { /* Display MPC_RRH and following MPC_PIX etc. */ mpc_display_rrh_and_pix( pDEVBLK, pMPC_TH, pMPC_RRH, bDir ); } else if( pMPC_RRH->proto == PROTOCOL_UNKNOWN ) { /* Display MPC_RRH and following MPC_PUK etc. */ mpc_display_rrh_and_puk( pDEVBLK, pMPC_TH, pMPC_RRH, bDir ); } else { /* Display MPC_RRH */ mpc_display_rrh( pDEVBLK, pMPC_RRH, bDir ); } /* Get the displacement from the start of the MPC_TH to the */ /* next MPC_RRH. pMPC_RRH->offrrh will contain zero if this */ /* is the last MPC_RRH. */ FETCH_FW( uOffRRH, pMPC_RRH->offrrh ); } return; } /* End function mpc_display_ptp_th_etc() */
static int ARCH_DEP(scedio_ior)(SCCB_SCEDIOR_BK *scedior_bk) { U32 origin; char image[9]; S32 size; unsigned int i; char filename[MAX_PATH]; FETCH_FW(origin,scedior_bk->origin); /* Convert image filename to null terminated ascii string */ for(i = 0; i < sizeof(image)-1 && scedior_bk->image[i] != 0x40; i++) image[i] = guest_to_host((int)scedior_bk->image[i]); image[i] = '\0'; /* Ensure file access is allowed and within specified directory */ if(!check_sce_filepath(image,filename)) { if(errno != ENOENT) WRMSG (HHC00604, "E", filename, image, strerror(errno)); return FALSE; } size = ARCH_DEP(load_main)(filename,origin,0); return (size >= 0) ? TRUE : FALSE; }
/*--------------------------------------------------------------------*/ DLL_EXPORT void mpc_display_th( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, BYTE bDir ) { U32 uOffRRH; // Display the MPC_TH. FETCH_FW( uOffRRH, pMPC_TH->offrrh ); mpc_display_stuff( pDEVBLK, "TH", (BYTE*)pMPC_TH, uOffRRH, bDir ); return; } /* End function mpc_display_th() */
void cgibin_debug_storage(WEBBLK *webblk) { int i, j; char *value; U32 addr = 0; /* INCOMPLETE * no storage alter * no storage type (abs/real/prim virt/sec virt/access reg virt) * no cpu selection for storage other then abs */ if((value = cgi_variable(webblk,"alter_a0"))) sscanf(value,"%x",&addr); addr &= ~0x0F; html_header(webblk); hprintf(webblk->sock,"<form method=post>\n" "<table>\n"); if(addr > sysblk.mainsize || (addr + 128) > sysblk.mainsize) addr = sysblk.mainsize - 128; for(i = 0; i < 128;) { if(i == 0) hprintf(webblk->sock,"<tr>\n" "<td><input type=text name=alter_a0 size=8 value=%8.8X>" "<input type=hidden name=alter_a1 value=%8.8X></td>\n" "<td><input type=submit name=refresh value=\"Refresh\"></td>\n", i + addr, i + addr); else hprintf(webblk->sock,"<tr>\n" "<td align=center>%8.8X</td>\n" "<td></td>\n", i + addr); for(j = 0; j < 4; i += 4, j++) { U32 m; FETCH_FW(m,sysblk.mainstor + i + addr); hprintf(webblk->sock,"<td><input type=text name=alter_m%d size=8 value=%8.8X></td>\n",i,m); } hprintf(webblk->sock,"</tr>\n"); } hprintf(webblk->sock,"</table>\n" "</form>\n"); html_footer(webblk); }
/*--------------------------------------------------------------------*/ DLL_EXPORT void mpc_display_rrh_and_pdu( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir, int iLimit ) { MPC_PH* pMPC_PH; U16 uNumPH; U16 uOffPH; int iForPH; int iDone; U32 uLenData; U32 uOffData; BYTE* pData; /* Display the MPC_RRH.*/ FETCH_HW( uOffPH, pMPC_RRH->offph ); mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir ); /* Display the MPC_PH(s). */ FETCH_HW( uNumPH, pMPC_RRH->numph ); pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH); for( iForPH = 1; iForPH <= uNumPH; iForPH++ ) { mpc_display_stuff( pDEVBLK, "PH", (BYTE*)pMPC_PH, SIZE_PH, bDir ); pMPC_PH = (MPC_PH*)((BYTE*)pMPC_PH + SIZE_PH); } /* Display the data referenced by the MPC_PH(s). */ /* if limit is negative or a silly number, don't display the */ /* data. If limit is zero, display all of the data, otherwise */ /* limit the length of the data displayed. */ iDone = 0; if( iLimit >= 0 && iLimit <= 65535 ) { pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH); for( iForPH = 1; iForPH <= uNumPH; iForPH++ ) { FETCH_F3( uLenData, pMPC_PH->lendata ); FETCH_FW( uOffData, pMPC_PH->offdata ); pData = (BYTE*)pMPC_TH + uOffData; if( iLimit > 0 ) { if( iDone >= iLimit ) break; if( (int)uLenData > ( iLimit - iDone ) ) uLenData = ( iLimit - iDone ); iDone =+ uLenData; } mpc_display_stuff( pDEVBLK, "PDU", pData, uLenData, bDir ); pMPC_PH = (MPC_PH*)((BYTE*)pMPC_PH + SIZE_PH); } } return; } /* End function mpc_display_rrh_and_pdu() */
/*--------------------------------------------------------------------*/ DLL_EXPORT void mpc_display_rrh_and_ipa( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir ) { MPC_PH* pMPC_PH; MPC_IPA* pMPC_IPA; BYTE* pMPC_IPA_CMD; U32 uOffData; U32 uLenData; U16 uOffPH; int iLenIPA; int iLenCmd; // Display the MPC_RRH. FETCH_HW( uOffPH, pMPC_RRH->offph ); mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir ); // Point to and display the MPC_PH. pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH); mpc_display_stuff( pDEVBLK, "PH", (BYTE*)pMPC_PH, SIZE_PH, bDir ); /* Point to and display the MPC_IPA (and commands, if any). */ FETCH_F3( uLenData, pMPC_PH->lendata ); FETCH_FW( uOffData, pMPC_PH->offdata ); if( uLenData > sizeof(MPC_IPA) ) { iLenIPA = sizeof(MPC_IPA); iLenCmd = uLenData - sizeof(MPC_IPA); } else { iLenIPA = uLenData; iLenCmd = 0; } pMPC_IPA = (MPC_IPA*)((BYTE*)pMPC_TH + uOffData); mpc_display_stuff( pDEVBLK, "IPA", (BYTE*)pMPC_IPA, iLenIPA, bDir ); if( iLenCmd ) { pMPC_IPA_CMD = (BYTE*)pMPC_IPA + iLenIPA; mpc_display_stuff( pDEVBLK, "Cmd", (BYTE*)pMPC_IPA_CMD, iLenCmd, bDir ); } return; } /* End function mpc_display_rrh_and_ipa() */
/*--------------------------------------------------------------------*/ DLL_EXPORT MPC_PUK* mpc_point_puk( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH ) { MPC_PH* pMPC_PH; MPC_PUK* pMPC_PUK; U32 uOffData; U16 uOffPH; UNREFERENCED( pDEVBLK ); // Point to the MPC_PH. FETCH_HW( uOffPH, pMPC_RRH->offph ); pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH); // Get the length of and point to the data referenced by the // MPC_PH. The data contain a MPC_PUK and one or more MPC_PUSs. FETCH_FW( uOffData, pMPC_PH->offdata ); pMPC_PUK = (MPC_PUK*)((BYTE*)pMPC_TH + uOffData); return pMPC_PUK; } /* End function mpc_point_puk() */
/* followed by a single MPC_PIX. */ DLL_EXPORT void mpc_display_rrh_and_pix( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir ) { MPC_PH* pMPC_PH; MPC_PIX* pMPC_PIX; U32 uOffData; U32 uLenData; U16 uOffPH; // Display the MPC_RRH. FETCH_HW( uOffPH, pMPC_RRH->offph ); mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir ); // Point to and display the MPC_PH. pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH); mpc_display_stuff( pDEVBLK, "PH", (BYTE*)pMPC_PH, SIZE_PH, bDir ); // Point to and display the MPC_PIX. FETCH_F3( uLenData, pMPC_PH->lendata ); FETCH_FW( uOffData, pMPC_PH->offdata ); pMPC_PIX = (MPC_PIX*)((BYTE*)pMPC_TH + uOffData); mpc_display_stuff( pDEVBLK, "PIX", (BYTE*)pMPC_PIX, uLenData, bDir ); return; } /* End function mpc_display_rrh_and_pix() */
/*-------------------------------------------------------------------*/ static void ARCH_DEP(hwl_loadfile)(SCCB_HWL_BK *hwl_bk) { CREG sto; U32 size; int fd; fd = open (hwl_fn[hwl_bk->file], O_RDONLY|O_BINARY); if (fd < 0) { logmsg (_("HHCHL002I %s open error: %s\n"), hwl_fn[hwl_bk->file], strerror(errno)); return; } // else // logmsg(_("HHCHL004I Loading %s\n"),hwl_fn[hwl_bk->file]); FETCH_FW(size,hwl_bk->size); /* Segment Table Origin */ FETCH_DW(sto,hwl_bk->sto); #if defined(FEATURE_ESAME) sto &= ASCE_TO; #else /*!defined(FEATURE_ESAME)*/ sto &= STD_STO; #endif /*!defined(FEATURE_ESAME)*/ for( ; ; sto += sizeof(sto)) { #if defined(FEATURE_ESAME) DBLWRD *ste; #else /*!defined(FEATURE_ESAME)*/ FWORD *ste; #endif /*!defined(FEATURE_ESAME)*/ CREG pto, pti; /* Fetch segment table entry and calculate Page Table Origin */ if( sto >= sysblk.mainsize) goto eof; #if defined(FEATURE_ESAME) ste = (DBLWRD*)(sysblk.mainstor + sto); #else /*!defined(FEATURE_ESAME)*/ ste = (FWORD*)(sysblk.mainstor + sto); #endif /*!defined(FEATURE_ESAME)*/ FETCH_W(pto, ste); if( pto & SEGTAB_INVALID ) goto eof; #if defined(FEATURE_ESAME) pto &= ZSEGTAB_PTO; #else /*!defined(FEATURE_ESAME)*/ pto &= SEGTAB_PTO; #endif /*!defined(FEATURE_ESAME)*/ for(pti = 0; pti < 256 ; pti++, pto += sizeof(pto)) { #if defined(FEATURE_ESAME) DBLWRD *pte; #else /*!defined(FEATURE_ESAME)*/ FWORD *pte; #endif /*!defined(FEATURE_ESAME)*/ CREG pgo; BYTE *page; /* Fetch Page Table Entry to get page origin */ if( pto >= sysblk.mainsize) goto eof; #if defined(FEATURE_ESAME) pte = (DBLWRD*)(sysblk.mainstor + pto); #else /*!defined(FEATURE_ESAME)*/ pte = (FWORD*)(sysblk.mainstor + pto); #endif /*!defined(FEATURE_ESAME)*/ FETCH_W(pgo, pte); if( pgo & PAGETAB_INVALID ) goto eof; #if defined(FEATURE_ESAME) pgo &= ZPGETAB_PFRA; #else /*!defined(FEATURE_ESAME)*/ pgo &= PAGETAB_PFRA; #endif /*!defined(FEATURE_ESAME)*/ /* Read page into main storage */ if( pgo >= sysblk.mainsize) goto eof; page = sysblk.mainstor + pgo; if( !(size--) || !read(fd, page, STORAGE_KEY_PAGESIZE) ) goto eof; STORAGE_KEY(pgo, &sysblk) |= (STORKEY_REF|STORKEY_CHANGE); } } eof: close(fd); }
static void CTCT_Write( DEVBLK* pDEVBLK, U32 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U32* pResidual ) { PCTCIHDR pFrame; // -> Frame header PCTCISEG pSegment; // -> Segment in buffer U16 sOffset; // Offset of next frame U16 sSegLen; // Current segment length U16 sDataLen; // Length of IP Frame data int iPos; // Offset into buffer U16 i; // Array subscript int rc; // Return code BYTE szStackID[33]; // VSE IP stack identity U32 iStackCmd; // VSE IP stack command // Check that CCW count is sufficient to contain block header if( sCount < sizeof( CTCIHDR ) ) { WRMSG(HHC00906, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, sCount ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Fix-up frame pointer pFrame = (PCTCIHDR)pIOBuf; // Extract the frame length from the header FETCH_HW( sOffset, pFrame->hwOffset ); // Check for special VSE TCP/IP stack command packet if( sOffset == 0 && sCount == 40 ) { // Extract the 32-byte stack identity string for( i = 0; i < sizeof( szStackID ) - 1 && i < sCount - 4; i++) szStackID[i] = guest_to_host( pIOBuf[i+4] ); szStackID[i] = '\0'; // Extract the stack command word FETCH_FW( iStackCmd, *((FWORD*)&pIOBuf[36]) ); // Display stack command and discard the packet WRMSG(HHC00907, "I", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, szStackID, iStackCmd ); *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; return; } // Check for special L/390 initialization packet if( sOffset == 0 ) { // Return normal status and discard the packet *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; return; } #if 0 // Notes: It appears that TurboLinux has gotten sloppy in their // ways. They are now giving us buffer sizes that are // greater than the CCW count, but the segment size // is within the count. // Check that the frame offset is valid if( sOffset < sizeof( CTCIHDR ) || sOffset > sCount ) { logmsg( _("CTC101W %4.4X: Write buffer contains invalid " "frame offset %u\n"), pDEVBLK->devnum, sOffset ); pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } #endif // Adjust the residual byte count *pResidual -= sizeof( CTCIHDR ); // Process each segment in the buffer for( iPos = sizeof( CTCIHDR ); iPos < sOffset; iPos += sSegLen ) { // Check that the segment is fully contained within the block if( iPos + sizeof( CTCISEG ) > sOffset ) { WRMSG(HHC00908, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, iPos ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Fix-up segment header in the I/O buffer pSegment = (PCTCISEG)(pIOBuf + iPos); // Extract the segment length from the segment header FETCH_HW( sSegLen, pSegment->hwLength ); // Check that the segment length is valid if( ( sSegLen < sizeof( CTCISEG ) ) || ( (U32)iPos + sSegLen > sOffset ) || ( (U32)iPos + sSegLen > sCount ) ) { WRMSG(HHC00909, "E", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, sSegLen, iPos ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Calculate length of IP frame data sDataLen = sSegLen - sizeof( CTCISEG ); // Trace the IP packet before sending if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) { WRMSG(HHC00934, "I", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->filename ); if( pDEVBLK->ccwtrace ) packet_trace( pSegment->bData, sDataLen, '>' ); } // Write the IP packet rc = write_socket( pDEVBLK->fd, pSegment->bData, sDataLen ); if( rc < 0 ) { WRMSG(HHC00936, "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; } // Adjust the residual byte count *pResidual -= sSegLen; // We are done if current segment satisfies CCW count if( (U32)iPos + sSegLen == sCount ) { *pResidual -= sSegLen; *pUnitStat = CSW_CE | CSW_DE; return; } } // Set unit status and residual byte count *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; }
/* is followed by up to four MPC_PUSs. */ DLL_EXPORT void mpc_display_rrh_and_puk( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir ) { MPC_PH* pMPC_PH; MPC_PUK* pMPC_PUK; MPC_PUS* pMPC_PUS; int iTotLenPUS; U32 uOffData; U16 uTotLenPUS; U16 uLenPUS; U16 uLenPUK; U16 uOffPH; // Display the MPC_RRH. FETCH_HW( uOffPH, pMPC_RRH->offph ); mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir ); // Point to and display the MPC_PH. pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH); mpc_display_stuff( pDEVBLK, "PH", (BYTE*)pMPC_PH, SIZE_PH, bDir ); // Get the length of and point to the data referenced by the // MPC_PH. The data contain a MPC_PUK and one or more MPC_PUSs. FETCH_FW( uOffData, pMPC_PH->offdata ); pMPC_PUK = (MPC_PUK*)((BYTE*)pMPC_TH + uOffData); // Display the MPC_PUK. FETCH_HW( uLenPUK, pMPC_PUK->length ); mpc_display_stuff( pDEVBLK, "PUK", (BYTE*)pMPC_PUK, uLenPUK, bDir ); // Get the total length of the following MPC_PUSs, then point to // the first MPC_PUS. FETCH_HW( uTotLenPUS, pMPC_PUK->lenpus ); iTotLenPUS = uTotLenPUS; pMPC_PUS = (MPC_PUS*)((BYTE*)pMPC_PUK + uLenPUK); // Display all of the MPC_PUSs. while( iTotLenPUS > 0 ) { // Ensure there are at least the first 4-bytes of the MPC_PUS. if( iTotLenPUS < 4 ) { mpc_display_stuff( pDEVBLK, "???", (BYTE*)pMPC_PUS, iTotLenPUS, bDir ); break; } // Get the length of the MPC_PUS. FETCH_HW( uLenPUS, pMPC_PUS->length ); if( uLenPUS == 0 ) /* Better safe than sorry */ { mpc_display_stuff( pDEVBLK, "???", (BYTE*)pMPC_PUS, iTotLenPUS, bDir ); break; } // Ensure there is the whole of the MPC_PUS. if( iTotLenPUS < uLenPUS ) { mpc_display_stuff( pDEVBLK, "???", (BYTE*)pMPC_PUS, iTotLenPUS, bDir ); break; } // Display the MPC_PUS. mpc_display_stuff( pDEVBLK, "PUS", (BYTE*)pMPC_PUS, uLenPUS, bDir ); // Point to the next MPC_PUS pMPC_PUS = (MPC_PUS*)((BYTE*)pMPC_PUS + uLenPUS); iTotLenPUS -= uLenPUS; } return; } /* End function mpc_display_rrh_and_puk() */
int main( int argc, char *argv[] ) { U64 nxtpos; /* file position of next read */ U64 altpos; /* file position of alternate track */ U64 orgpos; /* alternate track's file position of original track */ U32 numbad = 0; /* Counts defective tracks */ U32 reclaimed = 0; /* Counts reclaimed tracks */ U32 remaining; /* Counts number of tracks to process */ U32 total; /* Total number of tracks to process */ int infile = -1; /* Input file descriptor integer */ int outfile = -1; /* output file descriptor integer */ int cyl; /* Cylinder number */ int head; /* Head number */ int track; /* Track number */ int rc; /* Return code */ U8 trackbuf[TRACKSIZE]; /* Primary track buffer */ U8 alttrack[TRACKSIZE]; /* Alternate track buffer */ U8 altmark[6] = { BAD_TRACK_SIG }; /* Defective track signature */ U8 reclaim = 0; /* false: map, true: reclaim */ /*----------------*/ /* Initialization */ /*----------------*/ if (argc < 3 || argc > 4) return error( EINVAL, "invalid number of arguments" ); if (1 && strcmp( argv[1], "MAP" ) != 0 && strcmp( argv[1], "map" ) != 0 && strcmp( argv[1], "RECLAIM" ) != 0 && strcmp( argv[1], "reclaim" ) != 0 ) return error( EINVAL, "invalid 'action'" ); reclaim = ((strcmp( argv[1], "RECLAIM" ) == 0) || (strcmp( argv[1], "reclaim" ) == 0)); if (reclaim && argc < 4) return error( EINVAL, "missing outfile argument" ); printf( "Run option = %s\n", argv[1] ); printf( "Opening input file \"%s\"...\n", argv[2] ); if ((infile = HOPEN( argv[2], O_RDONLY | O_BINARY )) < 0) return error( errno, "could not open input file" ); /*------------------------------*/ /* Read and inspect file header */ /*------------------------------*/ if ((rc = read(infile, trackbuf, FILEHDRSIZE)) <= 0 || rc != FILEHDRSIZE) return error( EIO, "I/O error reading header from input file" ); if (memcmp(trackbuf, "CKD_P370", 8) != 0) return error(EINTR, "input file is no CKD dasd image"); if (trackbuf[16] != 0x90) return error(EINTR, "input file is no 3390 dasd image"); FETCH_FW( head, &trackbuf[8] ); FETCH_FW( track, &trackbuf[12] ); FETCH_HW( cyl, &trackbuf[18] ); if (bswap_32(track) != TRACKSIZE) return error(EINTR, "input file uses an unsupported track size"); printf("3390 DASD image: %d heads, %d cylinders\n\n", bswap_32(head), bswap_16(cyl)); remaining = total = TRACKSPERCYL * bswap_16(cyl); /*-----------------------------------------------------------*/ /* Open output file and copy file header (only on "reclaim") */ /*-----------------------------------------------------------*/ if (reclaim) { printf( "Opening output file \"%s\"...\n", argv[3] ); if ((outfile = HOPEN( argv[3], O_CREAT | O_EXCL | O_WRONLY | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP )) < 0) return error( errno, "could not open output file" ); if ((rc = write( outfile, trackbuf, FILEHDRSIZE )) < 0 || rc != FILEHDRSIZE) return error( EIO, "I/O error writing output file" ); } c: /*---------------------------*/ /* Start of copy tracks loop */ /*---------------------------*/ track = total - remaining; cyl = CYLNUM ( track ); head = HEADNUM( track ); if (!head) printf( "Inspecting cylinder %d...\r", cyl ); /* Read next track */ if ((rc = read( infile, trackbuf, TRACKSIZE )) <= 0 || rc != TRACKSIZE) return error( errno, "I/O error reading input file" ); /*------------------*/ /* Defective track? */ /*------------------*/ if (memcmp( &trackbuf[TRACKSIZE-16], altmark, 6 ) == 0) { numbad++; /* Count defective tracks */ if (reclaim) printf( "Reclaiming track %6d = Cyl %4d (%4.4X), Head %2d (%2.2X)...\n", track, cyl, cyl, head, head ); else printf( "Track %6d = Cyl %4d (%4.4X), Head %2d (%2.2X) is flagged\nas being defective and has an alternate track assigned.\n", track, cyl, cyl, head, head ); FETCH_DW( altpos, &trackbuf[ TRACKSIZE-8 ] ); /* get alternate track position */ nxtpos= lseek( infile, 0, SEEK_CUR ); /* save current file position */ lseek( infile, altpos, SEEK_SET ); /* position to alternate */ read ( infile, alttrack, TRACKSIZE ); /* read alternate track */ lseek( infile, nxtpos, SEEK_SET ); /* restore original file position */ FETCH_DW( orgpos, &alttrack[ TRACKSIZE-8 ] ); /* get original track position */ /*----------------------------------------------*/ #if (DEBUGOPT & DEBUG_POSITIONS) { int alttrk = POS2TRACK( altpos ); int altcyl = CYLNUM ( alttrk ); int althead = HEADNUM( alttrk ); int orgtrk = POS2TRACK( orgpos ); int orgcyl = CYLNUM ( orgtrk ); int orghead = HEADNUM( orgtrk ); printf("\n"); printf( "\taltpos = %llx ==> track %6d = Cyl %4d (%4.4X), Head %2d (%2.2X)\n", altpos, alttrk, altcyl, altcyl, althead, althead ); printf( "\torgpos = %llx ==> track %6d = Cyl %4d (%4.4X), Head %2d (%2.2X)\n", orgpos, orgtrk, orgcyl, orgcyl, orghead, orghead ); } #endif #if (DEBUGOPT & DEBUG_TRACKDATA) { char *dump = NULL; printf("\n"); hexdumpe( "\tPRI: ", &dump, trackbuf, 0, TRACKSIZE, orgpos, 4, 4 ); if (dump) printf( "%s\n", dump ); hexdumpe( "\tALT: ", &dump, alttrack, 0, TRACKSIZE, altpos, 4, 4 ); if (dump) printf( "%s", dump ); if (dump) free( dump ); } #endif #if (DEBUGOPT & DEBUG_BOTH) /* if EITHER debug option */ printf("\n"); /* if EITHER debug option */ #endif /*----------------------------------------------*/ if (reclaim) { /* Reclaim the original track: the alternate tracks's position of the original defective track must match, and the track header containing the cylinder and track numbers must also match. */ if (orgpos == (nxtpos-TRACKSIZE) && memcmp( &alttrack[0], &trackbuf[0], 16 ) == 0) { /* copy alternate track data to original track */ memcpy( trackbuf, alttrack, TRACKSIZE ); /* indicate original track is no longer defective */ memset( &trackbuf[TRACKSIZE-16], 0, 16 ); reclaimed++; /* Count reclaimed tracks */ } else fprintf( stderr, "\t*** ERROR *** Reclaim failed!\n\n" ); } } /*----------------------------*/ /* Write track to output file */ /*----------------------------*/ if (reclaim) if ((rc = write( outfile, trackbuf, TRACKSIZE )) < 0 || rc != TRACKSIZE) return error( EIO, "I/O error writing output file" ); /*------------------------------*/ /* Loop until all tracks copied */ /*------------------------------*/ if (--remaining) goto c; /*-----------------------*/ /* Print totals and exit */ /*-----------------------*/ if (infile > 0) close( infile ); if (outfile > 0) close( outfile ); printf( "%d tracks (%d cylinders) read.\n", total, CYLNUM(total) ); if (reclaim) printf( "%d tracks (%d cylinders) written.\n", total, CYLNUM(total) ); if (!reclaim) printf( "Image currently has %d defective tracks assigned to an alternate.\n", numbad ); else { printf( "Image had %d defective tracks assigned to an alternate.\n", numbad ); printf( "A total of %d defective tracks were reclaimed from their assigned alternate.\n", reclaimed ); printf( "Reclaim %s.\n", reclaimed >= numbad ? "was successful" : "function FAILED" ); } PAUSEIFBEINGDEBUGGED(); return (0); }
void CTCI_Write( DEVBLK* pDEVBLK, U16 sCount, BYTE* pIOBuf, BYTE* pUnitStat, U16* pResidual ) { PCTCBLK pCTCBLK = (PCTCBLK)pDEVBLK->dev_data; PCTCIHDR pFrame; // -> Frame header PCTCISEG pSegment; // -> Segment in buffer U16 sOffset; // Offset of next frame U16 sSegLen; // Current segment length U16 sDataLen; // Length of IP Frame data int iPos; // Offset into buffer U16 i; // Array subscript int rc; // Return code BYTE szStackID[33]; // VSE IP stack identity U32 iStackCmd; // VSE IP stack command // Check that CCW count is sufficient to contain block header if( sCount < sizeof( CTCIHDR ) ) { logmsg( _("HHCCT042E %4.4X: Write CCW count %u is invalid\n"), pDEVBLK->devnum, sCount ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Fix-up frame pointer pFrame = (PCTCIHDR)pIOBuf; // Extract the frame length from the header FETCH_HW( sOffset, pFrame->hwOffset ); // Check for special VSE TCP/IP stack command packet if( sOffset == 0 && sCount == 40 ) { // Extract the 32-byte stack identity string for( i = 0; i < sizeof( szStackID ) - 1 && i < sCount - 4; i++) szStackID[i] = guest_to_host( pIOBuf[i+4] ); szStackID[i] = '\0'; // Extract the stack command word FETCH_FW( iStackCmd, *((FWORD*)&pIOBuf[36]) ); // Display stack command and discard the packet logmsg( _("HHCCT043I %4.4X: Interface command: %s %8.8X\n"), pDEVBLK->devnum, szStackID, iStackCmd ); *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; return; } // Check for special L/390 initialization packet if( sOffset == 0 ) { // Return normal status and discard the packet *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; return; } #if 0 // Notes: It appears that TurboLinux has gotten sloppy in their // ways. They are now giving us buffer sizes that are // greater than the CCW count, but the segment size // is within the count. // Check that the frame offset is valid if( sOffset < sizeof( CTCIHDR ) || sOffset > sCount ) { logmsg( _("CTC101W %4.4X: Write buffer contains invalid " "frame offset %u\n"), pDEVBLK->devnum, sOffset ); pDEVBLK->sense[0] = SENSE_CR; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } #endif // Adjust the residual byte count *pResidual -= sizeof( CTCIHDR ); // Process each segment in the buffer for( iPos = sizeof( CTCIHDR ); iPos < sOffset; iPos += sSegLen ) { // Check that the segment is fully contained within the block if( iPos + sizeof( CTCISEG ) > sOffset ) { logmsg( _("HHCCT044E %4.4X: Write buffer contains incomplete " "segment header at offset %4.4X\n"), pDEVBLK->devnum, iPos ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Fix-up segment header in the I/O buffer pSegment = (PCTCISEG)(pIOBuf + iPos); // Extract the segment length from the segment header FETCH_HW( sSegLen, pSegment->hwLength ); // Check that the segment length is valid if( ( sSegLen < sizeof( CTCISEG ) ) || ( iPos + sSegLen > sOffset ) || ( iPos + sSegLen > sCount ) ) { logmsg( _("HHCCT045E %4.4X: Write buffer contains invalid " "segment length %u at offset %4.4X\n"), pDEVBLK->devnum, sSegLen, iPos ); pDEVBLK->sense[0] = SENSE_DC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Calculate length of IP frame data sDataLen = sSegLen - sizeof( CTCISEG ); // Trace the IP packet before sending to TUN device if( pCTCBLK->fDebug ) { logmsg( _("HHCCT046I %4.4X: Sending packet to %s:\n"), pDEVBLK->devnum, pCTCBLK->szTUNDevName ); packet_trace( pSegment->bData, sDataLen ); } // Write the IP packet to the TUN/TAP interface rc = TUNTAP_Write( pCTCBLK->fd, pSegment->bData, sDataLen ); if( rc < 0 ) { logmsg( _("HHCCT047E %4.4X: Error writing to %s: rc=%d errno=%d %s\n"), pDEVBLK->devnum, pCTCBLK->szTUNDevName, rc, errno, strerror(errno)); } /* Kludge for Ubuntu 10.04 by Martin Truebner */ if (rc == -1 && errno == 22) rc = 0; if (rc < 0) { pDEVBLK->sense[0] = SENSE_EC; *pUnitStat = CSW_CE | CSW_DE | CSW_UC; return; } // Adjust the residual byte count *pResidual -= sSegLen; // We are done if current segment satisfies CCW count if( iPos + sSegLen == sCount ) { *pResidual -= sSegLen; *pUnitStat = CSW_CE | CSW_DE; return; } } // Set unit status and residual byte count *pUnitStat = CSW_CE | CSW_DE; *pResidual = 0; }