-- File: PupBooterFastAlto.mesa,  Last Edit: HGM  November 18, 1980  12:53 PM

DIRECTORY
  System USING [Pulses, GetClockPulses, PulsesToMicroseconds],
  Lock USING [LockDisk, UnlockDisk],
  BootServerDefs USING [BootFile, WhatHappened],
  ReadDefs USING [
    CBZptr, CBptr, GetNextPage, LastPage, ReleasePage, StartReading, StopReading],
  EFTPDefs USING [
    EFTPAbortSending, EFTPFinishSending, EFTPOpenForSending, EFTPSendBlock,
    EFTPSetSendTimeout, EFTPTimeOut, EFTPTroubleSending],
  PupTypes USING [PupAddress];

PupBooterFastAlto: PROGRAM
  IMPORTS System, Lock, ReadDefs, EFTPDefs EXPORTS BootServerDefs =
  BEGIN

  blankDisplay: BOOLEAN = TRUE;

  bufferSize: CARDINAL ← 5; -- patch by hand to adjust

  KillingSpacesIsSillyInAltoMode: ERROR = CODE;

  FastBooter: PUBLIC PROCEDURE [
    bf: BootServerDefs.BootFile, him: PupTypes.PupAddress]
    RETURNS [what: BootServerDefs.WhatHappened] =
    BEGIN OPEN EFTPDefs;
    done: BOOLEAN ← FALSE;
    zone: ReadDefs.CBZptr;
    cb: ReadDefs.CBptr;
    pulses: System.Pulses ← System.GetClockPulses[];
    page: CARDINAL ← 0;
    IF ~Lock.LockDisk[bf.fileName, read, blankDisplay] THEN RETURN[diskBusy];
    EFTPSetSendTimeout[100, 5]; -- not very many tries
    BEGIN
    EFTPOpenForSending[
      him, FALSE ! EFTPTimeOut, EFTPTroubleSending => GOTO NeverStarted];
    zone ← ReadDefs.StartReading[@bf.file.fID, bufferSize];
    ReadDefs.ReleasePage[ReadDefs.GetNextPage[zone]]; -- skip leader page
    -- NB: There is no check to be sure that the file is in B format.  It should have been reformatted by now.
    UNTIL done DO
      cb ← ReadDefs.GetNextPage[zone];
      EFTPSendBlock[
	cb.dataAddress, cb.labelAddress.bytes !
	EFTPTimeOut, EFTPTroubleSending => GOTO Trouble];
      done ← ReadDefs.LastPage[cb];
      ReadDefs.ReleasePage[cb];
      -- This must total about 5 seconds to keep Pilot's EtherGerm happy.
      IF page = 0 THEN EFTPSetSendTimeout[200, 25];
      page ← page + 1;
      ENDLOOP;
    EFTPFinishSending[ ! EFTPTimeOut, EFTPTroubleSending => GOTO Trouble];
    ReadDefs.StopReading[zone];
    pulses ← System.Pulses[System.GetClockPulses[] - pulses];
    bf.count ← bf.count + 1;
    bf.ms ← bf.ms + System.PulsesToMicroseconds[pulses]/1000;
    what ← fast;
    EXITS
      Trouble =>
	BEGIN
	ReadDefs.StopReading[zone];
	EFTPAbortSending["I give up..."L];
	what ← troubles;
	END;
      NeverStarted => BEGIN what ← neverStarted; END;
    END;
    Lock.UnlockDisk[bf.fileName, blankDisplay];
    END;

  KillSpace: PUBLIC PROCEDURE [bf: BootServerDefs.BootFile] =
    BEGIN ERROR KillingSpacesIsSillyInAltoMode; END;

  END.