-- Copyright (C) 1983, 1985  by Xerox Corporation. All rights reserved. 
-- MoreBuffers.mesa, HGM,  6-Aug-85 21:35:06

DIRECTORY
  Boss,
  Buffer USING [],
  CommunicationInternal USING [
    CommPackageGo, CommPackageOff, NSPackageMake, NSPackageDestroy],
  Driver USING [GetDeviceChain, Network],
  EthernetOneDriver,
  PSB USING [InterruptLevel, PDA],
  Process USING [EnableAborts, Pause],
  Protocol1 USING [AddFamilyMember, Family, MatrixRecord],
  PupDefs USING [PupPackageDestroy, PupPackageMake],
  Runtime USING [GlobalFrame];

MoreBuffers: PROGRAM
  IMPORTS CommunicationInternal, Driver, Process, Runtime, Protocol1, PupDefs
  EXPORTS Buffer
  SHARES Boss, EthernetOneDriver =
  BEGIN
  
  Network: PUBLIC TYPE = Driver.Network;
  
  boss: LONG POINTER TO FRAME[Boss] = LOOPHOLE[Runtime.GlobalFrame[LOOPHOLE[CommunicationInternal.CommPackageGo]]];
  
  AddMoreBuffers: PROCEDURE =
    BEGIN
    first: Driver.Network ← Driver.GetDeviceChain[];  -- Glitches if off
    Poker: PROCEDURE =
      BEGIN -- Hack to get around microcode bug - naked CVs forget aborts enabled
      IF TRUE THEN RETURN; -- AOF copied this (UGLY) code to driver
      UNTIL off DO
        FOR int: PSB.InterruptLevel IN PSB.InterruptLevel DO
	  Process.EnableAborts[LOOPHOLE[@PSB.PDA.interrupt[int]]];
	  ENDLOOP;
	Process.Pause[1];
	ENDLOOP;
      END;
    off: BOOLEAN ← FALSE;
    poker: PROCESS ← FORK Poker[];
    CommunicationInternal.NSPackageDestroy[]; -- One free one
    IF boss.useCount # 1 THEN ERROR;
    CommunicationInternal.CommPackageOff[];
    off ← TRUE;
    JOIN poker;
    FOR network: Driver.Network ← first, network.next UNTIL network = NIL DO
      SELECT network.device FROM
        ethernet, ethernetOne => network.buffers ← 10;
	ENDCASE;
      ENDLOOP;
    CommunicationInternal.CommPackageGo[];
    [] ← CommunicationInternal.NSPackageMake[];
    PlugPupIntoEthernetOneDriverAgain[];
    END;

  PlugPupIntoEthernetOneDriverAgain: PROCEDURE =
    BEGIN
    first: Driver.Network ← Driver.GetDeviceChain[];  -- Glitches if off
    FOR network: Driver.Network ← first, network.next UNTIL network = NIL DO
      SELECT network.device FROM
        ethernetOne => {
	  ethernetOneDriver: LONG POINTER TO FRAME[EthernetOneDriver] =
	    LOOPHOLE[Runtime.GlobalFrame[LOOPHOLE[network.activateDriver]]];
          family: Protocol1.Family ← PupDefs.PupPackageMake[];
          matrix: Protocol1.MatrixRecord ← [  --AddFamilyMember copies fields
            family: family, context: @ethernetOneDriver.pup,
            encapsulator: ethernetOneDriver.encapsulatePup,
            decapsulator: ethernetOneDriver.decapsulatePup];
          Protocol1.AddFamilyMember[@ethernetOneDriver.myNetwork, @matrix];
IF FALSE THEN -- Horrible ML mess
          PupDefs.PupPackageDestroy[]; -- Didn't really want to turn it on
};
	ENDCASE;
      ENDLOOP;
    END;

  -- START traps do all the work
IF TRUE THEN
  AddMoreBuffers[];
  END..