// PupBSPBlock.bcpl -- procedures for fast BSP transfers // Copyright Xerox Corporation 1979, 1980 // Last modified December 30, 1980 5:35 PM by Boggs get "pup.decl" external [ // Outgoing procedures BSPReadBlock; BSPWriteBlock // Incoming procedures BSPPrepareIPBI; BSPGetCleanup; BSPPrepareOPBI; BSPForceOutput ByteBlt; Min; Errors // Statics offsetBSPStr ] structure [ lh byte; rh byte ] // --------------------------------------------------------------------------- let BSPReadBlock(str, wordP, byteP, count, timeout; numargs na)= valof // --------------------------------------------------------------------------- // Read a maximum of count bytes from the BSP stream str, // storing them starting at address wordP in byte byteP (0=left, // 1=right half). timeout (optional) is defined as for BSPGetByte. // Returns the actual number of bytes read. [ let soc = str-offsetBSPStr let bytesSoFar = 0 while count gr 0 do [ // Ensure there is at least one byte to read, getting new iPBI if necessary let ec = BSPPrepareIPBI(soc, (na ge 5? timeout, -1)) if ec ne 0 then [ Errors(str, ec); break ] // Transfer as many bytes as we can let c = Min(str>>BSPStr.iByteC, count) ByteBlt(wordP, byteP, str>>BSPStr.iWordP, str>>BSPStr.iByteP, c) // Adjust counts and pointers to account for bytes just transferred str>>BSPStr.iWordP = str>>BSPStr.iWordP + (c+str>>BSPStr.iByteP) rshift 1 str>>BSPStr.iByteP = (c+str>>BSPStr.iByteP) & 1 str>>BSPStr.iByteC = str>>BSPStr.iByteC - c wordP = wordP+(c+byteP) rshift 1 byteP = (c+byteP) & 1 bytesSoFar = bytesSoFar+c count = count-c // Clean up stream if current iPBI is exhausted if str>>BSPStr.iByteC eq 0 then BSPGetCleanup(soc) ] resultis bytesSoFar ] // --------------------------------------------------------------------------- and BSPWriteBlock(str, wordP, byteP, count, timeout; numargs na)= valof // --------------------------------------------------------------------------- // Write a maximum of count bytes into the BSP stream str, getting // them starting at address wordP in byte byteP (0=left, // 1=right half). timeout (optional) is defined as for BSPPutByte. // Returns the actual number of bytes written. [ let soc = str-offsetBSPStr let bytesSoFar = 0 while count gr 0 do [ // Ensure there is an oPBI set up let ec = BSPPrepareOPBI(soc, (na ge 5? timeout, -1)) if ec ne 0 then [ Errors(str, ec); break ] // Transfer as many bytes as we can let c = Min(str>>BSPStr.oByteC, count) ByteBlt(str>>BSPStr.oWordP, str>>BSPStr.oByteP, wordP, byteP, c) // Adjust counts and pointers to account for bytes just transferred str>>BSPStr.oWordP = str>>BSPStr.oWordP + (c+str>>BSPStr.oByteP) rshift 1 str>>BSPStr.oByteP = (c+str>>BSPStr.oByteP) & 1 str>>BSPStr.oByteC = str>>BSPStr.oByteC - c wordP = wordP+(c+byteP) rshift 1 byteP = (c+byteP) & 1 bytesSoFar = bytesSoFar+c count = count-c // Ensure that if the last byte transferred was to the left half, the // right half is zero. n.b. this may clobber one word beyond the end // of the data portion of the Pup, but that's the checksum word, so ok. str>>BSPStr.oWordP>>rh = 0 // Clean up stream if current oPBI is full if str>>BSPStr.oByteC eq 0 then BSPForceOutput(soc) ] resultis bytesSoFar ]