MODULE NetworkMii; (** AUTHOR "staubesv"; PURPOSE "Media Independent Interface (MII) management interface support"; *) (** * The Media Independent Interface (MII) is an interface between the MAC Layer and the PHY. The MII Management Interface's purpose is * to control the PHY and gather status from the PHY. This module defines constants and implements some basic functionality for both * the MII management interface and its superset GMII. * * References: * * [1] IEEE Std 802.3-2005 Edition, www.ieee.org * * History: * * 03.11.2006 First release (staubesv) * * Status: * * BETA * - 1GB auto-negotiation not yet supported * - Handling of devices that don't support auto-negotiation not supported *) IMPORT SYSTEM, KernelLog, Objects, Kernel, Network; CONST Ok* = 0; Unsupported* = 1; ParametersInvalid* = 2; NotAvailable* = 3; ErrorRead* = 5; ErrorWrite* = 6; Timeout* = 7; AutoNegotiationTimeout = 1000; (* ms *) TraceAutoNegotiation = {0}; TraceCommands = {1}; Trace = {}; Debug = TRUE; ModuleName = "NetworkMii"; (** MII register offsets *) (** Basic Registers *) BMCR* = 0H; (** Basic Mode Control Register *) BMSR* = 1H; (** Basic Mode Status Register *) BMESR* = 15H; (** Basic Mode Extended Status Register (GMII only) *) (** Extended Registers *) PHYIDR1* = 2H; (** PHY Identifier Register 1 *) PHYIDR2* = 3H; (** PHY Identifier Register 2 *) ANAR* = 4H; (** Auto-Negotiation Advertisement Register *) ANLPAR* = 5H; (** Auto-Negotiation Link Partner Ability Register *) ANER* = 6H; (** Auto-Negotiation Expansion Register *) ANNPTR* = 7H; (** Auto-Negotiation Next Page Transmit Register *) ANLPRNPR* = 8H; (** Auto-Negotiation Link Partner Received Next Page Register *) MSCR* = 9H; (** Master-Slave Control Register *) MSSR* = 10H; (** Master-Slave Status Register *) PSECR* = 11H; (** PSE Control Register *) PSESR* = 12H; (** PSE Status Register *) MMDACR* = 13H; (** MMD Access Control Register *) MMDAADR* = 14H; (** MMD Access Address Data Register *) (* 16H-31H: Vendor-Specific extended registers *) (* Basic Mode Control Register (BMCR) *) BMCR_Reset* = {15}; (* self-clearing, default: 0 *) BMCR_Loopback* = {14}; (* default: 0 *) BMCR_SpeedSelectionLsb* = {13}; BMCR_AutoNegotiationEnable* = {12}; (* default: 1 *) BMCR_PowerDown* = {11}; (* default: 0 *) BMCR_Isolate* = {10}; (* default: 0 *) BMCR_RestartAutoNegotiation* = {9}; (* self-clearing *) BMCR_DuplexMode* = {8}; BMCR_CollisionTest* = {7}; (* default: 0 *) BMCR_SpeedSelectionMsb* = {6}; BMCR_UnidirectionalEnable* = {5}; BMCR_Reserved* = {0..4}; (* write as zero *) (* Basic Mode Status Register (BMSR), all fields are read-only *) BMSR_100BaseT4* = {15}; BMSR_100BaseTXFullDuplex* = {14}; BMSR_100BaseTXHalfDuplex* = {13}; BMSR_10BaseTFullDuplex* = {12}; BMSR_10BaseTHalfDuplex* = {11}; BMSR_100BaseT2FullDuplex* = {10}; BMSR_100BaseT2HalfDuplex* = {9}; BMSR_ExtendedStatus* = {8}; (* Extended status information in register 15 (BMESR) *) BMSR_UnidirectionalAbility* = {7}; BMSR_MfPreambleSuppression* = {6}; BMSR_AutoNegotiationComplete* = {5}; BMSR_RemoteFault* = {4}; BMSR_AutoNegotiationAbility* = {3}; BMSR_LinkStatus* = {2}; BMSR_JabberDetect* = {1}; BMSR_ExtendedCapability* = {0}; (* Extended register available *) (* Basic Mode Extended Status Register (BMESR), all fields are read-only *) BMESR_1000BaseXFullDuplex* = {15}; BMESR_1000BaseXHalfDuplex* = {14}; BMESR_1000BaseTFullDuplex* = {13}; BMESR_1000BaseTHalfDuplex* = {12}; BMESR_Reserved* = {0..11}; (* PHY Identifier Register 1 (PHYIDR1) *) PHYIDR1_OuiMSB* = {0..15}; (* PHY Identifier Register 2 (PHYIDR2) *) PHYIDR2_OuiLSB* = {10..15}; PHYIDR2_VendorModel* = {4..9}; PHYIDR2_ModelRevision* = {0..3}; (* Auto Negotiation Advertisement Register (ANAR) *) (* Auto Negotiation Link Partner Ability Register (ANLPAR) *) ANAR_NextPageIndication* = {15}; ANAR_Ackknowlegdement* = {14}; ANAR_RemoteFault* = {13}; ANAR_Reserved* = {11..12}; (* write as zero *) ANAR_AsymmetricPause* = {11}; ANAR_Pause* = {10}; ANAR_100BaseT4Support* = {9}; ANAR_100BaseTXFullDuplex* = {8}; ANAR_100BaseTXHalfDuplex* = {7}; ANAR_10BaseTFullDuplex* = {6}; ANAR_10BaseTHalfDuplex* = {5}; ANAR_Selector* = {0..4}; (* ANAR/ANLPAR Selector field *) Selector_IEEE_STD802_3* = 1; Selector_IEEE_STD802_9ISLAN16T* = 2; (* Auto Negotiation Expansion Register (ANER) *) ANER_Reserved* = {5..15}; (* write as zero *) ANER_ParallelDetectionFault* = {4}; ANER_LinkPartnerNextPageEnable* = {3}; ANER_PhyNextPageEnable* = {2}; ANER_NewPageReception* = {1}; ANER_LinkPartnerAnEnable* = {0}; TYPE Identifier* = RECORD oui- : LONGINT; (* Organizationally Unique Identifier *) model- : LONGINT; revision- : LONGINT; END; TYPE MII* = OBJECT VAR phyId- : LONGINT; lockedBy : ANY; timer : Kernel.Timer; (** Abstract interface to be implemented by the implementor *) (** Acqurie PHY ownership *) PROCEDURE AcquirePhyOwnership*() : BOOLEAN; (* abstract *) BEGIN HALT(301); END AcquirePhyOwnership; (** Release PHY ownership *) PROCEDURE ReleasePhyOwnership*() : BOOLEAN; (* abstract *) BEGIN HALT(301); END ReleasePhyOwnership; PROCEDURE HasPhyOwnership() : BOOLEAN; (* abstract *) BEGIN HALT(301); END HasPhyOwnership; (** Read a MII/GMII register *) PROCEDURE ReadRegister16*(register: LONGINT; VAR value : SET; VAR res : WORD); (* abstract *) BEGIN HALT(301); END ReadRegister16; (** Write a MII/GMII register *) PROCEDURE WriteRegister16*(register : LONGINT; value : SET; VAR res : WORD); (* abstract *) BEGIN HALT(301); END WriteRegister16; (** MII Management Interface *) PROCEDURE Acquire*; VAR me : ANY; BEGIN {EXCLUSIVE} me := Objects.ActiveObject(); ASSERT(lockedBy # me); (* no recursive locking *) AWAIT(lockedBy = NIL); IF ~AcquirePhyOwnership() THEN Show("Serious error: Software could not acquire PHY ownership."); KernelLog.Ln; END; lockedBy := me; END Acquire; PROCEDURE Release*; BEGIN {EXCLUSIVE} ASSERT(lockedBy = Objects.ActiveObject()); IF ~ReleasePhyOwnership() THEN Show("Fatal error: Software could not release PHY ownership."); KernelLog.Ln; END; lockedBy := NIL; END Release; (** Enable/disable auto-negotiation *) PROCEDURE EnableAutoNegotiation*(enable : BOOLEAN; VAR res : WORD); VAR anar, bmcr, bmsr : SET; BEGIN ASSERT(lockedBy = Objects.ActiveObject()); (* Check wether PHY supports auto-negotiation *) ReadRegister16(BMSR, bmsr, res); IF res # Ok THEN RETURN; END; IF bmsr * BMSR_AutoNegotiationAbility = {} THEN IF Trace * TraceCommands # {} THEN Show("Auto-Negotiation not supported."); KernelLog.Ln; END; res := Unsupported; RETURN; END; IF bmsr * BMSR_ExtendedCapability = {} THEN IF Trace * TraceCommands # {} THEN Show("Extended registers not available."); KernelLog.Ln; END; res := Unsupported; RETURN; END; (* Set abilities to be advertised *) anar := SYSTEM.VAL(SET, Selector_IEEE_STD802_3) * ANAR_Selector; IF bmsr * BMSR_100BaseT4 # {} THEN anar := anar + ANAR_100BaseT4Support; END; IF bmsr * BMSR_100BaseTXFullDuplex # {} THEN anar := anar + ANAR_100BaseTXFullDuplex; END; IF bmsr * BMSR_100BaseTXHalfDuplex # {} THEN anar := anar + ANAR_100BaseTXHalfDuplex; END; IF bmsr * BMSR_10BaseTFullDuplex # {} THEN anar := anar + ANAR_10BaseTFullDuplex; END; IF bmsr * BMSR_10BaseTHalfDuplex # {} THEN anar := anar + ANAR_10BaseTHalfDuplex; END; IF bmsr * BMSR_100BaseT2FullDuplex # {} THEN (* TODO *) END; IF bmsr * BMSR_100BaseT2HalfDuplex # {} THEN (* TODO *) END; (* TODO: 1GB *) anar := anar + ANAR_Pause; WriteRegister16(ANAR, anar, res); IF res # Ok THEN RETURN END; ReadRegister16(BMCR, bmcr, res); IF res # Ok THEN RETURN; END; IF enable THEN bmcr := bmcr + BMCR_AutoNegotiationEnable; ELSE bmcr := bmcr - BMCR_AutoNegotiationEnable; END; WriteRegister16(BMCR, bmcr, res); IF res # Ok THEN RETURN; END; IF enable THEN WriteRegister16(BMCR, bmcr + BMCR_RestartAutoNegotiation, res); END; END EnableAutoNegotiation; (** Get link configuration negotiated by auto-negotiation *) PROCEDURE GetAutoNegotiationResult*(VAR linkspeed : LONGINT; VAR fullDuplex : BOOLEAN; VAR res : WORD); VAR bmsr, anar, aner, anlpar, supported : SET; timeout : LONGINT; string : ARRAY 64 OF CHAR; BEGIN ASSERT(lockedBy = Objects.ActiveObject()); ReadRegister16(BMSR, bmsr, res); IF res # Ok THEN RETURN; END; IF bmsr * BMSR_AutoNegotiationAbility = {} THEN IF Trace * TraceAutoNegotiation # {} THEN Show("Auto-Negotiation not supported."); KernelLog.Ln; END; res := Unsupported; RETURN; END; IF bmsr * BMSR_ExtendedCapability = {} THEN IF Trace * TraceAutoNegotiation# {} THEN Show("Extended registers not available."); KernelLog.Ln; END; res := Unsupported; RETURN; END; ReadRegister16(ANER, aner, res); IF res # Ok THEN RETURN; END; IF aner * ANER_LinkPartnerAnEnable = {} THEN IF Trace * TraceAutoNegotiation # {} THEN Show("Link partner has not enabled auto-negotiation."); KernelLog.Ln; END; res := NotAvailable; RETURN; END; timeout := AutoNegotiationTimeout; REPEAT ReadRegister16(BMSR, bmsr, res); IF res # Ok THEN RETURN END; timer.Sleep(20); DEC(timeout, 20); UNTIL (bmsr * BMSR_AutoNegotiationComplete # {}) OR (timeout <= 0); IF bmsr * BMSR_AutoNegotiationComplete = {} THEN IF Trace * TraceAutoNegotiation # {} THEN Show("Auto-Negotiation not complete."); KernelLog.Ln; END; res := NotAvailable; RETURN; END; ReadRegister16(ANAR, anar, res); IF res # Ok THEN RETURN; END; ReadRegister16(ANLPAR, anlpar, res); IF res # Ok THEN RETURN; END; IF SYSTEM.VAL(LONGINT, anlpar * ANAR_Selector) # Selector_IEEE_STD802_3 THEN Show("Link partner doesn't use IEEE 802.3 Auto-Negotiation _ Other types not supported."); KernelLog.Ln; res := Unsupported; RETURN; END; supported := anar * anlpar; (* Priority Resolution according [1], Annex 28B *) IF supported * ANAR_100BaseTXFullDuplex # {} THEN linkspeed := 100; fullDuplex := TRUE; string := "100BASETX Full Duplex"; ELSIF supported * ANAR_100BaseTXHalfDuplex # {} THEN linkspeed := 100; fullDuplex := FALSE; string := "100BASETX Half Duplex"; ELSIF supported * ANAR_100BaseT4Support # {} THEN linkspeed := 100; fullDuplex := TRUE; string := "100BASET4"; ELSIF supported * ANAR_10BaseTFullDuplex # {} THEN linkspeed := 10; fullDuplex := TRUE; string := "10BASET Full Duplex"; ELSIF supported * ANAR_10BaseTHalfDuplex # {} THEN linkspeed := 10; fullDuplex := FALSE; string := "10BASET Half Duplex"; ELSE END; IF Trace * TraceAutoNegotiation # {} THEN Show("Detected "); KernelLog.String(string); KernelLog.Ln; END; END GetAutoNegotiationResult; (** Get the current link status *) PROCEDURE GetLinkStatus*(VAR linkStatus: LONGINT; VAR res : WORD); VAR value : SET; BEGIN ASSERT(lockedBy = Objects.ActiveObject()); ReadRegister16(BMSR, value, res); IF res = Ok THEN IF value * BMSR_LinkStatus # {} THEN linkStatus := Network.LinkLinked; ELSE linkStatus := Network.LinkNotLinked; END; END; END GetLinkStatus; (** Manually set the link speed and operating mode. This disables auto-negotiation as side-effect. *) PROCEDURE ConfigureLink*(speed : LONGINT; fullDuplex : BOOLEAN; VAR res : WORD); VAR value : SET; BEGIN ASSERT(lockedBy = Objects.ActiveObject()); ASSERT((speed = 10) OR (speed = 100) OR (speed = 1000)); (* determine whether PHY supports the desired link configuration *) ReadRegister16(BMSR, value, res); IF res # Ok THEN RETURN; END; (* BMSR_100BaseT4 ???? *) IF (speed = 10) & ((fullDuplex & (value * BMSR_10BaseTFullDuplex = {})) OR (~fullDuplex & (value * BMSR_10BaseTHalfDuplex = {}))) THEN res := ParametersInvalid; RETURN; ELSIF (speed = 100) & ((fullDuplex & (value * (BMSR_100BaseTXFullDuplex + BMSR_100BaseT2FullDuplex) = {})) OR (~fullDuplex & (value * (BMSR_100BaseTXHalfDuplex + BMSR_100BaseT2HalfDuplex) = {}))) THEN res := ParametersInvalid; RETURN; ELSIF (speed = 1000) THEN IF value * BMSR_ExtendedStatus = {} THEN res := ParametersInvalid; RETURN; END; ReadRegister16(BMESR, value, res); IF res # Ok THEN RETURN; END; IF (fullDuplex & (value * (BMESR_1000BaseXFullDuplex + BMESR_1000BaseTFullDuplex) = {})) OR (~fullDuplex & (value * (BMESR_1000BaseXHalfDuplex + BMESR_1000BaseTHalfDuplex) = {})) THEN res := ParametersInvalid; RETURN; END; END; (* disable auto-negotiation if it's enabled *) ReadRegister16(BMCR, value, res); IF res # Ok THEN RETURN; END; IF value * BMCR_AutoNegotiationEnable # {} THEN WriteRegister16(BMCR, value - BMCR_AutoNegotiationEnable, res); IF res # Ok THEN RETURN; END; END; (* set link speed and duplex mode *) IF fullDuplex THEN value := value + BMCR_DuplexMode; ELSE value := value - BMCR_DuplexMode; END; IF speed = 10 THEN value := value - BMCR_SpeedSelectionMsb - BMCR_SpeedSelectionLsb; ELSIF speed = 100 THEN value := value - BMCR_SpeedSelectionMsb + BMCR_SpeedSelectionLsb; ELSE value := value + BMCR_SpeedSelectionMsb - BMCR_SpeedSelectionLsb; END; WriteRegister16(BMCR, value, res); END ConfigureLink; PROCEDURE EnableLoopback*(enable : BOOLEAN; VAR res : WORD); VAR value : SET; BEGIN ASSERT(lockedBy = Objects.ActiveObject()); IF Trace * TraceCommands # {} THEN IF enable THEN Show("Enable "); ELSE Show("Disable "); END; KernelLog.String("loopback."); KernelLog.Ln; END; ReadRegister16(BMCR, value, res); IF res # Ok THEN RETURN; END; IF enable THEN value := value + BMCR_Loopback; ELSE value := value - BMCR_Loopback; END; WriteRegister16(BMCR, value + BMCR_Loopback, res); END EnableLoopback; (** Reset the PHY. Sets the Control and the Status registers to their default values. *) PROCEDURE Reset*(VAR res : WORD); VAR timeout, interval : LONGINT; value : SET; BEGIN (* {EXCLUSIVE} *) ASSERT(lockedBy = Objects.ActiveObject()); IF Trace * TraceCommands # {} THEN Show("Reset PHY... "); END; WriteRegister16(BMCR, BMCR_Reset, res); IF res # Ok THEN RETURN; END; (* 0.5s timeout according to [1], page 512 *) timeout := 500; interval := 10; LOOP timer.Sleep(interval); ReadRegister16(BMCR, value, res); IF (value * BMCR_Reset = {}) OR (res # Ok) THEN EXIT; END; DEC(timeout, interval); IF timeout <= 0 THEN res := Timeout; EXIT; END END; IF Trace * TraceCommands # {} THEN KernelLog.String("done."); KernelLog.Ln; END; END Reset; PROCEDURE GetIdentifier*(VAR identifier : Identifier; VAR res : WORD); VAR phyIdr1, phyIdr2 : SET; BEGIN ASSERT(lockedBy = Objects.ActiveObject()); ReadRegister16(PHYIDR1, phyIdr1, res); IF res # Ok THEN IF Debug THEN Show("Could not read PHYIDR1 register."); KernelLog.Ln; END; RETURN; END; ReadRegister16(PHYIDR2, phyIdr2, res); IF res # Ok THEN IF Debug THEN Show("Could not read PHYIDR2 register."); KernelLog.Ln; END; RETURN; END; identifier.oui := SYSTEM.VAL(LONGINT, LSH(phyIdr1 * PHYIDR1_OuiMSB, 3) + LSH(phyIdr2 * PHYIDR2_OuiLSB, 9)); identifier.model := SYSTEM.VAL(LONGINT, LSH(phyIdr2 * PHYIDR2_VendorModel, -4)); identifier.revision := SYSTEM.VAL(LONGINT, phyIdr2 * PHYIDR2_ModelRevision); END GetIdentifier; PROCEDURE Diag*; VAR identifier : Identifier; res : WORD; bmsr, anar, anlpar, register : SET; BEGIN ASSERT(lockedBy = Objects.ActiveObject()); KernelLog.String("MII information:"); KernelLog.Ln; KernelLog.String(" PHY ID: "); KernelLog.Hex(phyId, 0); KernelLog.Ln; GetIdentifier(identifier, res); IF res = Ok THEN KernelLog.String(" OUI: "); KernelLog.Hex(identifier.oui, 0); KernelLog.String(", Vendor model: "); KernelLog.Int(identifier.model, 0); KernelLog.String(", Revision: "); KernelLog.Int(identifier.revision, 0); ELSE KernelLog.String("Error: Could not read PHY Identification registers."); KernelLog.Ln; END; KernelLog.Ln; ReadRegister16(BMCR, register, res); IF res = Ok THEN ShowControlRegister(register); ELSE KernelLog.String("Error: Could not read BMCR register."); KernelLog.Ln; END; ReadRegister16(BMSR, bmsr, res); IF res = Ok THEN ShowStatusRegister(bmsr); ELSE KernelLog.String("Error: Could not read BMSR register."); KernelLog.Ln; END; KernelLog.String("Extended registers: "); KernelLog.Ln; IF bmsr * BMSR_ExtendedCapability # {} THEN ReadRegister16(ANAR, anar, res); IF res = Ok THEN ReadRegister16(ANLPAR, anlpar, res); IF res = Ok THEN ShowAdvertisementRegisters(anar, anlpar); ELSE KernelLog.String("Error: Could not read ANLPAR register."); KernelLog.Ln; END; ELSE KernelLog.String("Error: Could not read ANAR register."); KernelLog.Ln; END; ReadRegister16(ANER, register, res); IF res = Ok THEN ShowAnerRegister(register); ELSE KernelLog.String("Error: Could not read ANER register."); KernelLog.Ln; END; ELSE KernelLog.String("Extended registers not available."); KernelLog.Ln; END; IF bmsr * BMSR_ExtendedStatus # {} THEN ReadRegister16(BMESR, register, res); IF res = Ok THEN ShowExtendedStatusRegister(register); ELSE KernelLog.String("Error: Could not read BMESR register."); KernelLog.Ln; END; END; IF bmsr * BMSR_ExtendedCapability # {} THEN END; END Diag; PROCEDURE &Init*(phyId : LONGINT); BEGIN SELF.phyId := phyId; NEW(timer); lockedBy := NIL; END Init; END MII; PROCEDURE ShowControlRegister(bmcr : SET); BEGIN KernelLog.String("Basic Mode Control Register (BMCR):"); KernelLog.Ln; KernelLog.String(" Reset PHY: "); KernelLog.Boolean(bmcr * BMCR_Reset # {}); KernelLog.Ln; KernelLog.String(" Loopback: "); KernelLog.Boolean(bmcr * BMCR_Loopback # {}); KernelLog.Ln; KernelLog.String(" Auto-Negotiation Enable: "); KernelLog.Boolean(bmcr * BMCR_AutoNegotiationEnable # {}); KernelLog.Ln; KernelLog.String(" Power Down: "); KernelLog.Boolean(bmcr * BMCR_PowerDown # {}); KernelLog.Ln; KernelLog.String(" Isolate: "); KernelLog.Boolean(bmcr * BMCR_Isolate # {}); KernelLog.Ln; KernelLog.String(" Restart Auto-Negotiation: "); KernelLog.Boolean(bmcr * BMCR_RestartAutoNegotiation # {}); KernelLog.Ln; KernelLog.String(" Collision Test: "); KernelLog.Boolean(bmcr * BMCR_CollisionTest # {}); KernelLog.Ln; KernelLog.String(" Link Speed: "); IF bmcr * BMCR_AutoNegotiationEnable = {} THEN IF bmcr * BMCR_SpeedSelectionMsb = {} THEN IF bmcr * BMCR_SpeedSelectionLsb # {} THEN KernelLog.String("100 Mbps"); ELSE KernelLog.String("10 Mbps"); END; ELSE IF bmcr * BMCR_SpeedSelectionMsb # {} THEN KernelLog.String("1000 Mbps"); ELSE KernelLog.String("Invalid setting"); END; END; IF bmcr * BMCR_DuplexMode # {} THEN KernelLog.String(" (Full Duplex)"); ELSE KernelLog.String(" (Half Duplex)"); END; ELSE KernelLog.String("Reported in BMSR since Auto-negotiation is enabled"); END; KernelLog.Ln; END ShowControlRegister; PROCEDURE ShowStatusRegister(bmsr : SET); BEGIN KernelLog.String("Basic Mode Status Register (BMSR):"); KernelLog.Ln; KernelLog.String(" Link Capabilities:"); KernelLog.Ln; KernelLog.String(" 100BaseT4: "); KernelLog.Boolean(bmsr * BMSR_100BaseT4 # {}); KernelLog.Ln; KernelLog.String(" 100BaseX Full Duplex: "); KernelLog.Boolean(bmsr * BMSR_100BaseTXFullDuplex # {}); KernelLog.Ln; KernelLog.String(" 100BaseX Half Duplex: "); KernelLog.Boolean(bmsr * BMSR_100BaseTXHalfDuplex # {}); KernelLog.Ln; KernelLog.String(" 10Mb/s Full Duplex: "); KernelLog.Boolean(bmsr * BMSR_10BaseTFullDuplex # {}); KernelLog.Ln; KernelLog.String(" 10Mb/s Half Fuplex: "); KernelLog.Boolean(bmsr * BMSR_10BaseTHalfDuplex # {}); KernelLog.Ln; KernelLog.String(" 100BaseT2FullDuplex: "); KernelLog.Boolean(bmsr * BMSR_100BaseT2FullDuplex # {}); KernelLog.Ln; KernelLog.String(" 100BaseT2HalfDuplex: "); KernelLog.Boolean(bmsr * BMSR_100BaseT2HalfDuplex # {}); KernelLog.Ln; KernelLog.String(" Extended Status Register available: "); KernelLog.Boolean(bmsr * BMSR_ExtendedStatus # {}); KernelLog.Ln; KernelLog.String(" MF Preamble Suppression: "); KernelLog.Boolean(bmsr * BMSR_MfPreambleSuppression # {}); KernelLog.Ln; KernelLog.String(" Auto-Negotiation complete: "); KernelLog.Boolean(bmsr * BMSR_AutoNegotiationComplete # {}); KernelLog.Ln; KernelLog.String(" Remote Fault: "); KernelLog.Boolean(bmsr * BMSR_RemoteFault # {}); KernelLog.Ln; KernelLog.String(" Auto-Negotiation Ability: "); KernelLog.Boolean(bmsr * BMSR_AutoNegotiationAbility # {}); KernelLog.Ln; KernelLog.String(" Link status: "); IF bmsr * BMSR_LinkStatus # {} THEN KernelLog.String("UP"); ELSE KernelLog.String("DOWN"); END; KernelLog.Ln; KernelLog.String(" Jabber Detected: "); KernelLog.Boolean(bmsr * BMSR_JabberDetect # {}); KernelLog.Ln; KernelLog.String(" Extended Capability: "); KernelLog.Boolean(bmsr * BMSR_ExtendedCapability # {}); KernelLog.Ln; END ShowStatusRegister; PROCEDURE ShowAdvertisementRegisters(anar, anlpar : SET); PROCEDURE ShowBit(CONST title : ARRAY OF CHAR; bit : SET); BEGIN KernelLog.String(title); KernelLog.Boolean(anar * bit # {}); KernelLog.String(", Link partner: "); KernelLog.Boolean(anlpar * bit # {}); KernelLog.Ln; END ShowBit; BEGIN KernelLog.String("Auto-Negotiation Advertisement Registers (ANAR/ANLPAR):"); KernelLog.Ln; ShowBit(" Next page indication: ", ANAR_NextPageIndication); ShowBit(" Ackknowlegdement: ", ANAR_Ackknowlegdement); ShowBit(" Remote Fault: ", ANAR_RemoteFault); ShowBit(" Asymmetric Pause: ", ANAR_AsymmetricPause); ShowBit(" Pause: ", ANAR_Pause); ShowBit(" 100BaseT4 support: ", ANAR_100BaseT4Support); ShowBit(" 100BaseTX Full Duplex support: ", ANAR_100BaseTXFullDuplex); ShowBit(" 100BaseTX Half Duplex support: ", ANAR_100BaseTXHalfDuplex); ShowBit(" 10BaseT Full Duplex support: ", ANAR_10BaseTFullDuplex); ShowBit(" 10BaseT Half Duplex support: ", ANAR_10BaseTHalfDuplex); KernelLog.String(" Selector: "); KernelLog.Int(SYSTEM.VAL(LONGINT, anar * ANAR_Selector), 0); KernelLog.String(", Link partner: "); KernelLog.Int(SYSTEM.VAL(LONGINT, anlpar * ANAR_Selector), 0); KernelLog.Ln; END ShowAdvertisementRegisters; PROCEDURE ShowAnerRegister(aner : SET); BEGIN KernelLog.String("Auto-Negotiation Extension Register (ANER):"); KernelLog.Ln; KernelLog.String(" Parallel Detection Fault: "); KernelLog.Boolean(aner * ANER_ParallelDetectionFault # {}); KernelLog.Ln; KernelLog.String(" Link Partner Next Page Enable: "); KernelLog.Boolean(aner * ANER_LinkPartnerNextPageEnable # {}); KernelLog.Ln; KernelLog.String(" PHY Next Page Enable: "); KernelLog.Boolean(aner * ANER_PhyNextPageEnable # {}); KernelLog.Ln; KernelLog.String(" New Page Reception: "); KernelLog.Boolean(aner * ANER_NewPageReception # {}); KernelLog.Ln; KernelLog.String(" Link Partner Auto-Negotiation Enable: "); KernelLog.Boolean(aner * ANER_LinkPartnerAnEnable # {}); KernelLog.Ln; END ShowAnerRegister; PROCEDURE ShowExtendedStatusRegister(bmesr : SET); BEGIN KernelLog.String("Base Mode Extended Status Register (BMESR):"); KernelLog.Ln; KernelLog.String(" Link Capabilities:"); KernelLog.Ln; KernelLog.String(" 1000BaseX Full Duplex: "); KernelLog.Boolean(bmesr * BMESR_1000BaseXFullDuplex # {}); KernelLog.Ln; KernelLog.String(" 1000BaseX Half Duplex: "); KernelLog.Boolean(bmesr * BMESR_1000BaseXHalfDuplex # {}); KernelLog.Ln; KernelLog.String(" 1000BaseT Full Duplex: "); KernelLog.Boolean(bmesr * BMESR_1000BaseTFullDuplex # {}); KernelLog.Ln; KernelLog.String(" 1000BaseT Half Duplex: "); KernelLog.Boolean(bmesr * BMESR_1000BaseTHalfDuplex # {}); KernelLog.Ln; END ShowExtendedStatusRegister; PROCEDURE Show(CONST string : ARRAY OF CHAR); BEGIN KernelLog.String(ModuleName); KernelLog.String(": "); KernelLog.String(string); END Show; END NetworkMii.