From 1d2da6617feb086abad41412de1cf8731480731f Mon Sep 17 00:00:00 2001 From: jkim Date: Fri, 2 Apr 2010 16:48:51 +0000 Subject: Import ACPICA 20100331. --- changes.txt | 75 +++++++++ common/dmextern.c | 9 ++ compiler/aslanalyze.c | 6 + compiler/aslcompiler.h | 5 + compiler/aslpredef.c | 109 ++++++++++++- compiler/aslstubs.c | 7 - compiler/asltypes.h | 2 +- debugger/dbdisply.c | 59 +++---- events/evgpe.c | 279 +++++++++++++-------------------- events/evgpeblk.c | 196 +++++++++++------------ events/evxface.c | 2 +- events/evxfevnt.c | 282 +++++++++++++++++++++------------- executer/exdebug.c | 2 +- executer/exmutex.c | 32 ++-- executer/exoparg2.c | 27 ---- executer/exregion.c | 13 +- include/acevents.h | 20 +-- include/acexcep.h | 2 +- include/acglobal.h | 13 ++ include/aclocal.h | 3 + include/acpixf.h | 15 +- include/actables.h | 8 + include/actypes.h | 51 +++--- include/platform/acfreebsd.h | 33 ++-- os_specific/service_layers/oswintbl.c | 35 ++++- os_specific/service_layers/oswinxf.c | 6 +- parser/psxface.c | 5 + tables/tbutils.c | 82 ++++++++++ tables/tbxface.c | 63 +++++--- tools/acpiexec/aeexec.c | 55 +++---- utilities/utglobal.c | 1 + 31 files changed, 880 insertions(+), 617 deletions(-) diff --git a/changes.txt b/changes.txt index 5bd82ab..d2c8c0e 100644 --- a/changes.txt +++ b/changes.txt @@ -1,4 +1,79 @@ ---------------------------------------- +31 March 2010. Summary of changes for version 20100331: + +1) ACPI CA Core Subsystem: + +Completed a major update for the GPE support in order to improve support for +shared GPEs and to simplify both host OS and ACPICA code. Added a reference +count mechanism to support shared GPEs that require multiple device drivers. +Several external interfaces have changed. One external interface has been +removed. One new external interface was added. Most of the GPE external +interfaces now use the GPE spinlock instead of the events mutex (and the +Flags parameter for many GPE interfaces has been removed.) See the updated +ACPICA Programmer Reference for details. Matthew Garrett, Bob Moore, Rafael +Wysocki. ACPICA BZ 831. + +Changed: + AcpiEnableGpe, AcpiDisableGpe, AcpiClearGpe, AcpiGetGpeStatus +Removed: + AcpiSetGpeType +New: + AcpiSetGpe + +Implemented write support for DataTable operation regions. These regions are +defined via the DataTableRegion() operator. Previously, only read support was +implemented. The ACPI specification allows DataTableRegions to be read/write, +however. + +Implemented a new subsystem option to force a copy of the DSDT to local +memory. Optionally copy the entire DSDT to local memory (instead of simply +mapping it.) There are some (albeit very rare) BIOSs that corrupt or replace +the original DSDT, creating the need for this option. Default is FALSE, do +not copy the DSDT. + +Implemented detection of a corrupted or replaced DSDT. This change adds +support to detect a DSDT that has been corrupted and/or replaced from outside +the OS (by firmware). This is typically catastrophic for the system, but has +been seen on some machines. Once this problem has been detected, the DSDT +copy option can be enabled via system configuration. Lin Ming, Bob Moore. + +Fixed two problems with AcpiReallocateRootTable during the root table copy. +When copying the root table to the new allocation, the length used was +incorrect. The new size was used instead of the current table size, meaning +too much data was copied. Also, the count of available slots for ACPI tables +was not set correctly. Alexey Starikovskiy, Bob Moore. + +Example Code and Data Size: These are the sizes for the OS-independent +acpica.lib produced by the Microsoft Visual C++ 6.0 32-bit compiler. The +debug version of the code includes the debug output trace mechanism and has a +much larger code and data size. + + Previous Release: + Non-Debug Version: 87.5K Code, 18.4K Data, 105.9K Total + Debug Version: 163.4K Code, 51.1K Data, 214.5K Total + Current Release: + Non-Debug Version: 87.9K Code, 18.6K Data, 106.5K Total + Debug Version: 163.5K Code, 51.3K Data, 214.8K Total + +2) iASL Compiler/Disassembler and Tools: + +iASL: Implement limited typechecking for values returned from predefined +control methods. The type of any returned static (unnamed) object is now +validated. For example, Return(1). ACPICA BZ 786. + +iASL: Fixed a predefined name object verification regression. Fixes a problem +introduced in version 20100304. An error is incorrectly generated if a +predefined name is declared as a static named object with a value defined +using the keywords "Zero", "One", or "Ones". Lin Ming. + +iASL: Added Windows 7 support for the -g option (get local ACPI tables) by +reducing the requested registry access rights. ACPICA BZ 842. + +Disassembler: fixed a possible fault when generating External() statements. +Introduced in commit ae7d6fd: Properly handle externals with parent-prefix +(carat). Fixes a string length allocation calculation. Lin Ming. + +---------------------------------------- 04 March 2010. Summary of changes for version 20100304: 1) ACPI CA Core Subsystem: diff --git a/common/dmextern.c b/common/dmextern.c index 5afd034..ab46b69 100644 --- a/common/dmextern.c +++ b/common/dmextern.c @@ -270,6 +270,15 @@ AcpiDmNormalizeParentPrefix ( } Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1); + if (ParentPath[1]) + { + /* + * If ParentPath is not just a simple '\', increment the length + * for the required dot separator (ParentPath.Path) + */ + Length++; + } + Fullpath = ACPI_ALLOCATE_ZEROED (Length); if (!Fullpath) { diff --git a/compiler/aslanalyze.c b/compiler/aslanalyze.c index eaefd3f..19440c8 100644 --- a/compiler/aslanalyze.c +++ b/compiler/aslanalyze.c @@ -1157,6 +1157,12 @@ AnMethodAnalysisWalkEnd ( case PARSEOP_RETURN: /* + * If the parent is a predefined method name, attempt to typecheck + * the return value. Only static types can be validated. + */ + ApCheckPredefinedReturnValue (Op, MethodInfo); + + /* * The parent block does not "exit" and continue execution -- the * method is terminated here with the Return() statement. */ diff --git a/compiler/aslcompiler.h b/compiler/aslcompiler.h index cf6c8f3..5083798 100644 --- a/compiler/aslcompiler.h +++ b/compiler/aslcompiler.h @@ -461,6 +461,11 @@ ApCheckForPredefinedMethod ( ACPI_PARSE_OBJECT *Op, ASL_METHOD_INFO *MethodInfo); +void +ApCheckPredefinedReturnValue ( + ACPI_PARSE_OBJECT *Op, + ASL_METHOD_INFO *MethodInfo); + UINT32 ApCheckForPredefinedName ( ACPI_PARSE_OBJECT *Op, diff --git a/compiler/aslpredef.c b/compiler/aslpredef.c index 04cd2d4..6346baf 100644 --- a/compiler/aslpredef.c +++ b/compiler/aslpredef.c @@ -296,7 +296,11 @@ ApCheckForPredefinedMethod ( if (MethodInfo->NumReturnNoValue && PredefinedNames[Index].Info.ExpectedBtypes) { - sprintf (MsgBuffer, "%4.4s", PredefinedNames[Index].Info.Name); + ApGetExpectedTypes (StringBuffer, + PredefinedNames[Index].Info.ExpectedBtypes); + + sprintf (MsgBuffer, "%s required for %4.4s", + StringBuffer, PredefinedNames[Index].Info.Name); AslError (ASL_WARNING, ASL_MSG_RESERVED_RETURN_VALUE, Op, MsgBuffer); @@ -308,6 +312,90 @@ ApCheckForPredefinedMethod ( /******************************************************************************* * + * FUNCTION: ApCheckPredefinedReturnValue + * + * PARAMETERS: Op - A parse node of type "RETURN". + * MethodInfo - Saved info about this method + * + * RETURN: None + * + * DESCRIPTION: If method is a predefined name, attempt to validate the return + * value. Only "static" types can be validated - a simple return + * of an integer/string/buffer/package or a named reference to + * a static object. Values such as a Localx or Argx or a control + * method invocation are not checked. + * + ******************************************************************************/ + +void +ApCheckPredefinedReturnValue ( + ACPI_PARSE_OBJECT *Op, + ASL_METHOD_INFO *MethodInfo) +{ + UINT32 Index; + ACPI_PARSE_OBJECT *ReturnValueOp; + + + /* Check parent method for a match against the predefined name list */ + + Index = ApCheckForPredefinedName (MethodInfo->Op, + MethodInfo->Op->Asl.NameSeg); + + switch (Index) + { + case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */ + case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */ + case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */ + case ACPI_EVENT_RESERVED_NAME: /* _Lxx, _Exx, and _Qxx methods */ + + /* Just return, nothing to do */ + return; + + default: /* a real predefined ACPI name */ + + /* Exit if no return value expected */ + + if (!PredefinedNames[Index].Info.ExpectedBtypes) + { + return; + } + + /* Get the object returned, it is the next argument */ + + ReturnValueOp = Op->Asl.Child; + switch (ReturnValueOp->Asl.ParseOpcode) + { + case PARSEOP_ZERO: + case PARSEOP_ONE: + case PARSEOP_ONES: + case PARSEOP_INTEGER: + case PARSEOP_STRING_LITERAL: + case PARSEOP_BUFFER: + case PARSEOP_PACKAGE: + + /* Static data return object - check against expected type */ + + ApCheckObjectType (ReturnValueOp, + PredefinedNames[Index].Info.ExpectedBtypes); + break; + + default: + + /* + * All other ops are very difficult or impossible to typecheck at + * compile time. These include all Localx, Argx, and method + * invocations. Also, NAMESEG and NAMESTRING because the type of + * any named object can be changed at runtime (for example, + * CopyObject will change the type of the target object.) + */ + break; + } + } +} + + +/******************************************************************************* + * * FUNCTION: ApCheckForPredefinedObject * * PARAMETERS: Op - A parse node @@ -441,7 +529,7 @@ ApCheckForPredefinedName ( * * RETURN: None * - * DESCRIPTION: Check for the "special" predefined names - + * DESCRIPTION: Check for the "special" predefined names - * _Lxx, _Exx, _Qxx, and _T_x * ******************************************************************************/ @@ -512,7 +600,7 @@ ApCheckForSpecialName ( * * FUNCTION: ApCheckObjectType * - * PARAMETERS: Op - A parse node + * PARAMETERS: Op - Current parse node * ExpectedBtypes - Bitmap of expected return type(s) * * RETURN: None @@ -529,11 +617,13 @@ ApCheckObjectType ( UINT32 ExpectedBtypes) { UINT32 ReturnBtype; - char TypeBuffer[48]; /* Room for 5 types */ switch (Op->Asl.ParseOpcode) { + case PARSEOP_ZERO: + case PARSEOP_ONE: + case PARSEOP_ONES: case PARSEOP_INTEGER: ReturnBtype = ACPI_RTYPE_INTEGER; break; @@ -552,11 +642,11 @@ ApCheckObjectType ( default: /* Not one of the supported object types */ - + goto TypeErrorExit; } - /* Is the object one of the expected types? */ + /* Exit if the object is one of the expected types */ if (ReturnBtype & ExpectedBtypes) { @@ -568,10 +658,13 @@ TypeErrorExit: /* Format the expected types and emit an error message */ - ApGetExpectedTypes (TypeBuffer, ExpectedBtypes); + ApGetExpectedTypes (StringBuffer, ExpectedBtypes); + + sprintf (MsgBuffer, "found %s, requires %s", + UtGetOpName (Op->Asl.ParseOpcode), StringBuffer); AslError (ASL_ERROR, ASL_MSG_RESERVED_OPERAND_TYPE, Op, - TypeBuffer); + MsgBuffer); } diff --git a/compiler/aslstubs.c b/compiler/aslstubs.c index 8f3de7e..4555873 100644 --- a/compiler/aslstubs.c +++ b/compiler/aslstubs.c @@ -243,13 +243,6 @@ AcpiEvInitializeRegion ( return (AE_OK); } -ACPI_STATUS -AcpiEvCheckForWakeOnlyGpe ( - ACPI_GPE_EVENT_INFO *GpeEventInfo) -{ - return (AE_OK); -} - void AcpiExDoDebugObject ( ACPI_OPERAND_OBJECT *SourceDesc, diff --git a/compiler/asltypes.h b/compiler/asltypes.h index 6edf987..30b8fdf 100644 --- a/compiler/asltypes.h +++ b/compiler/asltypes.h @@ -507,7 +507,7 @@ char *AslMessages [] = { /* ASL_MSG_RESERVED_ARG_COUNT_HI */ "Reserved method has too many arguments", /* ASL_MSG_RESERVED_ARG_COUNT_LO */ "Reserved method has too few arguments", /* ASL_MSG_RESERVED_METHOD */ "Reserved name must be a control method", -/* ASL_MSG_RESERVED_OPERAND_TYPE */ "Invalid object type for reserved name, must be", +/* ASL_MSG_RESERVED_OPERAND_TYPE */ "Invalid object type for reserved name", /* ASL_MSG_RESERVED_RETURN_VALUE */ "Reserved method must return a value", /* ASL_MSG_RESERVED_USE */ "Invalid use of reserved name", /* ASL_MSG_RESERVED_WORD */ "Use of reserved name", diff --git a/debugger/dbdisply.c b/debugger/dbdisply.c index 7c04ffc..ec4715b 100644 --- a/debugger/dbdisply.c +++ b/debugger/dbdisply.c @@ -848,13 +848,12 @@ AcpiDbDisplayGpes ( Block, GpeBlock, GpeBlock->Node, Buffer); AcpiOsPrintf (" Registers: %u (%u GPEs)\n", - GpeBlock->RegisterCount, - ACPI_MUL_8 (GpeBlock->RegisterCount)); + GpeBlock->RegisterCount, GpeBlock->GpeCount); - AcpiOsPrintf (" GPE range: 0x%X to 0x%X\n", + AcpiOsPrintf (" GPE range: 0x%X to 0x%X on interrupt %u\n", GpeBlock->BlockBaseNumber, - GpeBlock->BlockBaseNumber + - (GpeBlock->RegisterCount * 8) -1); + GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1), + GpeXruptInfo->InterruptNumber); AcpiOsPrintf ( " RegisterInfo: %p Status %8.8X%8.8X Enable %8.8X%8.8X\n", @@ -871,9 +870,12 @@ AcpiDbDisplayGpes ( GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; AcpiOsPrintf ( - " Reg %u: WakeEnable %2.2X, RunEnable %2.2X Status %8.8X%8.8X Enable %8.8X%8.8X\n", - i, GpeRegisterInfo->EnableForWake, + " Reg %u: (GPE %.2X-%.2X) RunEnable %2.2X WakeEnable %2.2X" + " Status %8.8X%8.8X Enable %8.8X%8.8X\n", + i, GpeRegisterInfo->BaseGpeNumber, + GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), GpeRegisterInfo->EnableForRun, + GpeRegisterInfo->EnableForWake, ACPI_FORMAT_UINT64 (GpeRegisterInfo->StatusAddress.Address), ACPI_FORMAT_UINT64 (GpeRegisterInfo->EnableAddress.Address)); @@ -886,17 +888,19 @@ AcpiDbDisplayGpes ( if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)) { - /* This GPE is not used (no method or handler) */ + /* This GPE is not used (no method or handler), ignore it */ continue; } AcpiOsPrintf ( - " GPE %.3X: %p Flags %2.2X: ", - GpeBlock->BlockBaseNumber + GpeIndex, - GpeEventInfo, + " GPE %.2X: %p RunRefs %2.2X WakeRefs %2.2X Flags %2.2X (", + GpeBlock->BlockBaseNumber + GpeIndex, GpeEventInfo, + GpeEventInfo->RuntimeCount, GpeEventInfo->WakeupCount, GpeEventInfo->Flags); + /* Decode the flags byte */ + if (GpeEventInfo->Flags & ACPI_GPE_LEVEL_TRIGGERED) { AcpiOsPrintf ("Level, "); @@ -906,38 +910,13 @@ AcpiDbDisplayGpes ( AcpiOsPrintf ("Edge, "); } - switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) - { - case ACPI_GPE_TYPE_WAKE: - AcpiOsPrintf ("WakeOnly: "); - break; - case ACPI_GPE_TYPE_RUNTIME: - AcpiOsPrintf (" RunOnly: "); - break; - case ACPI_GPE_TYPE_WAKE_RUN: - AcpiOsPrintf (" WakeRun: "); - break; - default: - AcpiOsPrintf (" NotUsed: "); - break; - } - - if (GpeEventInfo->Flags & ACPI_GPE_WAKE_ENABLED) - { - AcpiOsPrintf ("[Wake 1 "); - } - else - { - AcpiOsPrintf ("[Wake 0 "); - } - - if (GpeEventInfo->Flags & ACPI_GPE_RUN_ENABLED) + if (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) { - AcpiOsPrintf ("Run 1], "); + AcpiOsPrintf ("CanWake, "); } else { - AcpiOsPrintf ("Run 0], "); + AcpiOsPrintf ("RunOnly, "); } switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) @@ -957,7 +936,7 @@ AcpiDbDisplayGpes ( break; } - AcpiOsPrintf ("\n"); + AcpiOsPrintf (")\n"); } } Block++; diff --git a/events/evgpe.c b/events/evgpe.c index 41efada..d3569b1 100644 --- a/events/evgpe.c +++ b/events/evgpe.c @@ -134,71 +134,20 @@ AcpiEvAsynchEnableGpe ( /******************************************************************************* * - * FUNCTION: AcpiEvSetGpeType - * - * PARAMETERS: GpeEventInfo - GPE to set - * Type - New type - * - * RETURN: Status - * - * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run) - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEvSetGpeType ( - ACPI_GPE_EVENT_INFO *GpeEventInfo, - UINT8 Type) -{ - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (EvSetGpeType); - - - /* Validate type and update register enable masks */ - - switch (Type) - { - case ACPI_GPE_TYPE_WAKE: - case ACPI_GPE_TYPE_RUNTIME: - case ACPI_GPE_TYPE_WAKE_RUN: - break; - - default: - return_ACPI_STATUS (AE_BAD_PARAMETER); - } - - /* Disable the GPE if currently enabled */ - - Status = AcpiEvDisableGpe (GpeEventInfo); - - /* Clear the type bits and insert the new Type */ - - GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK; - GpeEventInfo->Flags |= Type; - return_ACPI_STATUS (Status); -} - - -/******************************************************************************* - * * FUNCTION: AcpiEvUpdateGpeEnableMasks * * PARAMETERS: GpeEventInfo - GPE to update - * Type - What to do: ACPI_GPE_DISABLE or - * ACPI_GPE_ENABLE * * RETURN: Status * - * DESCRIPTION: Updates GPE register enable masks based on the GPE type + * DESCRIPTION: Updates GPE register enable masks based upon whether there are + * references (either wake or run) to this GPE * ******************************************************************************/ ACPI_STATUS AcpiEvUpdateGpeEnableMasks ( - ACPI_GPE_EVENT_INFO *GpeEventInfo, - UINT8 Type) + ACPI_GPE_EVENT_INFO *GpeEventInfo) { ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; UINT8 RegisterBit; @@ -216,36 +165,21 @@ AcpiEvUpdateGpeEnableMasks ( RegisterBit = (UINT8) (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); - /* 1) Disable case. Simply clear all enable bits */ + /* Clear the wake/run bits up front */ - if (Type == ACPI_GPE_DISABLE) - { - ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); - ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); - return_ACPI_STATUS (AE_OK); - } + ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); + ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); - /* 2) Enable case. Set/Clear the appropriate enable bits */ + /* Set the mask bits only if there are references to this GPE */ - switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) + if (GpeEventInfo->RuntimeCount) { - case ACPI_GPE_TYPE_WAKE: - ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); - ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); - break; - - case ACPI_GPE_TYPE_RUNTIME: - ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); - ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); - break; - - case ACPI_GPE_TYPE_WAKE_RUN: - ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); - ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); - break; + ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); + } - default: - return_ACPI_STATUS (AE_BAD_PARAMETER); + if (GpeEventInfo->WakeupCount) + { + ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); } return_ACPI_STATUS (AE_OK); @@ -257,19 +191,19 @@ AcpiEvUpdateGpeEnableMasks ( * FUNCTION: AcpiEvEnableGpe * * PARAMETERS: GpeEventInfo - GPE to enable - * WriteToHardware - Enable now, or just mark data structs - * (WAKE GPEs should be deferred) * * RETURN: Status * - * DESCRIPTION: Enable a GPE based on the GPE type + * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless + * of type or number of references. + * + * Note: The GPE lock should be already acquired when this function is called. * ******************************************************************************/ ACPI_STATUS AcpiEvEnableGpe ( - ACPI_GPE_EVENT_INFO *GpeEventInfo, - BOOLEAN WriteToHardware) + ACPI_GPE_EVENT_INFO *GpeEventInfo) { ACPI_STATUS Status; @@ -277,54 +211,37 @@ AcpiEvEnableGpe ( ACPI_FUNCTION_TRACE (EvEnableGpe); - /* Make sure HW enable masks are updated */ + /* + * We will only allow a GPE to be enabled if it has either an + * associated method (_Lxx/_Exx) or a handler. Otherwise, the + * GPE will be immediately disabled by AcpiEvGpeDispatch the + * first time it fires. + */ + if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)) + { + return_ACPI_STATUS (AE_NO_HANDLER); + } + + /* Ensure the HW enable masks are current */ - Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE); + Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } - /* Mark wake-enabled or HW enable, or both */ + /* Clear the GPE (of stale events) */ - switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) + Status = AcpiHwClearGpe (GpeEventInfo); + if (ACPI_FAILURE (Status)) { - case ACPI_GPE_TYPE_WAKE: - - ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED); - break; - - case ACPI_GPE_TYPE_WAKE_RUN: - - ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED); - - /*lint -fallthrough */ - - case ACPI_GPE_TYPE_RUNTIME: - - ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED); - - if (WriteToHardware) - { - /* Clear the GPE (of stale events), then enable it */ - - Status = AcpiHwClearGpe (GpeEventInfo); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Enable the requested runtime GPE */ - - Status = AcpiHwWriteGpeEnableReg (GpeEventInfo); - } - break; - - default: - return_ACPI_STATUS (AE_BAD_PARAMETER); + return_ACPI_STATUS (Status); } - return_ACPI_STATUS (AE_OK); + /* Enable the requested GPE */ + + Status = AcpiHwWriteGpeEnableReg (GpeEventInfo); + return_ACPI_STATUS (Status); } @@ -336,7 +253,10 @@ AcpiEvEnableGpe ( * * RETURN: Status * - * DESCRIPTION: Disable a GPE based on the GPE type + * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE, + * regardless of the type or number of references. + * + * Note: The GPE lock should be already acquired when this function is called. * ******************************************************************************/ @@ -356,40 +276,14 @@ AcpiEvDisableGpe ( * the GPE behind our back. */ - /* Make sure HW enable masks are updated */ + /* Ensure the HW enable masks are current */ - Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE); + Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } - /* Clear the appropriate enabled flags for this GPE */ - - switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) - { - case ACPI_GPE_TYPE_WAKE: - - ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED); - break; - - case ACPI_GPE_TYPE_WAKE_RUN: - - ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED); - - /*lint -fallthrough */ - - case ACPI_GPE_TYPE_RUNTIME: - - /* Disable the requested runtime GPE */ - - ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED); - break; - - default: - break; - } - /* * Always H/W disable this GPE, even if we don't know the GPE type. * Simply clear the enable bit for this particular GPE, but do not @@ -405,6 +299,49 @@ AcpiEvDisableGpe ( /******************************************************************************* * + * FUNCTION: AcpiEvLowGetGpeInfo + * + * PARAMETERS: GpeNumber - Raw GPE number + * GpeBlock - A GPE info block + * + * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber + * is not within the specified GPE block) + * + * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is + * the low-level implementation of EvGetGpeEventInfo. + * + ******************************************************************************/ + +ACPI_GPE_EVENT_INFO * +AcpiEvLowGetGpeInfo ( + UINT32 GpeNumber, + ACPI_GPE_BLOCK_INFO *GpeBlock) +{ + UINT32 GpeIndex; + + + /* + * Validate that the GpeNumber is within the specified GpeBlock. + * (Two steps) + */ + if (!GpeBlock || + (GpeNumber < GpeBlock->BlockBaseNumber)) + { + return (NULL); + } + + GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber; + if (GpeIndex >= GpeBlock->GpeCount) + { + return (NULL); + } + + return (&GpeBlock->EventInfo[GpeIndex]); +} + + +/******************************************************************************* + * * FUNCTION: AcpiEvGetGpeEventInfo * * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 @@ -426,7 +363,7 @@ AcpiEvGetGpeEventInfo ( UINT32 GpeNumber) { ACPI_OPERAND_OBJECT *ObjDesc; - ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_EVENT_INFO *GpeInfo; UINT32 i; @@ -441,16 +378,11 @@ AcpiEvGetGpeEventInfo ( for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) { - GpeBlock = AcpiGbl_GpeFadtBlocks[i]; - if (GpeBlock) + GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber, + AcpiGbl_GpeFadtBlocks[i]); + if (GpeInfo) { - if ((GpeNumber >= GpeBlock->BlockBaseNumber) && - (GpeNumber < GpeBlock->BlockBaseNumber + - (GpeBlock->RegisterCount * 8))) - { - return (&GpeBlock->EventInfo[GpeNumber - - GpeBlock->BlockBaseNumber]); - } + return (GpeInfo); } } @@ -468,15 +400,7 @@ AcpiEvGetGpeEventInfo ( return (NULL); } - GpeBlock = ObjDesc->Device.GpeBlock; - - if ((GpeNumber >= GpeBlock->BlockBaseNumber) && - (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8))) - { - return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]); - } - - return (NULL); + return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock)); } @@ -654,9 +578,9 @@ AcpiEvAsynchExecuteGpeMethod ( return_VOID; } - /* Set the GPE flags for return to enabled state */ + /* Update the GPE register masks for return to enabled state */ - (void) AcpiEvEnableGpe (GpeEventInfo, FALSE); + (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); /* * Take a snapshot of the GPE info for this level - we copy the info to @@ -872,15 +796,18 @@ AcpiEvGpeDispatch ( default: - /* No handler or method to run! */ - + /* + * No handler or method to run! + * 03/2010: This case should no longer be possible. We will not allow + * a GPE to be enabled if it has no handler or method. + */ ACPI_ERROR ((AE_INFO, "No handler or method for GPE[0x%2X], disabling event", GpeNumber)); /* - * Disable the GPE. The GPE will remain disabled until the ACPICA - * Core Subsystem is restarted, or a handler is installed. + * Disable the GPE. The GPE will remain disabled a handler + * is installed or ACPICA is restarted. */ Status = AcpiEvDisableGpe (GpeEventInfo); if (ACPI_FAILURE (Status)) diff --git a/events/evgpeblk.c b/events/evgpeblk.c index be6d45b..b109673 100644 --- a/events/evgpeblk.c +++ b/events/evgpeblk.c @@ -124,7 +124,7 @@ /* Local prototypes */ static ACPI_STATUS -AcpiEvSaveMethodInfo ( +AcpiEvMatchGpeMethod ( ACPI_HANDLE ObjHandle, UINT32 Level, void *ObjDesc, @@ -194,8 +194,7 @@ AcpiEvValidGpeEvent ( while (GpeBlock) { if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) && - (&GpeBlock->EventInfo[((ACPI_SIZE) - GpeBlock->RegisterCount) * 8] > GpeEventInfo)) + (&GpeBlock->EventInfo[GpeBlock->GpeCount] > GpeEventInfo)) { return (TRUE); } @@ -328,7 +327,7 @@ AcpiEvDeleteGpeHandlers ( /******************************************************************************* * - * FUNCTION: AcpiEvSaveMethodInfo + * FUNCTION: AcpiEvMatchGpeMethod * * PARAMETERS: Callback from WalkNamespace * @@ -340,8 +339,7 @@ AcpiEvDeleteGpeHandlers ( * information for quick lookup during GPE dispatch * * The name of each GPE control method is of the form: - * "_Lxx" or "_Exx" - * Where: + * "_Lxx" or "_Exx", where: * L - means that the GPE is level triggered * E - means that the GPE is edge triggered * xx - is the GPE number [in HEX] @@ -349,38 +347,44 @@ AcpiEvDeleteGpeHandlers ( ******************************************************************************/ static ACPI_STATUS -AcpiEvSaveMethodInfo ( +AcpiEvMatchGpeMethod ( ACPI_HANDLE ObjHandle, UINT32 Level, void *ObjDesc, void **ReturnValue) { + ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); ACPI_GPE_BLOCK_INFO *GpeBlock = (void *) ObjDesc; ACPI_GPE_EVENT_INFO *GpeEventInfo; UINT32 GpeNumber; char Name[ACPI_NAME_SIZE + 1]; UINT8 Type; - ACPI_STATUS Status; - ACPI_FUNCTION_TRACE (EvSaveMethodInfo); + ACPI_FUNCTION_TRACE (EvMatchGpeMethod); /* - * _Lxx and _Exx GPE method support + * Match and decode the _Lxx and _Exx GPE method names * - * 1) Extract the name from the object and convert to a string + * 1) Extract the method name and null terminate it */ - ACPI_MOVE_32_TO_32 ( - Name, &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Integer); + ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer); Name[ACPI_NAME_SIZE] = 0; + /* 2) Name must begin with an underscore */ + + if (Name[0] != '_') + { + return_ACPI_STATUS (AE_OK); /* Ignore this method */ + } + /* - * 2) Edge/Level determination is based on the 2nd character + * 3) Edge/Level determination is based on the 2nd character * of the method name * - * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE - * if a _PRW object is found that points to this GPE. + * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is + * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. */ switch (Name[1]) { @@ -393,16 +397,15 @@ AcpiEvSaveMethodInfo ( break; default: - /* Unknown method type, just ignore it! */ + /* Unknown method type, just ignore it */ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Ignoring unknown GPE method type: %s " - "(name not of form _Lxx or _Exx)", - Name)); + "(name not of form _Lxx or _Exx)", Name)); return_ACPI_STATUS (AE_OK); } - /* Convert the last two characters of the name to the GPE Number */ + /* 4) The last two characters of the name are the hex GPE Number */ GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); if (GpeNumber == ACPI_UINT32_MAX) @@ -411,45 +414,34 @@ AcpiEvSaveMethodInfo ( ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Could not extract GPE number from name: %s " - "(name is not of form _Lxx or _Exx)", - Name)); + "(name is not of form _Lxx or _Exx)", Name)); return_ACPI_STATUS (AE_OK); } /* Ensure that we have a valid GPE number for this GPE block */ - if ((GpeNumber < GpeBlock->BlockBaseNumber) || - (GpeNumber >= (GpeBlock->BlockBaseNumber + - (GpeBlock->RegisterCount * 8)))) + GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); + if (!GpeEventInfo) { /* - * Not valid for this GPE block, just ignore it. However, it may be - * valid for a different GPE block, since GPE0 and GPE1 methods both - * appear under \_GPE. + * This GpeNumber is not valid for this GPE block, just ignore it. + * However, it may be valid for a different GPE block, since GPE0 + * and GPE1 methods both appear under \_GPE. */ return_ACPI_STATUS (AE_OK); } /* - * Now we can add this information to the GpeEventInfo block for use - * during dispatch of this GPE. Default type is RUNTIME, although this may - * change when the _PRW methods are executed later. + * Add the GPE information from above to the GpeEventInfo block for + * use during dispatch of this GPE. */ - GpeEventInfo = &GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]; - - GpeEventInfo->Flags = (UINT8) - (Type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME); - - GpeEventInfo->Dispatch.MethodNode = (ACPI_NAMESPACE_NODE *) ObjHandle; - - /* Update enable mask, but don't enable the HW GPE as of yet */ - - Status = AcpiEvEnableGpe (GpeEventInfo, FALSE); + GpeEventInfo->Flags = (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); + GpeEventInfo->Dispatch.MethodNode = MethodNode; ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", Name, GpeNumber)); - return_ACPI_STATUS (Status); + return_ACPI_STATUS (AE_OK); } @@ -464,7 +456,7 @@ AcpiEvSaveMethodInfo ( * * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a * Device. Run the _PRW method. If present, extract the GPE - * number and mark the GPE as a WAKE GPE. + * number and mark the GPE as a CAN_WAKE GPE. * ******************************************************************************/ @@ -495,7 +487,7 @@ AcpiEvMatchPrwAndGpe ( ACPI_BTYPE_PACKAGE, &PkgDesc); if (ACPI_FAILURE (Status)) { - /* Ignore all errors from _PRW, we don't want to abort the subsystem */ + /* Ignore all errors from _PRW, we don't want to abort the walk */ return_ACPI_STATUS (AE_OK); } @@ -561,25 +553,17 @@ AcpiEvMatchPrwAndGpe ( * 2) The GPE index(number) is within the range of the Gpe Block * associated with the GPE device. */ - if ((GpeDevice == TargetGpeDevice) && - (GpeNumber >= GpeBlock->BlockBaseNumber) && - (GpeNumber < GpeBlock->BlockBaseNumber + - (GpeBlock->RegisterCount * 8))) + if (GpeDevice != TargetGpeDevice) { - GpeEventInfo = &GpeBlock->EventInfo[GpeNumber - - GpeBlock->BlockBaseNumber]; - - /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ - - GpeEventInfo->Flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); + goto Cleanup; + } - Status = AcpiEvSetGpeType (GpeEventInfo, ACPI_GPE_TYPE_WAKE); - if (ACPI_FAILURE (Status)) - { - goto Cleanup; - } + GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); + if (GpeEventInfo) + { + /* This GPE can wake the system */ - Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE); + GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; } Cleanup: @@ -880,7 +864,7 @@ AcpiEvDeleteGpeBlock ( AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); } - AcpiCurrentGpeCount -= GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH; + AcpiCurrentGpeCount -= GpeBlock->GpeCount; /* Free the GpeBlock */ @@ -925,8 +909,8 @@ AcpiEvCreateGpeInfoBlocks ( /* Allocate the GPE register information block */ GpeRegisterInfo = ACPI_ALLOCATE_ZEROED ( - (ACPI_SIZE) GpeBlock->RegisterCount * - sizeof (ACPI_GPE_REGISTER_INFO)); + (ACPI_SIZE) GpeBlock->RegisterCount * + sizeof (ACPI_GPE_REGISTER_INFO)); if (!GpeRegisterInfo) { ACPI_ERROR ((AE_INFO, @@ -938,10 +922,8 @@ AcpiEvCreateGpeInfoBlocks ( * Allocate the GPE EventInfo block. There are eight distinct GPEs * per register. Initialization to zeros is sufficient. */ - GpeEventInfo = ACPI_ALLOCATE_ZEROED ( - ((ACPI_SIZE) GpeBlock->RegisterCount * - ACPI_GPE_REGISTER_WIDTH) * - sizeof (ACPI_GPE_EVENT_INFO)); + GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount * + sizeof (ACPI_GPE_EVENT_INFO)); if (!GpeEventInfo) { ACPI_ERROR ((AE_INFO, @@ -1080,6 +1062,7 @@ AcpiEvCreateGpeBlock ( /* Initialize the new GPE block */ GpeBlock->Node = GpeDevice; + GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH); GpeBlock->RegisterCount = RegisterCount; GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; @@ -1110,7 +1093,7 @@ AcpiEvCreateGpeBlock ( Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, - AcpiEvSaveMethodInfo, NULL, GpeBlock, NULL); + AcpiEvMatchGpeMethod, NULL, GpeBlock, NULL); /* Return the new block */ @@ -1122,15 +1105,13 @@ AcpiEvCreateGpeBlock ( ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", (UINT32) GpeBlock->BlockBaseNumber, - (UINT32) (GpeBlock->BlockBaseNumber + - ((GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH) -1)), - GpeDevice->Name.Ascii, - GpeBlock->RegisterCount, + (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)), + GpeDevice->Name.Ascii, GpeBlock->RegisterCount, InterruptNumber)); /* Update global count of currently available GPEs */ - AcpiCurrentGpeCount += RegisterCount * ACPI_GPE_REGISTER_WIDTH; + AcpiCurrentGpeCount += GpeBlock->GpeCount; return_ACPI_STATUS (AE_OK); } @@ -1161,6 +1142,8 @@ AcpiEvInitializeGpeBlock ( ACPI_GPE_WALK_INFO GpeInfo; UINT32 WakeGpeCount; UINT32 GpeEnabledCount; + UINT32 GpeIndex; + UINT32 GpeNumber; UINT32 i; UINT32 j; @@ -1193,39 +1176,65 @@ AcpiEvInitializeGpeBlock ( Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, AcpiEvMatchPrwAndGpe, NULL, &GpeInfo, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While executing _PRW methods")); + } } /* - * Enable all GPEs in this block that have these attributes: - * 1) are "runtime" or "run/wake" GPEs, and - * 2) have a corresponding _Lxx or _Exx method - * - * Any other GPEs within this block must be enabled via the - * AcpiEnableGpe() external interface. + * Enable all GPEs that have a corresponding method and are not + * capable of generating wakeups. Any other GPEs within this block + * must be enabled via the AcpiEnableGpe interface. */ WakeGpeCount = 0; GpeEnabledCount = 0; + if (GpeDevice == AcpiGbl_FadtGpeDevice) + { + GpeDevice = NULL; + } + for (i = 0; i < GpeBlock->RegisterCount; i++) { - for (j = 0; j < 8; j++) + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { /* Get the info block for this particular GPE */ - GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * - ACPI_GPE_REGISTER_WIDTH) + j]; + GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; + GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; + + /* Ignore GPEs that can wake the system */ - if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_METHOD) && - (GpeEventInfo->Flags & ACPI_GPE_TYPE_RUNTIME)) + if (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) { - GpeEnabledCount++; + WakeGpeCount++; + if (AcpiGbl_LeaveWakeGpesDisabled) + { + continue; + } } - if (GpeEventInfo->Flags & ACPI_GPE_TYPE_WAKE) + /* Ignore GPEs that have no corresponding _Lxx/_Exx method */ + + if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_METHOD)) { - WakeGpeCount++; + continue; + } + + /* Enable this GPE */ + + GpeNumber = GpeIndex + GpeBlock->BlockBaseNumber; + Status = AcpiEnableGpe (GpeDevice, GpeNumber, + ACPI_GPE_TYPE_RUNTIME); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not enable GPE 0x%02X", GpeNumber)); + continue; } + + GpeEnabledCount++; } } @@ -1233,16 +1242,7 @@ AcpiEvInitializeGpeBlock ( "Found %u Wake, Enabled %u Runtime GPEs in this block\n", WakeGpeCount, GpeEnabledCount)); - /* Enable all valid runtime GPEs found above */ - - Status = AcpiHwEnableRuntimeGpeBlock (NULL, GpeBlock, NULL); - if (ACPI_FAILURE (Status)) - { - ACPI_ERROR ((AE_INFO, "Could not enable GPEs in GpeBlock %p", - GpeBlock)); - } - - return_ACPI_STATUS (Status); + return_ACPI_STATUS (AE_OK); } diff --git a/events/evxface.c b/events/evxface.c index 051e5bf..567eba4 100644 --- a/events/evxface.c +++ b/events/evxface.c @@ -705,7 +705,7 @@ AcpiInstallGpeHandler ( /* Parameter validation */ - if ((!Address) || (Type > ACPI_GPE_XRUPT_TYPE_MASK)) + if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } diff --git a/events/evxfevnt.c b/events/evxfevnt.c index 8860961..9f29063 100644 --- a/events/evxfevnt.c +++ b/events/evxfevnt.c @@ -307,30 +307,43 @@ ACPI_EXPORT_SYMBOL (AcpiEnableEvent) /******************************************************************************* * - * FUNCTION: AcpiSetGpeType + * FUNCTION: AcpiEnableGpe * - * PARAMETERS: GpeDevice - Parent GPE Device + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 * GpeNumber - GPE level within the GPE block - * Type - New GPE type + * GpeType - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE + * or both * * RETURN: Status * - * DESCRIPTION: Set the type of an individual GPE + * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is + * hardware-enabled (for runtime GPEs), or the GPE register mask + * is updated (for wake GPEs). * ******************************************************************************/ ACPI_STATUS -AcpiSetGpeType ( +AcpiEnableGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT8 Type) + UINT8 GpeType) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiEnableGpe); + + /* Parameter validation */ - ACPI_FUNCTION_TRACE (AcpiSetGpeType); + if (!GpeType || (GpeType & ~ACPI_GPE_TYPE_WAKE_RUN)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Ensure that we have a valid GPE number */ @@ -341,61 +354,101 @@ AcpiSetGpeType ( goto UnlockAndExit; } - if ((GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) == Type) + if (GpeType & ACPI_GPE_TYPE_RUNTIME) { - return_ACPI_STATUS (AE_OK); + if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) + { + Status = AE_LIMIT; /* Too many references */ + goto UnlockAndExit; + } + + GpeEventInfo->RuntimeCount++; + if (GpeEventInfo->RuntimeCount == 1) + { + Status = AcpiEvEnableGpe (GpeEventInfo); + if (ACPI_FAILURE (Status)) + { + GpeEventInfo->RuntimeCount--; + goto UnlockAndExit; + } + } } - /* Set the new type (will disable GPE if currently enabled) */ + if (GpeType & ACPI_GPE_TYPE_WAKE) + { + /* The GPE must have the ability to wake the system */ - Status = AcpiEvSetGpeType (GpeEventInfo, Type); + if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) + { + Status = AE_TYPE; + goto UnlockAndExit; + } + + if (GpeEventInfo->WakeupCount == ACPI_UINT8_MAX) + { + Status = AE_LIMIT; /* Too many references */ + goto UnlockAndExit; + } + + /* + * Update the enable mask on the first wakeup reference. Wake GPEs + * are only hardware-enabled just before sleeping. + */ + GpeEventInfo->WakeupCount++; + if (GpeEventInfo->WakeupCount == 1) + { + (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); + } + } UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); } -ACPI_EXPORT_SYMBOL (AcpiSetGpeType) +ACPI_EXPORT_SYMBOL (AcpiEnableGpe) /******************************************************************************* * - * FUNCTION: AcpiEnableGpe + * FUNCTION: AcpiDisableGpe * - * PARAMETERS: GpeDevice - Parent GPE Device + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 * GpeNumber - GPE level within the GPE block - * Flags - Just enable, or also wake enable? - * Called from ISR or not + * GpeType - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE + * or both * * RETURN: Status * - * DESCRIPTION: Enable an ACPI event (general purpose) + * DESCRIPTION: Remove a reference to a GPE. When the last reference is + * removed, only then is the GPE disabled (for runtime GPEs), or + * the GPE mask bit disabled (for wake GPEs) * ******************************************************************************/ ACPI_STATUS -AcpiEnableGpe ( +AcpiDisableGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT32 Flags) + UINT8 GpeType) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_CPU_FLAGS Flags; - ACPI_FUNCTION_TRACE (AcpiEnableGpe); + ACPI_FUNCTION_TRACE (AcpiDisableGpe); - /* Use semaphore lock if not executing at interrupt level */ + /* Parameter validation */ - if (Flags & ACPI_NOT_ISR) + if (!GpeType || (GpeType & ~ACPI_GPE_TYPE_WAKE_RUN)) { - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } + return_ACPI_STATUS (AE_BAD_PARAMETER); } + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); @@ -405,59 +458,92 @@ AcpiEnableGpe ( goto UnlockAndExit; } - /* Perform the enable */ + /* Hardware-disable a runtime GPE on removal of the last reference */ + + if (GpeType & ACPI_GPE_TYPE_RUNTIME) + { + if (!GpeEventInfo->RuntimeCount) + { + Status = AE_LIMIT; /* There are no references to remove */ + goto UnlockAndExit; + } - Status = AcpiEvEnableGpe (GpeEventInfo, TRUE); + GpeEventInfo->RuntimeCount--; + if (!GpeEventInfo->RuntimeCount) + { + Status = AcpiEvDisableGpe (GpeEventInfo); + if (ACPI_FAILURE (Status)) + { + GpeEventInfo->RuntimeCount++; + goto UnlockAndExit; + } + } + } -UnlockAndExit: - if (Flags & ACPI_NOT_ISR) + /* + * Update masks for wake GPE on removal of the last reference. + * No need to hardware-disable wake GPEs here, they are not currently + * enabled. + */ + if (GpeType & ACPI_GPE_TYPE_WAKE) { - (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + if (!GpeEventInfo->WakeupCount) + { + Status = AE_LIMIT; /* There are no references to remove */ + goto UnlockAndExit; + } + + GpeEventInfo->WakeupCount--; + if (!GpeEventInfo->WakeupCount) + { + (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); + } } + + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); } -ACPI_EXPORT_SYMBOL (AcpiEnableGpe) +ACPI_EXPORT_SYMBOL (AcpiDisableGpe) /******************************************************************************* * - * FUNCTION: AcpiDisableGpe + * FUNCTION: AcpiSetGpe * - * PARAMETERS: GpeDevice - Parent GPE Device + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 * GpeNumber - GPE level within the GPE block - * Flags - Just disable, or also wake disable? - * Called from ISR or not + * Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE * * RETURN: Status * - * DESCRIPTION: Disable an ACPI event (general purpose) + * DESCRIPTION: Enable or disable an individual GPE. This function bypasses + * the reference count mechanism used in the AcpiEnableGpe and + * AcpiDisableGpe interfaces -- and should be used with care. + * + * Note: Typically used to disable a runtime GPE for short period of time, + * then re-enable it, without disturbing the existing reference counts. This + * is useful, for example, in the Embedded Controller (EC) driver. * ******************************************************************************/ ACPI_STATUS -AcpiDisableGpe ( +AcpiSetGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT32 Flags) + UINT8 Action) { - ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; - ACPI_FUNCTION_TRACE (AcpiDisableGpe); - + ACPI_FUNCTION_TRACE (AcpiSetGpe); - /* Use semaphore lock if not executing at interrupt level */ - if (Flags & ACPI_NOT_ISR) - { - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - } + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Ensure that we have a valid GPE number */ @@ -468,17 +554,29 @@ AcpiDisableGpe ( goto UnlockAndExit; } - Status = AcpiEvDisableGpe (GpeEventInfo); + /* Perform the action */ -UnlockAndExit: - if (Flags & ACPI_NOT_ISR) + switch (Action) { - (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + case ACPI_GPE_ENABLE: + Status = AcpiEvEnableGpe (GpeEventInfo); + break; + + case ACPI_GPE_DISABLE: + Status = AcpiEvDisableGpe (GpeEventInfo); + break; + + default: + Status = AE_BAD_PARAMETER; + break; } + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); } -ACPI_EXPORT_SYMBOL (AcpiDisableGpe) +ACPI_EXPORT_SYMBOL (AcpiSetGpe) /******************************************************************************* @@ -592,9 +690,8 @@ ACPI_EXPORT_SYMBOL (AcpiClearEvent) * * FUNCTION: AcpiClearGpe * - * PARAMETERS: GpeDevice - Parent GPE Device + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 * GpeNumber - GPE level within the GPE block - * Flags - Called from an ISR or not * * RETURN: Status * @@ -605,26 +702,17 @@ ACPI_EXPORT_SYMBOL (AcpiClearEvent) ACPI_STATUS AcpiClearGpe ( ACPI_HANDLE GpeDevice, - UINT32 GpeNumber, - UINT32 Flags) + UINT32 GpeNumber) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (AcpiClearGpe); - /* Use semaphore lock if not executing at interrupt level */ - - if (Flags & ACPI_NOT_ISR) - { - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - } + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Ensure that we have a valid GPE number */ @@ -638,10 +726,7 @@ AcpiClearGpe ( Status = AcpiHwClearGpe (GpeEventInfo); UnlockAndExit: - if (Flags & ACPI_NOT_ISR) - { - (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); - } + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); } @@ -700,9 +785,8 @@ ACPI_EXPORT_SYMBOL (AcpiGetEventStatus) * * FUNCTION: AcpiGetGpeStatus * - * PARAMETERS: GpeDevice - Parent GPE Device + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 * GpeNumber - GPE level within the GPE block - * Flags - Called from an ISR or not * EventStatus - Where the current status of the event will * be returned * @@ -716,26 +800,17 @@ ACPI_STATUS AcpiGetGpeStatus ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT32 Flags, ACPI_EVENT_STATUS *EventStatus) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); - /* Use semaphore lock if not executing at interrupt level */ - - if (Flags & ACPI_NOT_ISR) - { - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - } + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Ensure that we have a valid GPE number */ @@ -751,10 +826,7 @@ AcpiGetGpeStatus ( Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); UnlockAndExit: - if (Flags & ACPI_NOT_ISR) - { - (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); - } + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); } @@ -823,21 +895,15 @@ AcpiInstallGpeBlock ( goto UnlockAndExit; } - /* Run the _PRW methods and enable the GPEs */ - - Status = AcpiEvInitializeGpeBlock (Node, GpeBlock); - if (ACPI_FAILURE (Status)) - { - goto UnlockAndExit; - } - - /* Get the DeviceObject attached to the node */ + /* Install block in the DeviceObject attached to the node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { - /* No object, create a new one */ - + /* + * No object, create a new one (Device nodes do not always have + * an attached object) + */ ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); if (!ObjDesc) { @@ -850,17 +916,20 @@ AcpiInstallGpeBlock ( /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); - if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } - /* Install the GPE block in the DeviceObject */ + /* Now install the GPE block in the DeviceObject */ ObjDesc->Device.GpeBlock = GpeBlock; + /* Run the _PRW methods and enable the runtime GPEs in the new block */ + + Status = AcpiEvInitializeGpeBlock (Node, GpeBlock); + UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); @@ -1018,8 +1087,7 @@ AcpiEvGetGpeDevice ( /* Increment Index by the number of GPEs in this block */ - Info->NextBlockBaseIndex += - (GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH); + Info->NextBlockBaseIndex += GpeBlock->GpeCount; if (Info->Index < Info->NextBlockBaseIndex) { diff --git a/executer/exdebug.c b/executer/exdebug.c index bef4f24..7347c71 100644 --- a/executer/exdebug.c +++ b/executer/exdebug.c @@ -235,7 +235,7 @@ AcpiExDoDebugObject ( AcpiOsPrintf ("[0x%.2X]\n", (UINT32) SourceDesc->Buffer.Length); AcpiUtDumpBuffer2 (SourceDesc->Buffer.Pointer, - (SourceDesc->Buffer.Length < 256) ? + (SourceDesc->Buffer.Length < 256) ? SourceDesc->Buffer.Length : 256, DB_BYTE_DISPLAY); break; diff --git a/executer/exmutex.c b/executer/exmutex.c index 172db63..e9646ca 100644 --- a/executer/exmutex.c +++ b/executer/exmutex.c @@ -168,10 +168,10 @@ AcpiExUnlinkMutex ( (ObjDesc->Mutex.Prev)->Mutex.Next = ObjDesc->Mutex.Next; /* - * Migrate the previous sync level associated with this mutex to the - * previous mutex on the list so that it may be preserved. This handles - * the case where several mutexes have been acquired at the same level, - * but are not released in opposite order. + * Migrate the previous sync level associated with this mutex to + * the previous mutex on the list so that it may be preserved. + * This handles the case where several mutexes have been acquired + * at the same level, but are not released in opposite order. */ (ObjDesc->Mutex.Prev)->Mutex.OriginalSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; @@ -187,8 +187,8 @@ AcpiExUnlinkMutex ( * * FUNCTION: AcpiExLinkMutex * - * PARAMETERS: ObjDesc - The mutex to be linked - * Thread - Current executing thread object + * PARAMETERS: ObjDesc - The mutex to be linked + * Thread - Current executing thread object * * RETURN: None * @@ -228,9 +228,9 @@ AcpiExLinkMutex ( * * FUNCTION: AcpiExAcquireMutexObject * - * PARAMETERS: TimeDesc - Timeout in milliseconds + * PARAMETERS: Timeout - Timeout in milliseconds * ObjDesc - Mutex object - * Thread - Current thread state + * ThreadId - Current thread state * * RETURN: Status * @@ -337,11 +337,12 @@ AcpiExAcquireMutex ( return_ACPI_STATUS (AE_BAD_PARAMETER); } - /* Must have a valid thread ID */ + /* Must have a valid thread state struct */ if (!WalkState->Thread) { - ACPI_ERROR ((AE_INFO, "Cannot acquire Mutex [%4.4s], null thread info", + ACPI_ERROR ((AE_INFO, + "Cannot acquire Mutex [%4.4s], null thread info", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -488,7 +489,8 @@ AcpiExReleaseMutex ( if (!OwnerThread) { - ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], not acquired", + ACPI_ERROR ((AE_INFO, + "Cannot release Mutex [%4.4s], not acquired", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED); } @@ -497,7 +499,8 @@ AcpiExReleaseMutex ( if (!WalkState->Thread) { - ACPI_ERROR ((AE_INFO, "Cannot release Mutex [%4.4s], null thread info", + ACPI_ERROR ((AE_INFO, + "Cannot release Mutex [%4.4s], null thread info", AcpiUtGetNodeName (ObjDesc->Mutex.Node))); return_ACPI_STATUS (AE_AML_INTERNAL); } @@ -553,6 +556,7 @@ AcpiExReleaseMutex ( OwnerThread->CurrentSyncLevel = PreviousSyncLevel; } + return_ACPI_STATUS (Status); } @@ -561,7 +565,7 @@ AcpiExReleaseMutex ( * * FUNCTION: AcpiExReleaseAllMutexes * - * PARAMETERS: Thread - Current executing thread object + * PARAMETERS: Thread - Current executing thread object * * RETURN: Status * @@ -620,5 +624,3 @@ AcpiExReleaseAllMutexes ( Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; } } - - diff --git a/executer/exoparg2.c b/executer/exoparg2.c index d71c910..6df45ea 100644 --- a/executer/exoparg2.c +++ b/executer/exoparg2.c @@ -206,33 +206,6 @@ AcpiExOpcode_2A_0T_0R ( break; } -#ifdef ACPI_GPE_NOTIFY_CHECK - /* - * GPE method wake/notify check. Here, we want to ensure that we - * don't receive any "DeviceWake" Notifies from a GPE _Lxx or _Exx - * GPE method during system runtime. If we do, the GPE is marked - * as "wake-only" and disabled. - * - * 1) Is the Notify() value == DeviceWake? - * 2) Is this a GPE deferred method? (An _Lxx or _Exx method) - * 3) Did the original GPE happen at system runtime? - * (versus during wake) - * - * If all three cases are true, this is a wake-only GPE that should - * be disabled at runtime. - */ - if (Value == 2) /* DeviceWake */ - { - Status = AcpiEvCheckForWakeOnlyGpe (WalkState->GpeEventInfo); - if (ACPI_FAILURE (Status)) - { - /* AE_WAKE_ONLY_GPE only error, means ignore this notify */ - - return_ACPI_STATUS (AE_OK) - } - } -#endif - /* * Dispatch the notify to the appropriate handler * NOTE: the request is queued for execution after this method diff --git a/executer/exregion.c b/executer/exregion.c index efe83eb..2ac8a0e 100644 --- a/executer/exregion.c +++ b/executer/exregion.c @@ -608,8 +608,10 @@ AcpiExDataTableSpaceHandler ( ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler); - /* Perform the memory read or write */ - + /* + * Perform the memory read or write. The BitWidth was already + * validated. + */ switch (Function) { case ACPI_READ: @@ -619,9 +621,14 @@ AcpiExDataTableSpaceHandler ( break; case ACPI_WRITE: + + ACPI_MEMCPY (ACPI_PHYSADDR_TO_PTR (Address), ACPI_CAST_PTR (char, Value), + ACPI_DIV_8 (BitWidth)); + break; + default: - return_ACPI_STATUS (AE_SUPPORT); + return_ACPI_STATUS (AE_BAD_PARAMETER); } return_ACPI_STATUS (AE_OK); diff --git a/include/acevents.h b/include/acevents.h index 567ac1e..4d945ef 100644 --- a/include/acevents.h +++ b/include/acevents.h @@ -171,13 +171,11 @@ AcpiEvQueueNotifyRequest ( */ ACPI_STATUS AcpiEvUpdateGpeEnableMasks ( - ACPI_GPE_EVENT_INFO *GpeEventInfo, - UINT8 Type); + ACPI_GPE_EVENT_INFO *GpeEventInfo); ACPI_STATUS AcpiEvEnableGpe ( - ACPI_GPE_EVENT_INFO *GpeEventInfo, - BOOLEAN WriteToHardware); + ACPI_GPE_EVENT_INFO *GpeEventInfo); ACPI_STATUS AcpiEvDisableGpe ( @@ -188,6 +186,11 @@ AcpiEvGetGpeEventInfo ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber); +ACPI_GPE_EVENT_INFO * +AcpiEvLowGetGpeInfo ( + UINT32 GpeNumber, + ACPI_GPE_BLOCK_INFO *GpeBlock); + /* * evgpeblk @@ -235,15 +238,6 @@ AcpiEvGpeDetect ( ACPI_GPE_XRUPT_INFO *GpeXruptList); ACPI_STATUS -AcpiEvSetGpeType ( - ACPI_GPE_EVENT_INFO *GpeEventInfo, - UINT8 Type); - -ACPI_STATUS -AcpiEvCheckForWakeOnlyGpe ( - ACPI_GPE_EVENT_INFO *GpeEventInfo); - -ACPI_STATUS AcpiEvGpeInitialize ( void); diff --git a/include/acexcep.h b/include/acexcep.h index 89fe5c6..a46de7d 100644 --- a/include/acexcep.h +++ b/include/acexcep.h @@ -162,7 +162,7 @@ #define AE_NO_GLOBAL_LOCK (ACPI_STATUS) (0x0017 | AE_CODE_ENVIRONMENTAL) #define AE_ABORT_METHOD (ACPI_STATUS) (0x0018 | AE_CODE_ENVIRONMENTAL) #define AE_SAME_HANDLER (ACPI_STATUS) (0x0019 | AE_CODE_ENVIRONMENTAL) -#define AE_WAKE_ONLY_GPE (ACPI_STATUS) (0x001A | AE_CODE_ENVIRONMENTAL) +#define AE_NO_HANDLER (ACPI_STATUS) (0x001A | AE_CODE_ENVIRONMENTAL) #define AE_OWNER_ID_LIMIT (ACPI_STATUS) (0x001B | AE_CODE_ENVIRONMENTAL) #define AE_CODE_ENV_MAX 0x001B diff --git a/include/acglobal.h b/include/acglobal.h index 0df0c27..4f0769e 100644 --- a/include/acglobal.h +++ b/include/acglobal.h @@ -191,6 +191,14 @@ UINT8 ACPI_INIT_GLOBAL (AcpiGbl_UseDefaultRegisterWidths, TRUE); */ UINT8 ACPI_INIT_GLOBAL (AcpiGbl_EnableAmlDebugObject, FALSE); +/* + * Optionally copy the entire DSDT to local memory (instead of simply + * mapping it.) There are some BIOSs that corrupt or replace the original + * DSDT, creating the need for this option. Default is FALSE, do not copy + * the DSDT. + */ +UINT8 ACPI_INIT_GLOBAL (AcpiGbl_CopyDsdtLocally, FALSE); + /* AcpiGbl_FADT is a local copy of the FADT, converted to a common format. */ @@ -223,6 +231,11 @@ ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1aEnable; ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1bStatus; ACPI_EXTERN ACPI_GENERIC_ADDRESS AcpiGbl_XPm1bEnable; +/* DSDT information. Used to check for DSDT corruption */ + +ACPI_EXTERN ACPI_TABLE_HEADER *AcpiGbl_DSDT; +ACPI_EXTERN ACPI_TABLE_HEADER AcpiGbl_OriginalDsdtHeader; + /* * Handle both ACPI 1.0 and ACPI 2.0 Integer widths. The integer width is * determined by the revision of the DSDT: If the DSDT revision is less than diff --git a/include/aclocal.h b/include/aclocal.h index 0aeacff..8818a6e 100644 --- a/include/aclocal.h +++ b/include/aclocal.h @@ -561,6 +561,8 @@ typedef struct acpi_gpe_event_info struct acpi_gpe_register_info *RegisterInfo; /* Backpointer to register info */ UINT8 Flags; /* Misc info about this GPE */ UINT8 GpeNumber; /* This GPE */ + UINT8 RuntimeCount; /* References to a run GPE */ + UINT8 WakeupCount; /* References to a wake GPE */ } ACPI_GPE_EVENT_INFO; @@ -590,6 +592,7 @@ typedef struct acpi_gpe_block_info ACPI_GPE_EVENT_INFO *EventInfo; /* One for each GPE */ ACPI_GENERIC_ADDRESS BlockAddress; /* Base address of the block */ UINT32 RegisterCount; /* Number of register pairs in block */ + UINT16 GpeCount; /* Number of individual GPEs in block */ UINT8 BlockBaseNumber;/* Base GPE number for this block */ } ACPI_GPE_BLOCK_INFO; diff --git a/include/acpixf.h b/include/acpixf.h index 220350a..300b2c7 100644 --- a/include/acpixf.h +++ b/include/acpixf.h @@ -120,7 +120,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20100304 +#define ACPI_CA_VERSION 0x20100331 #include "actypes.h" #include "actbl.h" @@ -146,6 +146,7 @@ extern UINT8 AcpiGbl_UseDefaultRegisterWidths; extern ACPI_NAME AcpiGbl_TraceMethodName; extern UINT32 AcpiGbl_TraceFlags; extern UINT8 AcpiGbl_EnableAmlDebugObject; +extern UINT8 AcpiGbl_CopyDsdtLocally; /* @@ -463,34 +464,32 @@ AcpiGetEventStatus ( * GPE Interfaces */ ACPI_STATUS -AcpiSetGpeType ( +AcpiSetGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT8 Type); + UINT8 Action); ACPI_STATUS AcpiEnableGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT32 Flags); + UINT8 GpeType); ACPI_STATUS AcpiDisableGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT32 Flags); + UINT8 GpeType); ACPI_STATUS AcpiClearGpe ( ACPI_HANDLE GpeDevice, - UINT32 GpeNumber, - UINT32 Flags); + UINT32 GpeNumber); ACPI_STATUS AcpiGetGpeStatus ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, - UINT32 Flags, ACPI_EVENT_STATUS *EventStatus); ACPI_STATUS diff --git a/include/actables.h b/include/actables.h index 54fdaae..9f1c4f0 100644 --- a/include/actables.h +++ b/include/actables.h @@ -231,6 +231,14 @@ AcpiTbVerifyChecksum ( UINT32 Length); void +AcpiTbCheckDsdtHeader ( + void); + +ACPI_TABLE_HEADER * +AcpiTbCopyDsdt ( + UINT32 TableIndex); + +void AcpiTbInstallTable ( ACPI_PHYSICAL_ADDRESS Address, char *Signature, diff --git a/include/actypes.h b/include/actypes.h index 8d0d06a..3c0626a 100644 --- a/include/actypes.h +++ b/include/actypes.h @@ -742,53 +742,42 @@ typedef UINT32 ACPI_EVENT_STATUS; #define ACPI_GPE_MAX 0xFF #define ACPI_NUM_GPE 256 +/* Actions for AcpiSetGpe */ + #define ACPI_GPE_ENABLE 0 #define ACPI_GPE_DISABLE 1 +/* GpeTypes for AcpiEnableGpe and AcpiDisableGpe */ + +#define ACPI_GPE_TYPE_WAKE (UINT8) 0x01 +#define ACPI_GPE_TYPE_RUNTIME (UINT8) 0x02 +#define ACPI_GPE_TYPE_WAKE_RUN (UINT8) 0x03 /* * GPE info flags - Per GPE - * +-+-+-+---+---+-+ - * |7|6|5|4:3|2:1|0| - * +-+-+-+---+---+-+ - * | | | | | | - * | | | | | +--- Interrupt type: Edge or Level Triggered - * | | | | +--- Type: Wake-only, Runtime-only, or wake/runtime - * | | | +--- Type of dispatch -- to method, handler, or none - * | | +--- Enabled for runtime? - * | +--- Enabled for wake? - * +--- Unused + * +-------+---+-+-+ + * | 7:4 |3:2|1|0| + * +-------+---+-+-+ + * | | | | + * | | | +--- Interrupt type: edge or level triggered + * | | +----- GPE can wake the system + * | +-------- Type of dispatch:to method, handler, or none + * +-------------- */ #define ACPI_GPE_XRUPT_TYPE_MASK (UINT8) 0x01 #define ACPI_GPE_LEVEL_TRIGGERED (UINT8) 0x01 #define ACPI_GPE_EDGE_TRIGGERED (UINT8) 0x00 -#define ACPI_GPE_TYPE_MASK (UINT8) 0x06 -#define ACPI_GPE_TYPE_WAKE_RUN (UINT8) 0x06 -#define ACPI_GPE_TYPE_WAKE (UINT8) 0x02 -#define ACPI_GPE_TYPE_RUNTIME (UINT8) 0x04 /* Default */ - -#define ACPI_GPE_DISPATCH_MASK (UINT8) 0x18 -#define ACPI_GPE_DISPATCH_HANDLER (UINT8) 0x08 -#define ACPI_GPE_DISPATCH_METHOD (UINT8) 0x10 -#define ACPI_GPE_DISPATCH_NOT_USED (UINT8) 0x00 /* Default */ +#define ACPI_GPE_CAN_WAKE (UINT8) 0x02 -#define ACPI_GPE_RUN_ENABLE_MASK (UINT8) 0x20 -#define ACPI_GPE_RUN_ENABLED (UINT8) 0x20 -#define ACPI_GPE_RUN_DISABLED (UINT8) 0x00 /* Default */ - -#define ACPI_GPE_WAKE_ENABLE_MASK (UINT8) 0x40 -#define ACPI_GPE_WAKE_ENABLED (UINT8) 0x40 -#define ACPI_GPE_WAKE_DISABLED (UINT8) 0x00 /* Default */ - -#define ACPI_GPE_ENABLE_MASK (UINT8) 0x60 /* Both run/wake */ +#define ACPI_GPE_DISPATCH_MASK (UINT8) 0x0C +#define ACPI_GPE_DISPATCH_HANDLER (UINT8) 0x04 +#define ACPI_GPE_DISPATCH_METHOD (UINT8) 0x08 +#define ACPI_GPE_DISPATCH_NOT_USED (UINT8) 0x00 /* * Flags for GPE and Lock interfaces */ -#define ACPI_EVENT_WAKE_ENABLE 0x2 /* AcpiGpeEnable */ -#define ACPI_EVENT_WAKE_DISABLE 0x2 /* AcpiGpeDisable */ - #define ACPI_NOT_ISR 0x1 #define ACPI_ISR 0x0 diff --git a/include/platform/acfreebsd.h b/include/platform/acfreebsd.h index 09ad54a..6e0e3b5 100644 --- a/include/platform/acfreebsd.h +++ b/include/platform/acfreebsd.h @@ -114,7 +114,7 @@ *****************************************************************************/ #ifndef __ACFREEBSD_H__ -#define __ACFREEBSD_H__ +#define __ACFREEBSD_H__ /* FreeBSD uses GCC */ @@ -123,12 +123,10 @@ #include #include -#define ACPI_UINTPTR_T uintptr_t - -#define ACPI_USE_LOCAL_CACHE -#define ACPI_USE_SYSTEM_CLIBRARY - -#define __cdecl +#define ACPI_UINTPTR_T uintptr_t +#define ACPI_USE_LOCAL_CACHE +#define ACPI_USE_SYSTEM_CLIBRARY +#define __cdecl #ifdef _KERNEL @@ -140,17 +138,17 @@ #include "opt_acpi.h" -#define ACPI_THREAD_ID lwpid_t +#define ACPI_THREAD_ID lwpid_t #ifdef ACPI_DEBUG -#define ACPI_DEBUG_OUTPUT /* for backward compatibility */ -#define ACPI_DISASSEMBLER +#define ACPI_DEBUG_OUTPUT /* for backward compatibility */ +#define ACPI_DISASSEMBLER #endif #ifdef ACPI_DEBUG_OUTPUT #include "opt_ddb.h" #ifdef DDB -#define ACPI_DEBUGGER +#define ACPI_DEBUGGER #endif /* DDB */ #endif /* ACPI_DEBUG_OUTPUT */ @@ -158,7 +156,7 @@ #undef DEBUGGER_THREADING #endif /* DEBUGGER_THREADING */ -#define DEBUGGER_THREADING 0 /* integrated with DDB */ +#define DEBUGGER_THREADING 0 /* integrated with DDB */ #else /* _KERNEL */ @@ -166,14 +164,13 @@ #include #endif -#define ACPI_THREAD_ID pthread_t +#define ACPI_THREAD_ID pthread_t /* Not building kernel code, so use libc */ -#define ACPI_USE_STANDARD_HEADERS -#define ACPI_FLUSH_CPU_CACHE() - -#define __cli() -#define __sti() +#define ACPI_USE_STANDARD_HEADERS +#define ACPI_FLUSH_CPU_CACHE() +#define __cli() +#define __sti() #endif /* _KERNEL */ diff --git a/os_specific/service_layers/oswintbl.c b/os_specific/service_layers/oswintbl.c index 30d7ba6..db609ee 100644 --- a/os_specific/service_layers/oswintbl.c +++ b/os_specific/service_layers/oswintbl.c @@ -132,6 +132,22 @@ static char KeyBuffer[64]; +static char ErrorBuffer[64]; + + +/* Little front-end to win FormatMessage */ + +char * +OsFormatException ( + LONG Status) +{ + + ErrorBuffer[0] = 0; + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, Status, 0, + ErrorBuffer, 64, NULL); + + return (ErrorBuffer); +} /****************************************************************************** @@ -169,7 +185,7 @@ OsGetTable ( ACPI_STRCAT (KeyBuffer, Signature); Status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, KeyBuffer, - 0L, KEY_ALL_ACCESS, &Handle); + 0L, KEY_READ, &Handle); if (Status != ERROR_SUCCESS) { @@ -187,8 +203,9 @@ OsGetTable ( } else { - AcpiOsPrintf ("Could not find %s in registry at %s\n", - Signature, KeyBuffer); + AcpiOsPrintf ( + "Could not find %s in registry at %s: %s (Status=0x%X)\n", + Signature, KeyBuffer, OsFormatException (Status), Status); return (NULL); } } @@ -212,7 +229,8 @@ OsGetTable ( Status = RegOpenKey (Handle, KeyBuffer, &SubKey); if (Status != ERROR_SUCCESS) { - AcpiOsPrintf ("Could not open %s entry\n", Signature); + AcpiOsPrintf ("Could not open %s entry: %s\n", + Signature, OsFormatException (Status)); return (NULL); } @@ -230,7 +248,8 @@ OsGetTable ( NULL, &Type, NULL, 0); if (Status != ERROR_SUCCESS) { - AcpiOsPrintf ("Could not get %s registry entry\n", Signature); + AcpiOsPrintf ("Could not get %s registry entry: %s\n", + Signature, OsFormatException (Status)); return (NULL); } @@ -246,7 +265,8 @@ OsGetTable ( Status = RegQueryValueEx (Handle, KeyBuffer, NULL, NULL, NULL, &DataSize); if (Status != ERROR_SUCCESS) { - AcpiOsPrintf ("Could not read the %s table size\n", Signature); + AcpiOsPrintf ("Could not read the %s table size: %s\n", + Signature, OsFormatException (Status)); return (NULL); } @@ -264,7 +284,8 @@ OsGetTable ( (UCHAR *) ReturnTable, &DataSize); if (Status != ERROR_SUCCESS) { - AcpiOsPrintf ("Could not read %s data\n", Signature); + AcpiOsPrintf ("Could not read %s data: %s\n", + Signature, OsFormatException (Status)); AcpiOsFree (ReturnTable); return (NULL); } diff --git a/os_specific/service_layers/oswinxf.c b/os_specific/service_layers/oswinxf.c index 3e44196..0f11777 100644 --- a/os_specific/service_layers/oswinxf.c +++ b/os_specific/service_layers/oswinxf.c @@ -336,7 +336,7 @@ AcpiOsTableOverride ( *NewTable = OsGetTable (TableName); if (*NewTable) { - AcpiOsPrintf ("Table %s obtained from registry, %d bytes\n", + AcpiOsPrintf ("Table [%s] obtained from registry, %d bytes\n", TableName, (*NewTable)->Length); } else @@ -1415,7 +1415,7 @@ AcpiOsSignal ( * FUNCTION: Local cache interfaces * * DESCRIPTION: Implements cache interfaces via malloc/free for testing - * purposes only. + * purposes only. * *****************************************************************************/ @@ -1470,7 +1470,7 @@ AcpiOsAcquireObject ( NewObject = malloc (((ACPI_MEMORY_LIST *) Cache)->ObjectSize); memset (NewObject, 0, ((ACPI_MEMORY_LIST *) Cache)->ObjectSize); - + return (NewObject); } diff --git a/parser/psxface.c b/parser/psxface.c index b34d985..6cc5f41 100644 --- a/parser/psxface.c +++ b/parser/psxface.c @@ -120,6 +120,7 @@ #include "acparser.h" #include "acdispat.h" #include "acinterp.h" +#include "actables.h" #include "amlcode.h" @@ -334,6 +335,10 @@ AcpiPsExecuteMethod ( ACPI_FUNCTION_TRACE (PsExecuteMethod); + /* Quick validation of DSDT header */ + + AcpiTbCheckDsdtHeader (); + /* Validate the Info and method Node */ if (!Info || !Info->ResolvedNode) diff --git a/tables/tbutils.c b/tables/tbutils.c index a496556..eb8bc43 100644 --- a/tables/tbutils.c +++ b/tables/tbutils.c @@ -395,6 +395,88 @@ AcpiTbChecksum ( /******************************************************************************* * + * FUNCTION: AcpiTbCheckDsdtHeader + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect + * if the DSDT has been replaced from outside the OS and/or if + * the DSDT header has been corrupted. + * + ******************************************************************************/ + +void +AcpiTbCheckDsdtHeader ( + void) +{ + + /* Compare original length and checksum to current values */ + + if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length || + AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum) + { + ACPI_ERROR ((AE_INFO, + "The DSDT has been corrupted or replaced - old, new headers below")); + AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader); + AcpiTbPrintTableHeader (0, AcpiGbl_DSDT); + + /* Disable further error messages */ + + AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length; + AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbCopyDsdt + * + * PARAMETERS: TableDesc - Installed table to copy + * + * RETURN: None + * + * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory. + * Some very bad BIOSs are known to either corrupt the DSDT or + * install a new, bad DSDT. This copy works around the problem. + * + ******************************************************************************/ + +ACPI_TABLE_HEADER * +AcpiTbCopyDsdt ( + UINT32 TableIndex) +{ + ACPI_TABLE_HEADER *NewTable; + ACPI_TABLE_DESC *TableDesc; + + + TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; + + NewTable = ACPI_ALLOCATE (TableDesc->Length); + if (!NewTable) + { + ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X", + TableDesc->Length)); + return (NULL); + } + + ACPI_MEMCPY (NewTable, TableDesc->Pointer, TableDesc->Length); + AcpiTbDeleteTable (TableDesc); + TableDesc->Pointer = NewTable; + TableDesc->Flags = ACPI_TABLE_ORIGIN_ALLOCATED; + + ACPI_INFO ((AE_INFO, + "Forced DSDT copy: length 0x%05X copied locally, original unmapped", + NewTable->Length)); + + return (NewTable); +} + + +/******************************************************************************* + * * FUNCTION: AcpiTbInstallTable * * PARAMETERS: Address - Physical address of DSDT or FACS diff --git a/tables/tbxface.c b/tables/tbxface.c index 6a4f413..8cbf15a 100644 --- a/tables/tbxface.c +++ b/tables/tbxface.c @@ -265,6 +265,7 @@ AcpiReallocateRootTable ( { ACPI_TABLE_DESC *Tables; ACPI_SIZE NewSize; + ACPI_SIZE CurrentSize; ACPI_FUNCTION_TRACE (AcpiReallocateRootTable); @@ -279,9 +280,15 @@ AcpiReallocateRootTable ( return_ACPI_STATUS (AE_SUPPORT); } - NewSize = ((ACPI_SIZE) AcpiGbl_RootTableList.Count + - ACPI_ROOT_TABLE_SIZE_INCREMENT) * - sizeof (ACPI_TABLE_DESC); + /* + * Get the current size of the root table and add the default + * increment to create the new table size. + */ + CurrentSize = (ACPI_SIZE) + AcpiGbl_RootTableList.Count * sizeof (ACPI_TABLE_DESC); + + NewSize = CurrentSize + + (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof (ACPI_TABLE_DESC)); /* Create new array and copy the old array */ @@ -291,10 +298,12 @@ AcpiReallocateRootTable ( return_ACPI_STATUS (AE_NO_MEMORY); } - ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables, NewSize); + ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables, CurrentSize); + + /* Update the root table descriptor */ - AcpiGbl_RootTableList.Size = AcpiGbl_RootTableList.Count; AcpiGbl_RootTableList.Tables = Tables; + AcpiGbl_RootTableList.Size += ACPI_ROOT_TABLE_SIZE_INCREMENT; AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; @@ -534,6 +543,7 @@ AcpiTbLoadNamespace ( { ACPI_STATUS Status; UINT32 i; + ACPI_TABLE_HEADER *NewDsdt; ACPI_FUNCTION_TRACE (TbLoadNamespace); @@ -542,30 +552,47 @@ AcpiTbLoadNamespace ( (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* - * Load the namespace. The DSDT is required, but any SSDT and PSDT tables - * are optional. + * Save the DSDT pointer for simple access. This is the mapped memory + * address. We must take care here because the address of the .Tables + * array can change dynamically as tables are loaded at run-time + */ + AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; + + /* + * Load the namespace. The DSDT is required, but any SSDT and + * PSDT tables are optional. Verify the DSDT. */ if (!AcpiGbl_RootTableList.Count || - !ACPI_COMPARE_NAME ( - &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), - ACPI_SIG_DSDT) || - ACPI_FAILURE (AcpiTbVerifyTable ( + !ACPI_COMPARE_NAME (AcpiGbl_DSDT->Signature, ACPI_SIG_DSDT) || + ACPI_FAILURE (AcpiTbVerifyTable ( &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) { Status = AE_NO_ACPI_TABLES; goto UnlockAndExit; } - /* A valid DSDT is required */ - - Status = AcpiTbVerifyTable ( - &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]); - if (ACPI_FAILURE (Status)) + /* + * Optionally copy the entire DSDT to local memory (instead of simply + * mapping it.) There are some BIOSs that corrupt or replace the original + * DSDT, creating the need for this option. Default is FALSE, do not copy + * the DSDT. + */ + if (AcpiGbl_CopyDsdtLocally) { - Status = AE_NO_ACPI_TABLES; - goto UnlockAndExit; + NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT); + if (NewDsdt) + { + AcpiGbl_DSDT = NewDsdt; + } } + /* + * Save the original DSDT header for detection of table corruption + * and/or replacement of the DSDT from outside the OS. + */ + ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, + sizeof (ACPI_TABLE_HEADER)); + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); /* Load and parse tables */ diff --git a/tools/acpiexec/aeexec.c b/tools/acpiexec/aeexec.c index 06dbddb..9aec80d 100644 --- a/tools/acpiexec/aeexec.c +++ b/tools/acpiexec/aeexec.c @@ -204,7 +204,8 @@ AeSetupConfiguration ( * * RETURN: None * - * DESCRIPTION: Various GPE initialization + * DESCRIPTION: Test GPE block device initialization. Requires test ASL with + * A \GPE2 device. * *****************************************************************************/ @@ -226,23 +227,18 @@ AfInstallGpeBlock ( return; } - BlockAddress.SpaceId = 0; + ACPI_MEMSET (&BlockAddress, 0, sizeof (ACPI_GENERIC_ADDRESS)); + BlockAddress.SpaceId = ACPI_ADR_SPACE_SYSTEM_MEMORY; BlockAddress.Address = 0x76540000; -#ifdef _OBSOLETE - Status = AcpiInstallGpeBlock (Handle, &BlockAddress, 4, 8); -#endif - - /* Above should fail, ignore */ - Status = AcpiGetHandle (NULL, "\\GPE2", &Handle2); if (ACPI_SUCCESS (Status)) { - Status = AcpiInstallGpeBlock (Handle2, &BlockAddress, 8, 8); + Status = AcpiInstallGpeBlock (Handle2, &BlockAddress, 7, 8); + Status = AcpiInstallGpeBlock (Handle2, &BlockAddress, 2, 0); AcpiInstallGpeHandler (Handle2, 8, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (Handle2, 8, ACPI_GPE_TYPE_WAKE); - AcpiEnableGpe (Handle2, 8, 0); + AcpiEnableGpe (Handle2, 8, ACPI_GPE_TYPE_RUNTIME); Status = AcpiGetGpeDevice (0x30, &GpeDevice); Status = AcpiGetGpeDevice (0x42, &GpeDevice); @@ -250,8 +246,6 @@ AfInstallGpeBlock ( Status = AcpiGetGpeDevice (AcpiCurrentGpeCount, &GpeDevice); AcpiRemoveGpeHandler (Handle2, 8, AeGpeHandler); - - Status = AcpiRemoveGpeBlock (Handle2); } Status = AcpiGetHandle (NULL, "\\GPE3", &Handle3); @@ -259,12 +253,6 @@ AfInstallGpeBlock ( { Status = AcpiInstallGpeBlock (Handle3, &BlockAddress, 8, 11); } - -#ifdef _OBSOLETE - Status = AcpiRemoveGpeBlock (Handle); - Status = AcpiRemoveGpeBlock (Handle2); - Status = AcpiRemoveGpeBlock (Handle3); -#endif } @@ -540,35 +528,34 @@ AeMiscellaneousTests ( AcpiGetName (AcpiGbl_RootNode, ACPI_FULL_PATHNAME, &ReturnBuf); AcpiEnableEvent (ACPI_EVENT_GLOBAL, 0); + /* + * GPEs: Handlers, enable/disable, etc. + */ AcpiInstallGpeHandler (NULL, 0, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (NULL, 0, ACPI_GPE_TYPE_WAKE_RUN); - AcpiEnableGpe (NULL, 0, ACPI_NOT_ISR); + AcpiEnableGpe (NULL, 0, ACPI_GPE_TYPE_RUNTIME); AcpiRemoveGpeHandler (NULL, 0, AeGpeHandler); AcpiInstallGpeHandler (NULL, 0, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (NULL, 0, ACPI_GPE_TYPE_WAKE_RUN); - AcpiEnableGpe (NULL, 0, ACPI_NOT_ISR); + AcpiEnableGpe (NULL, 0, ACPI_GPE_TYPE_RUNTIME); + AcpiSetGpe (NULL, 0, ACPI_GPE_DISABLE); + AcpiSetGpe (NULL, 0, ACPI_GPE_ENABLE); AcpiInstallGpeHandler (NULL, 1, ACPI_GPE_EDGE_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (NULL, 1, ACPI_GPE_TYPE_RUNTIME); - AcpiEnableGpe (NULL, 1, ACPI_NOT_ISR); + AcpiEnableGpe (NULL, 1, ACPI_GPE_TYPE_RUNTIME); AcpiInstallGpeHandler (NULL, 2, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (NULL, 2, ACPI_GPE_TYPE_WAKE); - AcpiEnableGpe (NULL, 2, ACPI_NOT_ISR); + AcpiEnableGpe (NULL, 2, ACPI_GPE_TYPE_RUNTIME); AcpiInstallGpeHandler (NULL, 3, ACPI_GPE_EDGE_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (NULL, 3, ACPI_GPE_TYPE_WAKE_RUN); - AcpiInstallGpeHandler (NULL, 4, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (NULL, 4, ACPI_GPE_TYPE_RUNTIME); - AcpiInstallGpeHandler (NULL, 5, ACPI_GPE_EDGE_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (NULL, 5, ACPI_GPE_TYPE_WAKE); AcpiInstallGpeHandler (NULL, 0x19, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); - AcpiSetGpeType (NULL, 0x19, ACPI_GPE_TYPE_WAKE_RUN); - AcpiEnableGpe (NULL, 0x19, ACPI_NOT_ISR); + AcpiEnableGpe (NULL, 0x19, ACPI_GPE_TYPE_RUNTIME); + + AcpiInstallGpeHandler (NULL, 0x62, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); + AcpiEnableGpe (NULL, 0x62, ACPI_GPE_TYPE_RUNTIME); + AcpiDisableGpe (NULL, 0x62, ACPI_GPE_TYPE_RUNTIME); AfInstallGpeBlock (); diff --git a/utilities/utglobal.c b/utilities/utglobal.c index 236d811..986dbeb 100644 --- a/utilities/utglobal.c +++ b/utilities/utglobal.c @@ -916,6 +916,7 @@ AcpiUtInitGlobals ( /* Miscellaneous variables */ + AcpiGbl_DSDT = NULL; AcpiGbl_CmSingleStep = FALSE; AcpiGbl_DbTerminateThreads = FALSE; AcpiGbl_Shutdown = FALSE; -- cgit v1.1 From 8af503e9ce639f4eabed0c7548c52f5c39c5660f Mon Sep 17 00:00:00 2001 From: jkim Date: Fri, 2 Apr 2010 16:57:25 +0000 Subject: Integrate FreeBSD changes for acfreebsd.h. http://git.moblin.org/cgit.cgi/acpica/commit/?id=4580a813dd812d85c9a0ec1b77f7855c9940c60c Obtained from: Intel --- include/platform/acfreebsd.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/platform/acfreebsd.h b/include/platform/acfreebsd.h index 6e0e3b5..145b7bb 100644 --- a/include/platform/acfreebsd.h +++ b/include/platform/acfreebsd.h @@ -124,9 +124,10 @@ #include #define ACPI_UINTPTR_T uintptr_t + +#define ACPI_USE_DO_WHILE_0 #define ACPI_USE_LOCAL_CACHE #define ACPI_USE_SYSTEM_CLIBRARY -#define __cdecl #ifdef _KERNEL @@ -139,6 +140,7 @@ #include "opt_acpi.h" #define ACPI_THREAD_ID lwpid_t +#define ACPI_MUTEX_TYPE ACPI_OSL_MUTEX #ifdef ACPI_DEBUG #define ACPI_DEBUG_OUTPUT /* for backward compatibility */ @@ -166,11 +168,10 @@ #define ACPI_THREAD_ID pthread_t -/* Not building kernel code, so use libc */ #define ACPI_USE_STANDARD_HEADERS + #define ACPI_FLUSH_CPU_CACHE() -#define __cli() -#define __sti() +#define __cdecl #endif /* _KERNEL */ -- cgit v1.1 From 76725434be69252a9cdad96097ac136ffeda91db Mon Sep 17 00:00:00 2001 From: jkim Date: Fri, 2 Apr 2010 17:00:37 +0000 Subject: Fixes for table load regression. http://git.moblin.org/cgit.cgi/acpica/commit/?id=e4c530f4e71d70804ed911d41d922dce4cea8b23 http://git.moblin.org/cgit.cgi/acpica/commit/?id=67a1ef8c98791bd4a0fb84fe0c2feff7082151dc Obtained from: Intel --- tables/tbxface.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tables/tbxface.c b/tables/tbxface.c index 8cbf15a..ba0ec0f 100644 --- a/tables/tbxface.c +++ b/tables/tbxface.c @@ -552,18 +552,13 @@ AcpiTbLoadNamespace ( (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* - * Save the DSDT pointer for simple access. This is the mapped memory - * address. We must take care here because the address of the .Tables - * array can change dynamically as tables are loaded at run-time - */ - AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; - - /* * Load the namespace. The DSDT is required, but any SSDT and * PSDT tables are optional. Verify the DSDT. */ if (!AcpiGbl_RootTableList.Count || - !ACPI_COMPARE_NAME (AcpiGbl_DSDT->Signature, ACPI_SIG_DSDT) || + !ACPI_COMPARE_NAME ( + &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), + ACPI_SIG_DSDT) || ACPI_FAILURE (AcpiTbVerifyTable ( &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) { @@ -572,6 +567,14 @@ AcpiTbLoadNamespace ( } /* + * Save the DSDT pointer for simple access. This is the mapped memory + * address. We must take care here because the address of the .Tables + * array can change dynamically as tables are loaded at run-time. Note: + * .Pointer field is not validated until after call to AcpiTbVerifyTable. + */ + AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; + + /* * Optionally copy the entire DSDT to local memory (instead of simply * mapping it.) There are some BIOSs that corrupt or replace the original * DSDT, creating the need for this option. Default is FALSE, do not copy -- cgit v1.1 From 8e0a43b899a7f44db303850b7d860566df0eefc2 Mon Sep 17 00:00:00 2001 From: jkim Date: Fri, 2 Apr 2010 21:05:28 +0000 Subject: Additional fix for root table size regression. Set the size of the new root table correctly. Not the current size, but the number of current tables + the default increment. http://git.moblin.org/cgit.cgi/acpica/commit/?id=752d13e80656436cd58e9710225a80c9deb3b053 Obtained from: Intel --- tables/tbxface.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tables/tbxface.c b/tables/tbxface.c index ba0ec0f..b3e09a0 100644 --- a/tables/tbxface.c +++ b/tables/tbxface.c @@ -300,10 +300,14 @@ AcpiReallocateRootTable ( ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables, CurrentSize); - /* Update the root table descriptor */ - + /* + * Update the root table descriptor. The new size will be the current + * number of tables plus the increment, independent of the reserved + * size of the original table list. + */ AcpiGbl_RootTableList.Tables = Tables; - AcpiGbl_RootTableList.Size += ACPI_ROOT_TABLE_SIZE_INCREMENT; + AcpiGbl_RootTableList.Size = + AcpiGbl_RootTableList.Count + ACPI_ROOT_TABLE_SIZE_INCREMENT; AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; -- cgit v1.1 From bba9d9c06c699a401091f437b2dced6938a6accc Mon Sep 17 00:00:00 2001 From: yongari Date: Mon, 26 Apr 2010 21:08:15 +0000 Subject: It seems ale(4) controllers do not like to see TCP payload in the first descriptor in TSO case. Otherwise controller can generate bad frames during TSO. To address it, make sure to pull up ethernet + IP + TCP header with options in first buffer. Also ensure the buffer length of the first descriptor for TSO covers entire ethernet + IP + TCP with options and setup additional Tx descriptor if the first buffer includes TCP payload. Tested by: Amar Takhar darkbeer dot org > MFC after: 1 week --- sys/dev/ale/if_ale.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/sys/dev/ale/if_ale.c b/sys/dev/ale/if_ale.c index b3e7187..ea6b53b 100644 --- a/sys/dev/ale/if_ale.c +++ b/sys/dev/ale/if_ale.c @@ -1585,7 +1585,7 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head) struct tcphdr *tcp; bus_dma_segment_t txsegs[ALE_MAXTXSEGS]; bus_dmamap_t map; - uint32_t cflags, ip_off, poff, vtag; + uint32_t cflags, hdrlen, ip_off, poff, vtag; int error, i, nsegs, prod, si; ALE_LOCK_ASSERT(sc); @@ -1678,6 +1678,11 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head) return (ENOBUFS); } tcp = (struct tcphdr *)(mtod(m, char *) + poff); + m = m_pullup(m, poff + (tcp->th_off << 2)); + if (m == NULL) { + *m_head = NULL; + return (ENOBUFS); + } /* * AR81xx requires IP/TCP header size and offset as * well as TCP pseudo checksum which complicates @@ -1730,7 +1735,7 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head) } /* Check descriptor overrun. */ - if (sc->ale_cdata.ale_tx_cnt + nsegs >= ALE_TX_RING_CNT - 2) { + if (sc->ale_cdata.ale_tx_cnt + nsegs >= ALE_TX_RING_CNT - 3) { bus_dmamap_unload(sc->ale_cdata.ale_tx_tag, map); return (ENOBUFS); } @@ -1782,8 +1787,32 @@ ale_encap(struct ale_softc *sc, struct mbuf **m_head) cflags |= ALE_TD_INSERT_VLAN_TAG; } - desc = NULL; - for (i = 0; i < nsegs; i++) { + i = 0; + if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) { + /* + * Make sure the first fragment contains + * only ethernet and IP/TCP header with options. + */ + hdrlen = poff + (tcp->th_off << 2); + desc = &sc->ale_cdata.ale_tx_ring[prod]; + desc->addr = htole64(txsegs[i].ds_addr); + desc->len = htole32(ALE_TX_BYTES(hdrlen) | vtag); + desc->flags = htole32(cflags); + sc->ale_cdata.ale_tx_cnt++; + ALE_DESC_INC(prod, ALE_TX_RING_CNT); + if (m->m_len - hdrlen > 0) { + /* Handle remaining payload of the first fragment. */ + desc = &sc->ale_cdata.ale_tx_ring[prod]; + desc->addr = htole64(txsegs[i].ds_addr + hdrlen); + desc->len = htole32(ALE_TX_BYTES(m->m_len - hdrlen) | + vtag); + desc->flags = htole32(cflags); + sc->ale_cdata.ale_tx_cnt++; + ALE_DESC_INC(prod, ALE_TX_RING_CNT); + } + i = 1; + } + for (; i < nsegs; i++) { desc = &sc->ale_cdata.ale_tx_ring[prod]; desc->addr = htole64(txsegs[i].ds_addr); desc->len = htole32(ALE_TX_BYTES(txsegs[i].ds_len) | vtag); -- cgit v1.1 From 1b05a112d4cbea67db29b7df286106b4cde94e93 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 27 Apr 2010 05:04:32 +0000 Subject: Move checking the version up from Makefile generation to just after we've parsed the config file. Makefile generation is too late if we've introduce changes to the syntax of the metafiles to warn about version skew, since we have to try to parse them and we get an parse error that's rather baffling to the user rather than a 'your config is too old, upgrade' which we should get. We have to defer doing it until after we've read the user's config file because we define machinename there. The version required to compile the kernel is encoded in Makefile.machinename. There's no real reason for this to be the case, but changing it now would introduce some logistical issues that I'd rather avoid for the moment. I intend to revisit this if we're still using config in FreeBSD 10. This also means that we cannot introduce any config metafile changes that result in a syntax error or other error for the user until 9.0 is released. Otherwise, we break the upgrade path, or at least reduce the usefulness of the error messages we generate. # This implies that the config file option mapping will need to be redone. MFC after: 3 days --- usr.sbin/config/config.h | 1 + usr.sbin/config/main.c | 40 +++++++++++++++++++++++++++++++++++++++ usr.sbin/config/mkmakefile.c | 45 +++++++++++++++++++++----------------------- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/usr.sbin/config/config.h b/usr.sbin/config/config.h index ec19986..4abb567 100644 --- a/usr.sbin/config/config.h +++ b/usr.sbin/config/config.h @@ -179,6 +179,7 @@ void makehints(void); void headers(void); void cfgfile_add(const char *); void cfgfile_removeall(void); +FILE *open_makefile_template(void); extern STAILQ_HEAD(device_head, device) dtab; diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c index 2b5e055..5cffed2 100644 --- a/usr.sbin/config/main.c +++ b/usr.sbin/config/main.c @@ -90,6 +90,7 @@ static void get_srcdir(void); static void usage(void); static void cleanheaders(char *); static void kernconfdump(const char *); +static void checkversion(void); struct hdr_list { char *h_name; @@ -204,6 +205,7 @@ main(int argc, char **argv) printf("cpu type must be specified\n"); exit(1); } + checkversion(); /* * make symbolic links in compilation directory @@ -721,3 +723,41 @@ kernconfdump(const char *file) } fclose(fp); } + +static void +badversion(int versreq) +{ + fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n"); + fprintf(stderr, "config version = %d, ", CONFIGVERS); + fprintf(stderr, "version required = %d\n\n", versreq); + fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n"); + fprintf(stderr, "with your /usr/src/sys and install a new config binary\n"); + fprintf(stderr, "before trying this again.\n\n"); + fprintf(stderr, "If running the new config fails check your config\n"); + fprintf(stderr, "file against the GENERIC or LINT config files for\n"); + fprintf(stderr, "changes in config syntax, or option/device naming\n"); + fprintf(stderr, "conventions\n\n"); + exit(1); +} + +static void +checkversion(void) +{ + FILE *ifp; + char line[BUFSIZ]; + int versreq; + + ifp = open_makefile_template(); + while (fgets(line, BUFSIZ, ifp) != 0) { + if (*line != '%') + continue; + if (strncmp(line, "%VERSREQ=", 9) != 0) + continue; + versreq = atoi(line + 9); + if (MAJOR_VERS(versreq) == MAJOR_VERS(CONFIGVERS) && + versreq <= CONFIGVERS) + continue; + badversion(versreq); + } + fclose(ifp); +} diff --git a/usr.sbin/config/mkmakefile.c b/usr.sbin/config/mkmakefile.c index 7845089..b5a0e35 100644 --- a/usr.sbin/config/mkmakefile.c +++ b/usr.sbin/config/mkmakefile.c @@ -105,17 +105,14 @@ new_fent(void) } /* - * Build the makefile from the skeleton + * Open the correct Makefile and return it, or error out. */ -void -makefile(void) +FILE * +open_makefile_template(void) { - FILE *ifp, *ofp; + FILE *ifp; char line[BUFSIZ]; - struct opt *op, *t; - int versreq; - read_files(); snprintf(line, sizeof(line), "../../conf/Makefile.%s", machinename); ifp = fopen(line, "r"); if (ifp == 0) { @@ -124,7 +121,21 @@ makefile(void) } if (ifp == 0) err(1, "%s", line); + return (ifp); +} +/* + * Build the makefile from the skeleton + */ +void +makefile(void) +{ + FILE *ifp, *ofp; + char line[BUFSIZ]; + struct opt *op, *t; + + read_files(); + ifp = open_makefile_template(); ofp = fopen(path("Makefile.new"), "w"); if (ofp == 0) err(1, "%s", path("Makefile.new")); @@ -156,23 +167,9 @@ makefile(void) do_rules(ofp); else if (eq(line, "%CLEAN\n")) do_clean(ofp); - else if (strncmp(line, "%VERSREQ=", sizeof("%VERSREQ=") - 1) == 0) { - versreq = atoi(line + sizeof("%VERSREQ=") - 1); - if (MAJOR_VERS(versreq) != MAJOR_VERS(CONFIGVERS) || - versreq > CONFIGVERS) { - fprintf(stderr, "ERROR: version of config(8) does not match kernel!\n"); - fprintf(stderr, "config version = %d, ", CONFIGVERS); - fprintf(stderr, "version required = %d\n\n", versreq); - fprintf(stderr, "Make sure that /usr/src/usr.sbin/config is in sync\n"); - fprintf(stderr, "with your /usr/src/sys and install a new config binary\n"); - fprintf(stderr, "before trying this again.\n\n"); - fprintf(stderr, "If running the new config fails check your config\n"); - fprintf(stderr, "file against the GENERIC or LINT config files for\n"); - fprintf(stderr, "changes in config syntax, or option/device naming\n"); - fprintf(stderr, "conventions\n\n"); - exit(1); - } - } else + else if (strncmp(line, "%VERSREQ=", 9) == 0) + line[0] = '\0'; /* handled elsewhere */ + else fprintf(stderr, "Unknown %% construct in generic makefile: %s", line); -- cgit v1.1 From 0ee54d44efd2c656c466198d0afa88cd0357a0eb Mon Sep 17 00:00:00 2001 From: alc Date: Tue, 27 Apr 2010 05:35:35 +0000 Subject: MFi386 r207205 Clearing a page table entry's accessed bit (PG_A) and setting the page's PG_REFERENCED flag in pmap_protect() can't really be justified, so don't do it. --- sys/i386/xen/pmap.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index 40e36be..18619c3 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -2600,22 +2600,16 @@ retry: obits = pbits = *pte; if ((pbits & PG_V) == 0) continue; - if (pbits & PG_MANAGED) { - m = NULL; - if (pbits & PG_A) { - m = PHYS_TO_VM_PAGE(xpmap_mtop(pbits) & PG_FRAME); - vm_page_flag_set(m, PG_REFERENCED); - pbits &= ~PG_A; - } - if ((pbits & PG_M) != 0) { - if (m == NULL) - m = PHYS_TO_VM_PAGE(xpmap_mtop(pbits) & PG_FRAME); + + if ((prot & VM_PROT_WRITE) == 0) { + if ((pbits & (PG_MANAGED | PG_M | PG_RW)) == + (PG_MANAGED | PG_M | PG_RW)) { + m = PHYS_TO_VM_PAGE(xpmap_mtop(pbits) & + PG_FRAME); vm_page_dirty(m); } - } - - if ((prot & VM_PROT_WRITE) == 0) pbits &= ~(PG_RW | PG_M); + } #ifdef PAE if ((prot & VM_PROT_EXECUTE) == 0) pbits |= pg_nx; -- cgit v1.1 From 687e047ca195631a69ddbd770d9b88470f6f69d1 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 27 Apr 2010 05:38:26 +0000 Subject: Redo how we add compat options so as to be compatible with old versions of config. Remove support for the syntax OLD = NEW form the options file, and instead have a new file $S/conf/options-compat. This file will be parsed as OLD NEW on each line. Bump version of config. Since nothing in -current ever used this, there's no hazards for current users, so I'm not bumping the version in the Makefiles.$MACHINE. No need, really, for this version bump in -current, but this was introduced into -stable before I realized the version check was ineffective there, so the verison bump doesn't hurt here and keeps the two branches in sync, versionwise, after the MFC. MFC after: 3 days --- usr.sbin/config/configvers.h | 2 +- usr.sbin/config/mkoptions.c | 157 ++++++++++++++++++++++--------------------- 2 files changed, 81 insertions(+), 78 deletions(-) diff --git a/usr.sbin/config/configvers.h b/usr.sbin/config/configvers.h index 73310bd..2d43329 100644 --- a/usr.sbin/config/configvers.h +++ b/usr.sbin/config/configvers.h @@ -49,5 +49,5 @@ * * $FreeBSD$ */ -#define CONFIGVERS 600008 +#define CONFIGVERS 600009 #define MAJOR_VERS(x) ((x) / 100000) diff --git a/usr.sbin/config/mkoptions.c b/usr.sbin/config/mkoptions.c index 1a6ccc8..846e028 100644 --- a/usr.sbin/config/mkoptions.c +++ b/usr.sbin/config/mkoptions.c @@ -166,7 +166,7 @@ do_option(char *name) fprintf(outf, "#define %s %s\n", name, value); } /* else empty file */ - (void) fclose(outf); + (void)fclose(outf); return; } basefile = ""; @@ -225,7 +225,7 @@ do_option(char *name) if (cp == (char *)EOF) break; } - (void) fclose(inf); + (void)fclose(inf); if (!tidy && ((value == NULL && oldvalue == NULL) || (value && oldvalue && eq(value, oldvalue)))) { while (!SLIST_EMPTY(&op_head)) { @@ -263,7 +263,7 @@ do_option(char *name) free(op->op_value); free(op); } - (void) fclose(outf); + (void)fclose(outf); } /* @@ -277,7 +277,7 @@ tooption(char *name) struct opt_list *po; /* "cannot happen"? the otab list should be complete.. */ - (void) strlcpy(nbuf, "options.h", sizeof(nbuf)); + (void)strlcpy(nbuf, "options.h", sizeof(nbuf)); SLIST_FOREACH(po, &otab, o_next) { if (eq(po->o_name, name)) { @@ -286,96 +286,99 @@ tooption(char *name) } } - (void) strlcpy(hbuf, path(nbuf), sizeof(hbuf)); + (void)strlcpy(hbuf, path(nbuf), sizeof(hbuf)); return (hbuf); } -/* - * read the options and options. files - */ + static void -read_options(void) +insert_option(char *this, char *val, int flags) +{ + struct opt_list *po; + + po = (struct opt_list *) calloc(1, sizeof *po); + if (po == NULL) + err(EXIT_FAILURE, "calloc"); + po->o_name = this; + po->o_file = val; + po->o_flags = flags; + SLIST_INSERT_HEAD(&otab, po, o_next); +} + + +static void +check_duplicate(const char *fname, const char *this) +{ + struct opt_list *po; + + SLIST_FOREACH(po, &otab, o_next) { + if (eq(po->o_name, this)) { + printf("%s: Duplicate option %s.\n", + fname, this); + exit(1); + } + } +} + +static int +read_option_file(const char *fname, int flags) { FILE *fp; - char fname[MAXPATHLEN]; char *wd, *this, *val; - struct opt_list *po; - int first = 1; char genopt[MAXPATHLEN]; - int flags = 0; - SLIST_INIT(&otab); - (void) snprintf(fname, sizeof(fname), "../../conf/options"); -openit: fp = fopen(fname, "r"); - if (fp == 0) { - return; - } -next: - flags = 0; - wd = get_word(fp); - if (wd == (char *)EOF) { - (void) fclose(fp); - if (first == 1) { - first++; - (void) snprintf(fname, sizeof fname, "../../conf/options.%s", machinename); - fp = fopen(fname, "r"); - if (fp != 0) - goto next; - (void) snprintf(fname, sizeof fname, "options.%s", machinename); - goto openit; + if (fp == 0) + return (0); + while ((wd = get_word(fp)) != (char *)EOF) { + if (wd == 0) + continue; + if (wd[0] == '#') { + while (((wd = get_word(fp)) != (char *)EOF) && wd) + continue; + continue; } - return; - } - if (wd == 0) - goto next; - if (wd[0] == '#') - { - while (((wd = get_word(fp)) != (char *)EOF) && wd) - ; - goto next; - } - this = ns(wd); - val = get_word(fp); - if (val == (char *)EOF) - return; - if (val == 0) { - char *s = ns(this); - (void) snprintf(genopt, sizeof(genopt), "opt_%s.h", lower(s)); - val = genopt; - free(s); - } else if (eq(val, "=")) { + this = ns(wd); val = get_word(fp); - if (val == (char *)EOF) { - printf("%s: unexpected end of file\n", fname); - exit(1); - } + if (val == (char *)EOF) + return (1); if (val == 0) { - printf("%s: Expected a right hand side at %s\n", fname, - this); - exit(1); + if (flags) { + printf("%s: compat file requires two words " + "per line at %s\n", fname, this); + exit(1); + } + char *s = ns(this); + (void)snprintf(genopt, sizeof(genopt), "opt_%s.h", + lower(s)); + val = genopt; + free(s); } - flags |= OL_ALIAS; + val = ns(val); + check_duplicate(fname, this); + insert_option(this, val, flags); } - val = ns(val); + (void)fclose(fp); + return (1); +} - SLIST_FOREACH(po, &otab, o_next) { - if (eq(po->o_name, this)) { - printf("%s: Duplicate option %s.\n", - fname, this); - exit(1); - } - } - - po = (struct opt_list *) calloc(1, sizeof *po); - if (po == NULL) - err(EXIT_FAILURE, "calloc"); - po->o_name = this; - po->o_file = val; - po->o_flags = flags; - SLIST_INSERT_HEAD(&otab, po, o_next); +/* + * read the options and options. files + */ +static void +read_options(void) +{ + char fname[MAXPATHLEN]; - goto next; + SLIST_INIT(&otab); + read_option_file("../../conf/options", 0); + (void)snprintf(fname, sizeof fname, "../../conf/options.%s", + machinename); + if (!read_option_file(fname, 0)) { + (void)snprintf(fname, sizeof fname, "options.%s", machinename); + read_option_file(fname, 0); + } + read_option_file("../../conf/options-compat", OL_ALIAS); } static char * -- cgit v1.1 From 7eb24f6aa6071a123dd0d24f5e8806cf803305fa Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 27 Apr 2010 06:14:30 +0000 Subject: Require the option that's mapped be listed in the options file. This will allow people with old config options to either have it just work (if config is new enough), or get a version error (if their config is about 7.0 or newer) rather than getting a cryptic error about duplicated options in the options file, or getting an error about an unknown option, at which point they'd update their config file only to learn they need a new config, only to learn they didn't really need to update their config file... All this because our version checking was in the wrong place for the past decade... # hopefully this is the last change, and we'll be able to config with an # 8.0 GENERIC file on stable/8 after I merge this change and add the # compat options. MFC after: 3 days --- usr.sbin/config/mkoptions.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/usr.sbin/config/mkoptions.c b/usr.sbin/config/mkoptions.c index 846e028..044b669 100644 --- a/usr.sbin/config/mkoptions.c +++ b/usr.sbin/config/mkoptions.c @@ -292,32 +292,49 @@ tooption(char *name) static void -insert_option(char *this, char *val, int flags) +check_duplicate(const char *fname, const char *this) { struct opt_list *po; + SLIST_FOREACH(po, &otab, o_next) { + if (eq(po->o_name, this)) { + printf("%s: Duplicate option %s.\n", + fname, this); + exit(1); + } + } +} + +static void +insert_option(const char *fname, char *this, char *val) +{ + struct opt_list *po; + + check_duplicate(fname, this); po = (struct opt_list *) calloc(1, sizeof *po); if (po == NULL) err(EXIT_FAILURE, "calloc"); po->o_name = this; po->o_file = val; - po->o_flags = flags; + po->o_flags = 0; SLIST_INSERT_HEAD(&otab, po, o_next); } - static void -check_duplicate(const char *fname, const char *this) +update_option(const char *this, char *val, int flags) { struct opt_list *po; SLIST_FOREACH(po, &otab, o_next) { if (eq(po->o_name, this)) { - printf("%s: Duplicate option %s.\n", - fname, this); - exit(1); + free(po->o_file); + po->o_file = val; + po->o_flags = flags; + return; } } + printf("Compat option %s not listed in options file.\n", this); + exit(1); } static int @@ -355,8 +372,10 @@ read_option_file(const char *fname, int flags) free(s); } val = ns(val); - check_duplicate(fname, this); - insert_option(this, val, flags); + if (flags == 0) + insert_option(fname, this, val); + else + update_option(this, val, flags); } (void)fclose(fp); return (1); -- cgit v1.1 From 85688162953c4cf38c355bcc60c0ab181a3bfa2e Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 27 Apr 2010 09:47:14 +0000 Subject: Provide 32bit compat for SIOCGDEFIFACE_IN6. Based on submission by: pluknet gmail com Reviewed by: emaste MFC after: 2 weeks --- sys/netinet6/in6.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 74c15d5..15ff6b2 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -63,6 +63,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" #include "opt_inet.h" #include "opt_inet6.h" @@ -176,6 +177,14 @@ in6_mask2len(struct in6_addr *mask, u_char *lim0) #define ifa2ia6(ifa) ((struct in6_ifaddr *)(ifa)) #define ia62ifa(ia6) (&((ia6)->ia_ifa)) +#ifdef COMPAT_FREEBSD32 +struct in6_ndifreq32 { + char ifname[IFNAMSIZ]; + uint32_t ifindex; +}; +#define SIOCGDEFIFACE32_IN6 _IOWR('i', 86, struct in6_ndifreq32) +#endif + int in6_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) @@ -226,6 +235,22 @@ in6_control(struct socket *so, u_long cmd, caddr_t data, case SIOCGNBRINFO_IN6: case SIOCGDEFIFACE_IN6: return (nd6_ioctl(cmd, data, ifp)); + +#ifdef COMPAT_FREEBSD32 + case SIOCGDEFIFACE32_IN6: + { + struct in6_ndifreq ndif; + struct in6_ndifreq32 *ndif32; + + error = nd6_ioctl(SIOCGDEFIFACE_IN6, (caddr_t)&ndif, + ifp); + if (error) + return (error); + ndif32 = (struct in6_ndifreq32 *)data; + ndif32->ifindex = ndif.ifindex; + return (0); + } +#endif } switch (cmd) { -- cgit v1.1 From e20b2d597f181152ff9b2de6a030674bf89a65e0 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 27 Apr 2010 09:48:43 +0000 Subject: Style: use #define instead of #define. Noted by: bde, pluknet gmail com MFC after: 11 days --- sys/amd64/include/proc.h | 4 ++-- sys/arm/include/proc.h | 2 +- sys/i386/include/proc.h | 2 +- sys/ia64/include/proc.h | 4 ++-- sys/mips/include/proc.h | 4 ++-- sys/powerpc/include/proc.h | 2 +- sys/sparc64/include/proc.h | 2 +- sys/sun4v/include/proc.h | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h index 126412c..acea4c0 100644 --- a/sys/amd64/include/proc.h +++ b/sys/amd64/include/proc.h @@ -53,8 +53,8 @@ struct mdproc { struct system_segment_descriptor md_ldt_sd; }; -#define KINFO_PROC_SIZE 1088 -#define KINFO_PROC32_SIZE 768 +#define KINFO_PROC_SIZE 1088 +#define KINFO_PROC32_SIZE 768 #ifdef _KERNEL diff --git a/sys/arm/include/proc.h b/sys/arm/include/proc.h index 37051bf..0885744 100644 --- a/sys/arm/include/proc.h +++ b/sys/arm/include/proc.h @@ -60,6 +60,6 @@ struct mdproc { void *md_sigtramp; }; -#define KINFO_PROC_SIZE 792 +#define KINFO_PROC_SIZE 792 #endif /* !_MACHINE_PROC_H_ */ diff --git a/sys/i386/include/proc.h b/sys/i386/include/proc.h index 0b9fca2..86be8c8 100644 --- a/sys/i386/include/proc.h +++ b/sys/i386/include/proc.h @@ -57,7 +57,7 @@ struct mdproc { struct proc_ldt *md_ldt; /* (t) per-process ldt */ }; -#define KINFO_PROC_SIZE 768 +#define KINFO_PROC_SIZE 768 #ifdef _KERNEL diff --git a/sys/ia64/include/proc.h b/sys/ia64/include/proc.h index 81e2e4f..e9f337c 100644 --- a/sys/ia64/include/proc.h +++ b/sys/ia64/include/proc.h @@ -38,7 +38,7 @@ struct mdproc { int __dummy; /* Avoid having an empty struct. */ }; -#define KINFO_PROC_SIZE 1088 -#define KINFO_PROC32_SIZE 768 +#define KINFO_PROC_SIZE 1088 +#define KINFO_PROC32_SIZE 768 #endif /* !_MACHINE_PROC_H_ */ diff --git a/sys/mips/include/proc.h b/sys/mips/include/proc.h index 1479eda..e71c858 100644 --- a/sys/mips/include/proc.h +++ b/sys/mips/include/proc.h @@ -69,9 +69,9 @@ void mips_cpu_switch(struct thread *, struct thread *, struct mtx *); void mips_cpu_throw(struct thread *, struct thread *); #ifdef __mips_n64 -#define KINFO_PROC_SIZE 1088 +#define KINFO_PROC_SIZE 1088 #else -#define KINFO_PROC_SIZE 816 +#define KINFO_PROC_SIZE 816 #endif #endif /* !_MACHINE_PROC_H_ */ diff --git a/sys/powerpc/include/proc.h b/sys/powerpc/include/proc.h index cbe6da9..d51116b 100644 --- a/sys/powerpc/include/proc.h +++ b/sys/powerpc/include/proc.h @@ -46,6 +46,6 @@ struct mdthread { struct mdproc { }; -#define KINFO_PROC_SIZE 768 +#define KINFO_PROC_SIZE 768 #endif /* !_MACHINE_PROC_H_ */ diff --git a/sys/sparc64/include/proc.h b/sys/sparc64/include/proc.h index 84eaed5..3c23663 100644 --- a/sys/sparc64/include/proc.h +++ b/sys/sparc64/include/proc.h @@ -51,6 +51,6 @@ struct mdproc { void *md_sigtramp; }; -#define KINFO_PROC_SIZE 1088 +#define KINFO_PROC_SIZE 1088 #endif /* !_MACHINE_PROC_H_ */ diff --git a/sys/sun4v/include/proc.h b/sys/sun4v/include/proc.h index 84eaed5..3c23663 100644 --- a/sys/sun4v/include/proc.h +++ b/sys/sun4v/include/proc.h @@ -51,6 +51,6 @@ struct mdproc { void *md_sigtramp; }; -#define KINFO_PROC_SIZE 1088 +#define KINFO_PROC_SIZE 1088 #endif /* !_MACHINE_PROC_H_ */ -- cgit v1.1 From 6def960c90c238bc5be3dd59b7704373f0b3989c Mon Sep 17 00:00:00 2001 From: bms Date: Tue, 27 Apr 2010 14:14:21 +0000 Subject: Fix a regression where DVMRP diagnostic traffic, such as that used by mrinfo and mtrace, was dropped by the IGMP TTL check. IGMP control traffic must always have a TTL of 1. Submitted by: Matthew Luckie MFC after: 3 days --- sys/netinet/igmp.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index f9f6381..d4c8e99 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -1468,12 +1468,6 @@ igmp_input(struct mbuf *m, int off) } ip = mtod(m, struct ip *); - if (ip->ip_ttl != 1) { - IGMPSTAT_INC(igps_rcv_badttl); - m_freem(m); - return; - } - /* * Validate checksum. */ @@ -1488,6 +1482,17 @@ igmp_input(struct mbuf *m, int off) m->m_data -= iphlen; m->m_len += iphlen; + /* + * IGMP control traffic is link-scope, and must have a TTL of 1. + * DVMRP traffic (e.g. mrinfo, mtrace) is an exception; + * probe packets may come from beyond the LAN. + */ + if (igmp->igmp_type != IGMP_DVMRP && ip->ip_ttl != 1) { + IGMPSTAT_INC(igps_rcv_badttl); + m_freem(m); + return; + } + switch (igmp->igmp_type) { case IGMP_HOST_MEMBERSHIP_QUERY: if (igmplen == IGMP_MINLEN) { -- cgit v1.1 From e66b2bd00b8aeff7786ee941efdd1b5c067e459c Mon Sep 17 00:00:00 2001 From: bz Date: Tue, 27 Apr 2010 15:05:03 +0000 Subject: Make sure IPv6 source address selection does not change interface addresses while walking the IPv6 address list if in the jail case something is connecting to ::1. Reported by: Pieter de Boer (pieter thedarkside.nl) Tested by: Pieter de Boer (pieter thedarkside.nl) MFC after: 4 days --- sys/netinet6/in6_src.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index ea302a5..e6c2cd8 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -182,7 +182,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, struct inpcb *inp, struct route_in6 *ro, struct ucred *cred, struct ifnet **ifpp, struct in6_addr *srcp) { - struct in6_addr dst; + struct in6_addr dst, tmp; struct ifnet *ifp = NULL; struct in6_ifaddr *ia = NULL, *ia_best = NULL; struct in6_pktinfo *pi = NULL; @@ -326,10 +326,9 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, if (!V_ip6_use_deprecated && IFA6_IS_DEPRECATED(ia)) continue; + /* If jailed only take addresses of the jail into account. */ if (cred != NULL && - prison_local_ip6(cred, &ia->ia_addr.sin6_addr, - (inp != NULL && - (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) + prison_check_ip6(cred, &ia->ia_addr.sin6_addr) != 0) continue; /* Rule 1: Prefer same address */ @@ -476,10 +475,26 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, return (EADDRNOTAVAIL); } + /* + * At this point at least one of the addresses belonged to the jail + * but it could still be, that we want to further restrict it, e.g. + * theoratically IN6_IS_ADDR_LOOPBACK. + * It must not be IN6_IS_ADDR_UNSPECIFIED anymore. + * prison_local_ip6() will fix an IN6_IS_ADDR_LOOPBACK but should + * let all others previously selected pass. + * Use tmp to not change ::1 on lo0 to the primary jail address. + */ + tmp = ia->ia_addr.sin6_addr; + if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL && + (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) { + IN6_IFADDR_RUNLOCK(); + return (EADDRNOTAVAIL); + } + if (ifpp) *ifpp = ifp; - bcopy(&ia->ia_addr.sin6_addr, srcp, sizeof(*srcp)); + bcopy(&tmp, srcp, sizeof(*srcp)); IN6_IFADDR_RUNLOCK(); return (0); } -- cgit v1.1 From c7fd54ae5aaa23136f70d1bc2685cdc3e78a315e Mon Sep 17 00:00:00 2001 From: bz Date: Tue, 27 Apr 2010 15:07:08 +0000 Subject: Enhance the historic behaviour of raw sockets and jails in a way that we allow all possible jail IPs as source address rather than forcing the "primary". While IPv6 naturally has source address selection, for legacy IP we do not go through the pain in case IP_HDRINCL was not set. People should bind(2) for that. This will, for example, allow ping(|6) -S to work correctly for non-primary addresses. Reported by: (ten 211.ru) Tested by: (ten 211.ru) MFC after: 4 days --- sys/netinet/raw_ip.c | 23 ++++++++++++++++++----- sys/netinet6/raw_ip6.c | 2 +- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 1db3774..0b77b5b 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -427,11 +427,24 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst) ip->ip_p = inp->inp_ip_p; ip->ip_len = m->m_pkthdr.len; ip->ip_src = inp->inp_laddr; - error = prison_get_ip4(inp->inp_cred, &ip->ip_src); - if (error != 0) { - INP_RUNLOCK(inp); - m_freem(m); - return (error); + if (jailed(inp->inp_cred)) { + /* + * prison_local_ip4() would be good enough but would + * let a source of INADDR_ANY pass, which we do not + * want to see from jails. We do not go through the + * pain of in_pcbladdr() for raw sockets. + */ + if (ip->ip_src.s_addr == INADDR_ANY) + error = prison_get_ip4(inp->inp_cred, + &ip->ip_src); + else + error = prison_local_ip4(inp->inp_cred, + &ip->ip_src); + if (error != 0) { + INP_RUNLOCK(inp); + m_freem(m); + return (error); + } } ip->ip_dst.s_addr = dst; ip->ip_ttl = inp->inp_ip_ttl; diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 9f1236a..6052b24 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -465,7 +465,7 @@ rip6_output(m, va_alist) &oifp, &in6a); if (error) goto bad; - error = prison_get_ip6(in6p->inp_cred, &in6a); + error = prison_check_ip6(in6p->inp_cred, &in6a); if (error != 0) goto bad; ip6->ip6_src = in6a; -- cgit v1.1 From 7fcd42cfee8558342ba8a17f56aa25fc53bac879 Mon Sep 17 00:00:00 2001 From: bz Date: Tue, 27 Apr 2010 15:16:54 +0000 Subject: MFP4: @177254 Add missing CURVNET_RESTORE() calls for multiple code paths, to stop leaking the currently cached vnet into callers and to the process. Sponsored by: The FreeBSD Foundation Sponsored by: CK Software GmbH MFC after: 4 days --- sys/net/bpf.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 1755ec7..16245c9 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -1454,6 +1454,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, /* FALLSTHROUGH */ default: + CURVNET_RESTORE(); return (EINVAL); } @@ -1461,6 +1462,7 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, if (d->bd_sbuf != NULL || d->bd_hbuf != NULL || d->bd_fbuf != NULL || d->bd_bif != NULL) { BPFD_UNLOCK(d); + CURVNET_RESTORE(); return (EBUSY); } d->bd_bufmode = *(u_int *)addr; @@ -1468,13 +1470,16 @@ bpfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, break; case BIOCGETZMAX: - return (bpf_ioctl_getzmax(td, d, (size_t *)addr)); + error = bpf_ioctl_getzmax(td, d, (size_t *)addr); + break; case BIOCSETZBUF: - return (bpf_ioctl_setzbuf(td, d, (struct bpf_zbuf *)addr)); + error = bpf_ioctl_setzbuf(td, d, (struct bpf_zbuf *)addr); + break; case BIOCROTZBUF: - return (bpf_ioctl_rotzbuf(td, d, (struct bpf_zbuf *)addr)); + error = bpf_ioctl_rotzbuf(td, d, (struct bpf_zbuf *)addr); + break; } CURVNET_RESTORE(); return (error); -- cgit v1.1 From 0e0efd3d2fd202dc81c6e8a3707c5ec046e62b2f Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 27 Apr 2010 15:50:25 +0000 Subject: Take advantage of OF_getscsinitid(). --- sys/dev/esp/esp_sbus.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sys/dev/esp/esp_sbus.c b/sys/dev/esp/esp_sbus.c index 2033cc6..3ba0d46 100644 --- a/sys/dev/esp/esp_sbus.c +++ b/sys/dev/esp/esp_sbus.c @@ -466,9 +466,7 @@ espattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep) goto fail_lock; } - if (OF_getprop(ofw_bus_get_node(esc->sc_dev), "scsi-initiator-id", - &sc->sc_id, sizeof(sc->sc_id)) == -1) - sc->sc_id = 7; + sc->sc_id = OF_getscsinitid(esc->sc_dev); #ifdef ESP_SBUS_DEBUG device_printf(esc->sc_dev, "%s: sc_id %d, freq %d\n", -- cgit v1.1 From e766c487b011e066797a3ca22470812e40e39511 Mon Sep 17 00:00:00 2001 From: mav Date: Tue, 27 Apr 2010 15:59:38 +0000 Subject: Update device identify data and serial number when device change detected. Reprobe immediately following this should have fresh data. --- sys/cam/ata/ata_xpt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c index 3bf9c1e..10e6182 100644 --- a/sys/cam/ata/ata_xpt.c +++ b/sys/cam/ata/ata_xpt.c @@ -768,6 +768,7 @@ noerror: { struct ccb_pathinq cpi; int16_t *ptr; + int changed = 1; ident_buf = &softc->ident_data; for (ptr = (int16_t *)ident_buf; @@ -809,9 +810,12 @@ noerror: sizeof(ident_buf->serial))) { /* Device changed. */ xpt_async(AC_LOST_DEVICE, path, NULL); - } else + } else { bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); - } else { + changed = 0; + } + } + if (changed) { bcopy(&softc->ident_data, ident_buf, sizeof(struct ata_params)); /* Clean up from previous instance of this device */ if (path->device->serial_num != NULL) { -- cgit v1.1 From 8c986a2f888166ed91becbd51c87ff00b554678c Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 27 Apr 2010 17:50:43 +0000 Subject: Language improvements to make the BUGS section easier to read. Reviewed by: Alexander Best MFC after: 13 days --- usr.bin/gzip/gzip.1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/usr.bin/gzip/gzip.1 b/usr.bin/gzip/gzip.1 index bb1fadd..848a4b3 100644 --- a/usr.bin/gzip/gzip.1 +++ b/usr.bin/gzip/gzip.1 @@ -25,7 +25,7 @@ .\" SUCH DAMAGE. .\" .\" $FreeBSD$ -.Dd April 7, 2010 +.Dd April 27, 2010 .Dt GZIP 1 .Os .Sh NAME @@ -218,8 +218,8 @@ with unpack support written by .An Xin LI Aq delphij@FreeBSD.org . .Sh BUGS According to RFC 1952, the recorded file size is stored in a 32-bit -integer and therefore it can not represent files that is bigger than -4GB in size. This limitation also applies to +integer, therefore, it can not represent files larger than 4GB. +This limitation also applies to .Fl l option of .Nm -- cgit v1.1 From 16ffa87683fefed796ccdad41a11b885b0688b24 Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 27 Apr 2010 17:57:04 +0000 Subject: Use _exit(2) system call directly instead of using exit(3) in signal handler, as the latter is not guaranteed to be signal safe, and we do not really care about flushing the stream during SIGINT. Suggested by: Maxim Konovalov MFC after: 13 days --- usr.bin/gzip/gzip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/gzip/gzip.c b/usr.bin/gzip/gzip.c index 9503762..de9fe80 100644 --- a/usr.bin/gzip/gzip.c +++ b/usr.bin/gzip/gzip.c @@ -1178,7 +1178,7 @@ sigint_handler(int signo __unused) if (remove_file != NULL) unlink(remove_file); - exit(2); + _exit(2); } #endif -- cgit v1.1 From 810d92b3d2a82e273d353c01b779d771b914ede7 Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 27 Apr 2010 18:05:33 +0000 Subject: - On sparc64 obtain the initiator ID from the Open Firmware device tree in order to match what the PROM built-in driver uses. - Remove some no longer used includes. --- sys/dev/sym/sym_hipd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c index a43c816..5050a5f 100644 --- a/sys/dev/sym/sym_hipd.c +++ b/sys/dev/sym/sym_hipd.c @@ -87,6 +87,12 @@ __FBSDID("$FreeBSD$"); #include #include + +#ifdef __sparc64__ +#include +#include +#endif + #include #include @@ -98,10 +104,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include -#include -#include - /* Short and quite clear integer types */ typedef int8_t s8; typedef int16_t s16; @@ -2682,6 +2684,9 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) */ np->myaddr = 255; sym_nvram_setup_host (np, nvram); +#ifdef __sparc64__ + np->myaddr = OF_getscsinitid(np->device); +#endif /* * Get SCSI addr of host adapter (set by bios?). -- cgit v1.1 From e4de7c863563cef3e5f2ebcf832f5be8e954ad84 Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 27 Apr 2010 18:06:54 +0000 Subject: Replace a magic value with the appropriate macro. --- sys/dev/mpt/mpt_cam.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c index 5e63ef9..56ea3e0 100644 --- a/sys/dev/mpt/mpt_cam.c +++ b/sys/dev/mpt/mpt_cam.c @@ -1058,12 +1058,13 @@ mpt_read_config_info_spi(struct mpt_softc *mpt) static int mpt_set_initial_config_spi(struct mpt_softc *mpt) { - int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id; - int error; + int error, i, pp1val; mpt->mpt_disc_enable = 0xff; mpt->mpt_tag_enable = 0; + pp1val = ((1 << mpt->mpt_ini_id) << + MPI_SCSIPORTPAGE1_CFG_SHIFT_PORT_RESPONSE_ID) | mpt->mpt_ini_id; if (mpt->mpt_port_page1.Configuration != pp1val) { CONFIG_PAGE_SCSI_PORT_1 tmp; -- cgit v1.1 From 97002d72b5e073618d8b4d7c2e2a8b20f2cd3392 Mon Sep 17 00:00:00 2001 From: marius Date: Tue, 27 Apr 2010 18:41:16 +0000 Subject: On sparc64 obtain the initiator ID to be used for SPI HBAs from the Open Firmware device tree in order to match what the PROM built-in driver uses. This is especially important when netbooting Fujitsu Siemens PRIMEPOWER250 as in that case the built-in driver isn't used and the port facts PortSCSIID defaults to 0, conflicting with the disk at the same address. --- sys/dev/mpt/mpt.c | 2 ++ sys/dev/mpt/mpt.h | 10 +++++++++- sys/dev/mpt/mpt_pci.c | 5 +++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c index 6a74dc3..40c581c 100644 --- a/sys/dev/mpt/mpt.c +++ b/sys/dev/mpt/mpt.c @@ -2667,6 +2667,8 @@ mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset) mpt->is_fc = 0; mpt->is_sas = 0; mpt->is_spi = 1; + if (mpt->mpt_ini_id == MPT_INI_ID_NONE) + mpt->mpt_ini_id = pfp->PortSCSIID; } else if (pfp->PortType == MPI_PORTFACTS_PORTTYPE_ISCSI) { mpt_prt(mpt, "iSCSI not supported yet\n"); return (ENXIO); diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h index 1fa2d1aa..ab4cfa6 100644 --- a/sys/dev/mpt/mpt.h +++ b/sys/dev/mpt/mpt.h @@ -130,6 +130,11 @@ #include #endif +#ifdef __sparc64__ +#include +#include +#endif + #include #if __FreeBSD_version < 500000 @@ -172,6 +177,8 @@ #define MPT_ROLE_BOTH 3 #define MPT_ROLE_DEFAULT MPT_ROLE_INITIATOR +#define MPT_INI_ID_NONE -1 + /**************************** Forward Declarations ****************************/ struct mpt_softc; struct mpt_personality; @@ -637,7 +644,6 @@ struct mpt_softc { * Port Facts */ MSG_PORT_FACTS_REPLY * port_facts; -#define mpt_ini_id port_facts[0].PortSCSIID #define mpt_max_tgtcmds port_facts[0].MaxPostedCmdBuffers /* @@ -650,6 +656,7 @@ struct mpt_softc { CONFIG_PAGE_SCSI_PORT_2 _port_page2; CONFIG_PAGE_SCSI_DEVICE_0 _dev_page0[16]; CONFIG_PAGE_SCSI_DEVICE_1 _dev_page1[16]; + int _ini_id; uint16_t _tag_enable; uint16_t _disc_enable; } spi; @@ -658,6 +665,7 @@ struct mpt_softc { #define mpt_port_page2 cfg.spi._port_page2 #define mpt_dev_page0 cfg.spi._dev_page0 #define mpt_dev_page1 cfg.spi._dev_page1 +#define mpt_ini_id cfg.spi._ini_id #define mpt_tag_enable cfg.spi._tag_enable #define mpt_disc_enable cfg.spi._disc_enable struct mpi_fc_cfg { diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c index 1e9dc92..e3b0ea3 100644 --- a/sys/dev/mpt/mpt_pci.c +++ b/sys/dev/mpt/mpt_pci.c @@ -460,6 +460,11 @@ mpt_pci_attach(device_t dev) mpt->raid_queue_depth = MPT_RAID_QUEUE_DEPTH_DEFAULT; mpt->verbose = MPT_PRT_NONE; mpt->role = MPT_ROLE_NONE; + mpt->mpt_ini_id = MPT_INI_ID_NONE; +#ifdef __sparc64__ + if (mpt->is_spi) + mpt->mpt_ini_id = OF_getscsinitid(dev); +#endif mpt_set_options(mpt); if (mpt->verbose == MPT_PRT_NONE) { mpt->verbose = MPT_PRT_WARN; -- cgit v1.1 From e04522d3423e9357b3154adcc6c92bdfdb143798 Mon Sep 17 00:00:00 2001 From: kmacy Date: Tue, 27 Apr 2010 23:48:50 +0000 Subject: need to initialize the lock before it is used MFC after: 3 days --- sys/net/flowtable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net/flowtable.c b/sys/net/flowtable.c index 39b6b40..0e4beb4 100644 --- a/sys/net/flowtable.c +++ b/sys/net/flowtable.c @@ -1626,7 +1626,7 @@ flowtable_init(const void *unused __unused) EVENTHANDLER_PRI_ANY); flowclean_freq = 20*hz; } -SYSINIT(flowtable_init, SI_SUB_SMP, SI_ORDER_MIDDLE, +SYSINIT(flowtable_init, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, flowtable_init, NULL); -- cgit v1.1 From ab8f1a23027c2e8da82bdd87bf0a682b0d46cfd3 Mon Sep 17 00:00:00 2001 From: alc Date: Wed, 28 Apr 2010 04:25:36 +0000 Subject: Adapt i386 r207205 to mips: Clearing PV_TABLE_REF and setting the page's PG_REFERENCED flag in pmap_protect() can't really be justified, so don't do it. --- sys/mips/mips/pmap.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c index 3634a27..e7c3239 100644 --- a/sys/mips/mips/pmap.c +++ b/sys/mips/mips/pmap.c @@ -1690,16 +1690,10 @@ retry: obits = pbits = *pte; pa = mips_tlbpfn_to_paddr(pbits); - if (page_is_managed(pa)) { + if (page_is_managed(pa) && (pbits & PTE_M) != 0) { m = PHYS_TO_VM_PAGE(pa); - if (m->md.pv_flags & PV_TABLE_REF) { - vm_page_flag_set(m, PG_REFERENCED); - m->md.pv_flags &= ~PV_TABLE_REF; - } - if (pbits & PTE_M) { - vm_page_dirty(m); - m->md.pv_flags &= ~PV_TABLE_MOD; - } + vm_page_dirty(m); + m->md.pv_flags &= ~PV_TABLE_MOD; } pbits = (pbits & ~PTE_M) | PTE_RO; -- cgit v1.1 From e3ebeca68ee63f3d21dcf972f4bce28fd2cb8fae Mon Sep 17 00:00:00 2001 From: alc Date: Wed, 28 Apr 2010 04:57:32 +0000 Subject: Change vm_object_madvise() so that it checks whether the page is invalid or unmanaged before acquiring the page queues lock. Neither of these tests require that lock. Moreover, a better way of testing if the page is unmanaged is to test the type of vm object. This avoids a pointless vm_page_lookup(). MFC after: 3 weeks --- sys/vm/vm_object.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 7e4dbc8..c25ab77 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1162,7 +1162,8 @@ shadowlookup: (tobject->flags & OBJ_ONEMAPPING) == 0) { goto unlock_tobject; } - } + } else if (tobject->type == OBJT_PHYS) + goto unlock_tobject; m = vm_page_lookup(tobject, tpindex); if (m == NULL && advise == MADV_WILLNEED) { /* @@ -1189,18 +1190,13 @@ shadowlookup: VM_OBJECT_UNLOCK(tobject); tobject = backing_object; goto shadowlookup; - } + } else if (m->valid != VM_PAGE_BITS_ALL) + goto unlock_tobject; /* - * If the page is busy or not in a normal active state, - * we skip it. If the page is not managed there are no - * page queues to mess with. Things can break if we mess - * with pages in any of the below states. + * If the page is not in a normal state, skip it. */ vm_page_lock_queues(); - if (m->hold_count || - m->wire_count || - (m->flags & PG_UNMANAGED) || - m->valid != VM_PAGE_BITS_ALL) { + if (m->hold_count != 0 || m->wire_count != 0) { vm_page_unlock_queues(); goto unlock_tobject; } -- cgit v1.1 From bf8b583320ded917c381fddea802978da3283373 Mon Sep 17 00:00:00 2001 From: alc Date: Wed, 28 Apr 2010 06:34:47 +0000 Subject: Setting PG_REFERENCED on a page at the end of vm_fault() is redundant since the page table entry's accessed bit is either preset by the immediately preceding call to pmap_enter() or by hardware (or software) upon return from vm_fault() when the faulting access is restarted. --- sys/vm/vm_fault.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index f409856..058cbb0 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -924,7 +924,6 @@ vnode_locked: vm_fault_prefault(fs.map->pmap, vaddr, fs.entry); VM_OBJECT_LOCK(fs.object); vm_page_lock_queues(); - vm_page_flag_set(fs.m, PG_REFERENCED); /* * If the page is not wired down, then put it where the pageout daemon -- cgit v1.1 From 564f436237b899065a515b935bf0bc8502082439 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 28 Apr 2010 07:26:41 +0000 Subject: - Fix builds without SOFTUPDATES defined in the kernel config. --- sys/ufs/ffs/ffs_softdep.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 4a659f9..b08e7c2 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -123,6 +123,21 @@ softdep_uninitialize() } void +softdep_unmount(mp) + struct mount *mp; +{ + +} + +void +softdep_setup_sbupdate(ump, fs, bp) + struct ufsmount *ump; + struct fs *fs; + struct buf *bp; +{ +} + +void softdep_setup_inomapdep(bp, ip, newinum) struct buf *bp; struct inode *ip; @@ -267,6 +282,162 @@ softdep_setup_directory_change(bp, dp, ip, newinum, isrmdir) panic("softdep_setup_directory_change called"); } +void * +softdep_setup_trunc(vp, length, flags) + struct vnode *vp; + off_t length; + int flags; +{ + + panic("%s called", __FUNCTION__); + + return (NULL); +} + +int +softdep_complete_trunc(vp, cookie) + struct vnode *vp; + void *cookie; +{ + + panic("%s called", __FUNCTION__); + + return (0); +} + +void +softdep_setup_blkfree(mp, bp, blkno, frags, wkhd) + struct mount *mp; + struct buf *bp; + ufs2_daddr_t blkno; + int frags; + struct workhead *wkhd; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_setup_inofree(mp, bp, ino, wkhd) + struct mount *mp; + struct buf *bp; + ino_t ino; + struct workhead *wkhd; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_setup_unlink(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_setup_link(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_revert_link(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_setup_rmdir(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_revert_rmdir(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_setup_create(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_revert_create(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_setup_mkdir(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_revert_mkdir(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +void +softdep_setup_dotdot_link(dp, ip) + struct inode *dp; + struct inode *ip; +{ + + panic("%s called", __FUNCTION__); +} + +int +softdep_prealloc(vp, waitok) + struct vnode *vp; + int waitok; +{ + + panic("%s called", __FUNCTION__); + + return (0); +} + +int +softdep_journal_lookup(mp, vpp) + struct mount *mp; + struct vnode **vpp; +{ + + return (ENOENT); +} + void softdep_change_linkcnt(ip) struct inode *ip; -- cgit v1.1 From 47b1b89a950518d81f6325cff900426303029b36 Mon Sep 17 00:00:00 2001 From: jeff Date: Wed, 28 Apr 2010 07:57:37 +0000 Subject: - When canceling jaddrefs they may not yet be in the journal if this is via a revert call. In this case don't attempt to remove something that has not yet been added. Otherwise this jaddref must hang around to prevent the bitmap write as normal. --- sys/ufs/ffs/ffs_softdep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index b08e7c2..b05339b 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -3504,7 +3504,8 @@ cancel_jaddref(jaddref, inodedep, wkhd) WORKLIST_INSERT(wkhd, &jsegdep->jd_list); } else { free_jsegdep(jsegdep); - remove_from_journal(&jaddref->ja_list); + if (jaddref->ja_state & DEPCOMPLETE) + remove_from_journal(&jaddref->ja_list); } /* * Leave NEWBLOCK jaddrefs on the inodedep so handle_workitem_remove -- cgit v1.1 From c86e821ecb2a324088edbbb87198b4d55833575a Mon Sep 17 00:00:00 2001 From: rnoland Date: Wed, 28 Apr 2010 10:33:41 +0000 Subject: fx->lock is used as an index, correct test case. MFC after: 1 week --- sys/dev/drm/via_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/drm/via_video.c b/sys/dev/drm/via_video.c index f903cf5..3bd9605 100644 --- a/sys/dev/drm/via_video.c +++ b/sys/dev/drm/via_video.c @@ -78,7 +78,7 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_ DRM_DEBUG("\n"); - if (fx->lock > VIA_NR_XVMC_LOCKS) + if (fx->lock >= VIA_NR_XVMC_LOCKS) return -EFAULT; lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock); -- cgit v1.1 From fc607a2e80dfeb125ae2fe83191d934929997047 Mon Sep 17 00:00:00 2001 From: des Date: Wed, 28 Apr 2010 10:36:33 +0000 Subject: Upgrade to OpenSSH 5.5p1. --- crypto/openssh/ChangeLog | 118 ++++++++++++++++++++++++- crypto/openssh/README | 4 +- crypto/openssh/auth-options.c | 6 +- crypto/openssh/auth2-pubkey.c | 31 ++++--- crypto/openssh/channels.c | 6 +- crypto/openssh/clientloop.c | 3 +- crypto/openssh/config.h | 15 +++- crypto/openssh/config.h.in | 12 ++- crypto/openssh/defines.h | 2 +- crypto/openssh/key.c | 15 +++- crypto/openssh/key.h | 3 +- crypto/openssh/loginrec.c | 9 +- crypto/openssh/logintest.c | 2 +- crypto/openssh/openbsd-compat/bsd-arc4random.c | 4 +- crypto/openssh/servconf.c | 19 ++-- crypto/openssh/session.c | 8 +- crypto/openssh/ssh-keygen.1 | 43 +++++---- crypto/openssh/ssh-keygen.c | 5 +- crypto/openssh/ssh-pkcs11-helper.c | 4 +- crypto/openssh/ssh.1 | 9 +- crypto/openssh/ssh_config | 2 +- crypto/openssh/ssh_config.5 | 12 +-- crypto/openssh/sshd_config | 2 +- crypto/openssh/sshd_config.5 | 2 +- crypto/openssh/version.h | 6 +- 25 files changed, 254 insertions(+), 88 deletions(-) diff --git a/crypto/openssh/ChangeLog b/crypto/openssh/ChangeLog index d6e4a4a..a08e1a7 100644 --- a/crypto/openssh/ChangeLog +++ b/crypto/openssh/ChangeLog @@ -1,4 +1,120 @@ -20100307 +20100410 + - (dtucker) [configure.ac] Put the check for the existence of getaddrinfo + back so we disable the IPv6 tests if we don't have it. + +20100409 + - (dtucker) [contrib/cygwin/Makefile] Don't overwrite files with the wrong + ones. Based on a patch from Roumen Petrov. + - (dtucker) [configure.ac] Bug #1744: use pkg-config for libedit flags if we + have it and the path is not provided to --with-libedit. Based on a patch + from Iain Morgan. + - (dtucker) [configure.ac defines.h loginrec.c logintest.c] Bug #1732: enable + utmpx support on FreeBSD where possible. Patch from Ed Schouten, ok djm@ + +20100326 + - (djm) [openbsd-compat/bsd-arc4random.c] Fix preprocessor detection + for arc4random_buf() and arc4random_uniform(); from Josh Gilkerson + - (dtucker) [configure.ac] Bug #1741: Add section for Haiku, patch originally + by Ingo Weinhold via Scott McCreary, ok djm@ + - (djm) OpenBSD CVS Sync + - djm@cvs.openbsd.org 2010/03/25 23:38:28 + [servconf.c] + from portable: getcwd(NULL, 0) doesn't work on all platforms, so + use a stack buffer; ok dtucker@ + - djm@cvs.openbsd.org 2010/03/26 00:26:58 + [ssh.1] + mention that -S none disables connection sharing; from Colin Watson + - (djm) [session.c] Allow ChrootDirectory to work on SELinux platforms - + set up SELinux execution context before chroot() call. From Russell + Coker via Colin watson; bz#1726 ok dtucker@ + - (djm) [channels.c] Check for EPFNOSUPPORT as a socket() errno; bz#1721 + ok dtucker@ + - (dtucker) Bug #1725: explicitly link libX11 into gnome-ssh-askpass2 using + pkg-config, patch from Colin Watson. Needed for newer linkers (ie gold). + - (djm) [contrib/ssh-copy-id] Don't blow up when the agent has no keys; + bz#1723 patch from Adeodato Simóvia Colin Watson; ok dtucker@ + - (dtucker) OpenBSD CVS Sync + - dtucker@cvs.openbsd.org 2010/03/26 01:06:13 + [ssh_config.5] + Reformat default value of PreferredAuthentications entry (current + formatting implies ", " is acceptable as a separator, which it's not. + ok djm@ + +20100324 + - (dtucker) [contrib/cygwin/ssh-host-config] Mount the Windows directory + containing the services file explicitely case-insensitive. This allows to + tweak the Windows services file reliably. Patch from vinschen at redhat. + +20100321 + - (djm) OpenBSD CVS Sync + - jmc@cvs.openbsd.org 2010/03/08 09:41:27 + [ssh-keygen.1] + sort the list of constraints (to -O); ok djm + - jmc@cvs.openbsd.org 2010/03/10 07:40:35 + [ssh-keygen.1] + typos; from Ross Richardson + closes prs 6334 and 6335 + - djm@cvs.openbsd.org 2010/03/10 23:27:17 + [auth2-pubkey.c] + correct certificate logging and make it more consistent between + authorized_keys and TrustedCAKeys; ok markus@ + - djm@cvs.openbsd.org 2010/03/12 01:06:25 + [servconf.c] + unbreak AuthorizedKeys option with a $HOME-relative path; reported by + vinschen AT redhat.com, ok dtucker@ + - markus@cvs.openbsd.org 2010/03/12 11:37:40 + [servconf.c] + do not prepend AuthorizedKeysFile with getcwd(), unbreaks relative paths + free() (not xfree()) the buffer returned by getcwd() + - djm@cvs.openbsd.org 2010/03/13 21:10:38 + [clientloop.c] + protocol conformance fix: send language tag when disconnecting normally; + spotted by 1.41421 AT gmail.com, ok markus@ deraadt@ + - djm@cvs.openbsd.org 2010/03/13 21:45:46 + [ssh-keygen.1] + Certificates are named *-cert.pub, not *_cert.pub; committing a diff + from stevesk@ ok me + - jmc@cvs.openbsd.org 2010/03/13 23:38:13 + [ssh-keygen.1] + fix a formatting error (args need quoted); noted by stevesk + - stevesk@cvs.openbsd.org 2010/03/15 19:40:02 + [key.c key.h ssh-keygen.c] + also print certificate type (user or host) for ssh-keygen -L + ok djm kettenis + - stevesk@cvs.openbsd.org 2010/03/16 15:46:52 + [auth-options.c] + spelling in error message. ok djm kettenis + - djm@cvs.openbsd.org 2010/03/16 16:36:49 + [version.h] + crank version to openssh-5.5 since we have a few fixes since 5.4; + requested deraadt@ kettenis@ + - (djm) [README contrib/caldera/openssh.spec contrib/redhat/openssh.spec] + [contrib/suse/openssh.spec] Crank version numbers + +20100314 + - (djm) [ssh-pkcs11-helper.c] Move #ifdef to after #defines to fix + compilation failure when !HAVE_DLOPEN. Reported by felix-mindrot + AT fefe.de + - (djm) [Makefile.in] Respecify -lssh after -lopenbsd-compat for + ssh-pkcs11-helper to repair static builds (we do the same for + ssh-keyscan). Reported by felix-mindrot AT fefe.de + +20100312 + - (tim) [Makefile.in] Now that scard is gone, no need to make $(datadir) + - (tim) [Makefile.in] Add missing $(EXEEXT) to install targets. + Patch from Corinna Vinschen. + - (tim) [contrib/cygwin/Makefile] Fix list of documentation files to install + on a Cygwin installation. Patch from Corinna Vinschen. + +20100311 + - (tim) [contrib/suse/openssh.spec] crank version number here too. + report by imorgan AT nas.nasa.gov + +20100309 + - (dtucker) [configure.ac] Use a proper AC_CHECK_DECL for BROKEN_GETADDRINFO + so setting it in CFLAGS correctly skips IPv6 tests. + +20100428 - (djm) OpenBSD CVS Sync - djm@cvs.openbsd.org 2010/03/07 22:16:01 [ssh-keygen.c] diff --git a/crypto/openssh/README b/crypto/openssh/README index 0ecb670..a29f200 100644 --- a/crypto/openssh/README +++ b/crypto/openssh/README @@ -1,4 +1,4 @@ -See http://www.openssh.com/txt/release-5.4 for the release notes. +See http://www.openssh.com/txt/release-5.5 for the release notes. - A Japanese translation of this document and of the OpenSSH FAQ is - available at http://www.unixuser.org/~haruyama/security/openssh/index.html @@ -62,4 +62,4 @@ References - [6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9 [7] http://www.openssh.com/faq.html -$Id: README,v 1.72 2010/03/07 22:41:02 djm Exp $ +$Id: README,v 1.73 2010/03/21 19:11:55 djm Exp $ diff --git a/crypto/openssh/auth-options.c b/crypto/openssh/auth-options.c index 1293017..69b314f 100644 --- a/crypto/openssh/auth-options.c +++ b/crypto/openssh/auth-options.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-options.c,v 1.48 2010/03/07 11:57:13 dtucker Exp $ */ +/* $OpenBSD: auth-options.c,v 1.49 2010/03/16 15:46:52 stevesk Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -434,7 +434,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw) goto out; } if (strlen(command) != clen) { - error("force-command constrain contains \\0"); + error("force-command constraint contains \\0"); goto out; } if (cert_forced_command != NULL) { @@ -454,7 +454,7 @@ auth_cert_constraints(Buffer *c_orig, struct passwd *pw) goto out; } if (strlen(allowed) != clen) { - error("source-address constrain contains \\0"); + error("source-address constraint contains \\0"); goto out; } if (cert_source_address_done++) { diff --git a/crypto/openssh/auth2-pubkey.c b/crypto/openssh/auth2-pubkey.c index 51aa774..c4cadf4 100644 --- a/crypto/openssh/auth2-pubkey.c +++ b/crypto/openssh/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.21 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.22 2010/03/10 23:27:17 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -240,22 +240,26 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) continue; if (!key_equal(found, key->cert->signature_key)) continue; - debug("matching CA found: file %s, line %lu", - file, linenum); fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); - verbose("Found matching %s CA: %s", - key_type(found), fp); - xfree(fp); + debug("matching CA found: file %s, line %lu, %s %s", + file, linenum, key_type(found), fp); if (key_cert_check_authority(key, 0, 0, pw->pw_name, &reason) != 0) { + xfree(fp); error("%s", reason); auth_debug_add("%s", reason); continue; } if (auth_cert_constraints(&key->cert->constraints, - pw) != 0) + pw) != 0) { + xfree(fp); continue; + } + verbose("Accepted certificate ID \"%s\" " + "signed by %s CA %s via %s", key->cert->key_id, + key_type(found), fp, file); + xfree(fp); found_key = 1; break; } else if (!key_is_cert_authority && key_equal(found, key)) { @@ -281,15 +285,15 @@ user_key_allowed2(struct passwd *pw, Key *key, char *file) static int user_cert_trusted_ca(struct passwd *pw, Key *key) { - char *key_fp, *ca_fp; + char *ca_fp; const char *reason; int ret = 0; if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL) return 0; - key_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - ca_fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + ca_fp = key_fingerprint(key->cert->signature_key, + SSH_FP_MD5, SSH_FP_HEX); if (key_in_file(key->cert->signature_key, options.trusted_user_ca_keys, 1) != 1) { @@ -306,13 +310,12 @@ user_cert_trusted_ca(struct passwd *pw, Key *key) if (auth_cert_constraints(&key->cert->constraints, pw) != 0) goto out; - verbose("%s certificate %s allowed by trusted %s key %s", - key_type(key), key_fp, key_type(key->cert->signature_key), ca_fp); + verbose("Accepted certificate ID \"%s\" signed by %s CA %s via %s", + key->cert->key_id, key_type(key->cert->signature_key), ca_fp, + options.trusted_user_ca_keys); ret = 1; out: - if (key_fp != NULL) - xfree(key_fp); if (ca_fp != NULL) xfree(ca_fp); return ret; diff --git a/crypto/openssh/channels.c b/crypto/openssh/channels.c index d8c53a4..a55d278 100644 --- a/crypto/openssh/channels.c +++ b/crypto/openssh/channels.c @@ -3252,7 +3252,11 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock < 0) { - if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) { + if ((errno != EINVAL) && (errno != EAFNOSUPPORT) +#ifdef EPFNOSUPPORT + && (errno != EPFNOSUPPORT) +#endif + ) { error("socket: %.100s", strerror(errno)); freeaddrinfo(aitop); return -1; diff --git a/crypto/openssh/clientloop.c b/crypto/openssh/clientloop.c index 6ffef95..9ab56b4 100644 --- a/crypto/openssh/clientloop.c +++ b/crypto/openssh/clientloop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clientloop.c,v 1.218 2010/01/28 00:21:18 djm Exp $ */ +/* $OpenBSD: clientloop.c,v 1.219 2010/03/13 21:10:38 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -1484,6 +1484,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) packet_start(SSH2_MSG_DISCONNECT); packet_put_int(SSH2_DISCONNECT_BY_APPLICATION); packet_put_cstring("disconnected by user"); + packet_put_cstring(""); /* language tag */ packet_send(); packet_write_wait(); } diff --git a/crypto/openssh/config.h b/crypto/openssh/config.h index 66e3c7a..01fc523 100644 --- a/crypto/openssh/config.h +++ b/crypto/openssh/config.h @@ -124,7 +124,7 @@ #define DISABLE_WTMPX 1 /* Enable for PKCS#11 support */ -#define ENABLE_PKCS11 +#define ENABLE_PKCS11 /**/ /* Builtin PRNG command timeout */ #define ENTROPY_TIMEOUT_MSEC 200 @@ -456,6 +456,9 @@ /* Define to 1 if you have the `getutxline' function. */ #define HAVE_GETUTXLINE 1 +/* Define to 1 if you have the `getutxuser' function. */ +#define HAVE_GETUTXUSER 1 + /* Define to 1 if you have the `get_default_context_with_level' function. */ /* #undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL */ @@ -552,6 +555,9 @@ /* Define if system has libiaf that supports set_id */ /* #undef HAVE_LIBIAF */ +/* Define to 1 if you have the `network' library (-lnetwork). */ +/* #undef HAVE_LIBNETWORK */ + /* Define to 1 if you have the `nsl' library (-lnsl). */ /* #undef HAVE_LIBNSL */ @@ -805,6 +811,9 @@ /* Define to 1 if you have the `setutent' function. */ /* #undef HAVE_SETUTENT */ +/* Define to 1 if you have the `setutxdb' function. */ +#define HAVE_SETUTXDB 1 + /* Define to 1 if you have the `setutxent' function. */ #define HAVE_SETUTXENT 1 @@ -1416,8 +1425,8 @@ /* Define if you want SELinux support. */ /* #undef WITH_SELINUX */ -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ #if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 #elif ! defined __LITTLE_ENDIAN__ diff --git a/crypto/openssh/config.h.in b/crypto/openssh/config.h.in index a61dec6..a43ad57 100644 --- a/crypto/openssh/config.h.in +++ b/crypto/openssh/config.h.in @@ -80,9 +80,6 @@ /* Define if you want to specify the path to your lastlog file */ #undef CONF_LASTLOG_FILE -/* Define if you want to specify the path to your utmpx file */ -#undef CONF_UTMPX_FILE - /* Define if you want to specify the path to your utmp file */ #undef CONF_UTMP_FILE @@ -455,6 +452,9 @@ /* Define to 1 if you have the `getutxline' function. */ #undef HAVE_GETUTXLINE +/* Define to 1 if you have the `getutxuser' function. */ +#undef HAVE_GETUTXUSER + /* Define to 1 if you have the `get_default_context_with_level' function. */ #undef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL @@ -551,6 +551,9 @@ /* Define if system has libiaf that supports set_id */ #undef HAVE_LIBIAF +/* Define to 1 if you have the `network' library (-lnetwork). */ +#undef HAVE_LIBNETWORK + /* Define to 1 if you have the `nsl' library (-lnsl). */ #undef HAVE_LIBNSL @@ -804,6 +807,9 @@ /* Define to 1 if you have the `setutent' function. */ #undef HAVE_SETUTENT +/* Define to 1 if you have the `setutxdb' function. */ +#undef HAVE_SETUTXDB + /* Define to 1 if you have the `setutxent' function. */ #undef HAVE_SETUTXENT diff --git a/crypto/openssh/defines.h b/crypto/openssh/defines.h index e592249..fe25170 100644 --- a/crypto/openssh/defines.h +++ b/crypto/openssh/defines.h @@ -25,7 +25,7 @@ #ifndef _DEFINES_H #define _DEFINES_H -/* $Id: defines.h,v 1.159 2010/01/13 23:44:34 tim Exp $ */ +/* $Id: defines.h,v 1.160 2010/04/09 08:13:27 dtucker Exp $ */ /* Constants */ diff --git a/crypto/openssh/key.c b/crypto/openssh/key.c index 0d0c912..66592c7 100644 --- a/crypto/openssh/key.c +++ b/crypto/openssh/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.85 2010/03/04 01:44:57 djm Exp $ */ +/* $OpenBSD: key.c,v 1.86 2010/03/15 19:40:02 stevesk Exp $ */ /* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -802,6 +802,19 @@ key_type(const Key *k) } const char * +key_cert_type(const Key *k) +{ + switch (k->cert->type) { + case SSH2_CERT_TYPE_USER: + return "user"; + case SSH2_CERT_TYPE_HOST: + return "host"; + default: + return "unknown"; + } +} + +const char * key_ssh_name(const Key *k) { switch (k->type) { diff --git a/crypto/openssh/key.h b/crypto/openssh/key.h index 6a2e049..4f17777 100644 --- a/crypto/openssh/key.h +++ b/crypto/openssh/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.28 2010/02/26 20:29:54 djm Exp $ */ +/* $OpenBSD: key.h,v 1.29 2010/03/15 19:40:02 stevesk Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -82,6 +82,7 @@ int key_equal(const Key *, const Key *); char *key_fingerprint(Key *, enum fp_type, enum fp_rep); u_char *key_fingerprint_raw(Key *, enum fp_type, u_int *); const char *key_type(const Key *); +const char *key_cert_type(const Key *); int key_write(const Key *, FILE *); int key_read(Key *, char **); u_int key_size(const Key *); diff --git a/crypto/openssh/loginrec.c b/crypto/openssh/loginrec.c index e6eaf0b..62962ac 100644 --- a/crypto/openssh/loginrec.c +++ b/crypto/openssh/loginrec.c @@ -510,6 +510,10 @@ getlast_entry(struct logininfo *li) #ifdef USE_LASTLOG return(lastlog_get_entry(li)); #else /* !USE_LASTLOG */ +#if defined(USE_UTMPX) && defined(HAVE_SETUTXDB) && \ + defined(UTXDB_LASTLOGIN) && defined(HAVE_GETUTXUSER) + return (utmpx_get_entry(li)); +#endif #if 1 return (utmpx_get_entry(li)); @@ -1614,7 +1618,8 @@ lastlog_get_entry(struct logininfo *li) #endif /* HAVE_GETLASTLOGXBYNAME */ #endif /* USE_LASTLOG */ -#if 1 +#if defined(USE_UTMPX) && defined(HAVE_SETUTXDB) && \ + defined(UTXDB_LASTLOGIN) && defined(HAVE_GETUTXUSER) int utmpx_get_entry(struct logininfo *li) { @@ -1637,7 +1642,7 @@ utmpx_get_entry(struct logininfo *li) endutxent(); return (1); } -#endif +#endif /* USE_UTMPX && HAVE_SETUTXDB && UTXDB_LASTLOGIN && HAVE_GETUTXUSER */ #ifdef USE_BTMP /* diff --git a/crypto/openssh/logintest.c b/crypto/openssh/logintest.c index 7e9fbbf..4897ae0 100644 --- a/crypto/openssh/logintest.c +++ b/crypto/openssh/logintest.c @@ -264,7 +264,7 @@ showOptions(void) printf("\tUSE_UTMP (UTMP_FILE=%s)\n", UTMP_FILE); #endif #ifdef USE_UTMPX - printf("\tUSE_UTMPX (UTMPX_FILE=%s)\n", UTMPX_FILE); + printf("\tUSE_UTMPX\n"); #endif #ifdef USE_WTMP printf("\tUSE_WTMP (WTMP_FILE=%s)\n", WTMP_FILE); diff --git a/crypto/openssh/openbsd-compat/bsd-arc4random.c b/crypto/openssh/openbsd-compat/bsd-arc4random.c index 9d4c869..d7c5862 100644 --- a/crypto/openssh/openbsd-compat/bsd-arc4random.c +++ b/crypto/openssh/openbsd-compat/bsd-arc4random.c @@ -84,7 +84,7 @@ arc4random_stir(void) } #endif /* !HAVE_ARC4RANDOM */ -#ifndef ARC4RANDOM_BUF +#ifndef HAVE_ARC4RANDOM_BUF void arc4random_buf(void *_buf, size_t n) { @@ -102,7 +102,7 @@ arc4random_buf(void *_buf, size_t n) } #endif /* !HAVE_ARC4RANDOM_BUF */ -#ifndef ARC4RANDOM_UNIFORM +#ifndef HAVE_ARC4RANDOM_UNIFORM /* * Calculate a uniformly distributed random number less than upper_bound * avoiding "modulo bias". diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index 603c586..626f38c 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.204 2010/03/04 10:36:03 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.207 2010/03/25 23:38:28 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -474,15 +474,14 @@ parse_token(const char *cp, const char *filename, char * derelativise_path(const char *path) { - char *expanded, *ret, *cwd; + char *expanded, *ret, cwd[MAXPATHLEN]; expanded = tilde_expand_filename(path, getuid()); if (*expanded == '/') return expanded; - if ((cwd = getcwd(NULL, 0)) == NULL) + if (getcwd(cwd, sizeof(cwd)) == NULL) fatal("%s: getcwd: %s", __func__, strerror(errno)); xasprintf(&ret, "%s/%s", cwd, expanded); - xfree(cwd); xfree(expanded); return ret; } @@ -1227,7 +1226,17 @@ process_server_config_line(ServerOptions *options, char *line, charptr = (opcode == sAuthorizedKeysFile) ? &options->authorized_keys_file : &options->authorized_keys_file2; - goto parse_filename; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing file name.", + filename, linenum); + if (*activep && *charptr == NULL) { + *charptr = tilde_expand_filename(arg, getuid()); + /* increase optional counter */ + if (intptr != NULL) + *intptr = *intptr + 1; + } + break; case sClientAliveInterval: intptr = &options->client_alive_interval; diff --git a/crypto/openssh/session.c b/crypto/openssh/session.c index aad0979..c11a68a 100644 --- a/crypto/openssh/session.c +++ b/crypto/openssh/session.c @@ -1581,6 +1581,10 @@ do_setusercontext(struct passwd *pw) } #endif /* HAVE_SETPCRED */ +#ifdef WITH_SELINUX + ssh_selinux_setup_exec_context(pw->pw_name); +#endif + if (options.chroot_directory != NULL && strcasecmp(options.chroot_directory, "none") != 0) { tmp = tilde_expand_filename(options.chroot_directory, @@ -1605,10 +1609,6 @@ do_setusercontext(struct passwd *pw) if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) fatal("Failed to set uids to %u.", (u_int) pw->pw_uid); - -#ifdef WITH_SELINUX - ssh_selinux_setup_exec_context(pw->pw_name); -#endif } static void diff --git a/crypto/openssh/ssh-keygen.1 b/crypto/openssh/ssh-keygen.1 index 0da6354..6931842 100644 --- a/crypto/openssh/ssh-keygen.1 +++ b/crypto/openssh/ssh-keygen.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ssh-keygen.1,v 1.88 2010/03/08 00:28:55 djm Exp $ +.\" $OpenBSD: ssh-keygen.1,v 1.92 2010/03/13 23:38:13 jmc Exp $ .\" $FreeBSD$ .\" .\" -*- nroff -*- @@ -38,7 +38,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 8 2010 +.Dd March 13 2010 .Dt SSH-KEYGEN 1 .Os .Sh NAME @@ -308,8 +308,15 @@ Please see the section for details. The constraints that are valid for user certificates are: .Bl -tag -width Ds -.It Ic no-x11-forwarding -Disable X11 forwarding (permitted by default). +.It Ic clear +Clear all enabled permissions. +This is useful for clearing the default set of permissions so permissions may +be added individually. +.It Ic force-command Ns = Ns Ar command +Forces the execution of +.Ar command +instead of any shell or command specified by the user when +the certificate is used for authentication. .It Ic no-agent-forwarding Disable .Xr ssh-agent 1 @@ -324,12 +331,8 @@ Disable execution of by .Xr sshd 8 (permitted by default). -.It Ic clear -Clear all enabled permissions. -This is useful for clearing the default set of permissions so permissions may -be added individually. -.It Ic permit-x11-forwarding -Allows X11 forwarding. +.It Ic no-x11-forwarding +Disable X11 forwarding (permitted by default). .It Ic permit-agent-forwarding Allows .Xr ssh-agent 1 @@ -343,14 +346,10 @@ Allows execution of .Pa ~/.ssh/rc by .Xr sshd 8 . -.It Ic force-command=command -Forces the execution of -.Ar command -instead of any shell or command specified by the user when -the certificate is used for authentication. -.It Ic source-address=address_list -Restrict the source addresses from which the certificate is considered valid -from. +.It Ic permit-x11-forwarding +Allows X11 forwarding. +.It Ic source-address Ns = Ns Ar address_list +Restrict the source addresses from which the certificate is considered valid. The .Ar address_list is a comma-separated list of one or more address/netmask pairs in CIDR @@ -415,7 +414,7 @@ in YYYYMMDDHHMMSS format or a relative time (to the current time) consisting of a minus sign followed by a relative time in the format described in the .Sx TIME FORMATS section of -.Xr ssh_config 5 . +.Xr sshd_config 5 . The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMMSS time or a relative time starting with a plus character. .Pp @@ -520,7 +519,7 @@ To generate a user certificate: .Dl $ ssh-keygen -s /path/to/ca_key -I key_id /path/to/user_key.pub .Pp The resultant certificate will be placed in -.Pa /path/to/user_key_cert.pub . +.Pa /path/to/user_key-cert.pub . A host certificate requires the .Fl h option: @@ -528,7 +527,7 @@ option: .Dl $ ssh-keygen -s /path/to/ca_key -I key_id -h /path/to/host_key.pub .Pp The host certificate will be output to -.Pa /path/to/host_key_cert.pub . +.Pa /path/to/host_key-cert.pub . In both cases, .Ar key_id is a "key identifier" that is logged by the server when the certificate @@ -540,7 +539,7 @@ By default, generated certificates are valid for all users or hosts. To generate a certificate for a specified set of principals: .Pp .Dl $ ssh-keygen -s ca_key -I key_id -n user1,user2 user_key.pub -.Dl $ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub +.Dl "$ ssh-keygen -s ca_key -I key_id -h -n host.domain user_key.pub" .Pp Additional limitations on the validity and use of user certificates may be specified through certificate constraints. diff --git a/crypto/openssh/ssh-keygen.c b/crypto/openssh/ssh-keygen.c index dd662c9..37e516f 100644 --- a/crypto/openssh/ssh-keygen.c +++ b/crypto/openssh/ssh-keygen.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.184 2010/03/07 22:16:01 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.185 2010/03/15 19:40:02 stevesk Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -1393,7 +1393,8 @@ do_show_cert(struct passwd *pw) SSH_FP_MD5, SSH_FP_HEX); printf("%s:\n", identity_file); - printf(" %s certificate %s\n", key_type(key), key_fp); + printf(" %s %s certificate %s\n", key_type(key), + key_cert_type(key), key_fp); printf(" Signed by %s CA %s\n", key_type(key->cert->signature_key), ca_fp); printf(" Key ID \"%s\"\n", key->cert->key_id); diff --git a/crypto/openssh/ssh-pkcs11-helper.c b/crypto/openssh/ssh-pkcs11-helper.c index d3bfb98..8e3f57a 100644 --- a/crypto/openssh/ssh-pkcs11-helper.c +++ b/crypto/openssh/ssh-pkcs11-helper.c @@ -17,8 +17,6 @@ #include "includes.h" -#ifdef ENABLE_PKCS11 - #include #ifdef HAVE_SYS_TIME_H # include @@ -39,6 +37,8 @@ #include "authfd.h" #include "ssh-pkcs11.h" +#ifdef ENABLE_PKCS11 + /* borrows code from sftp-server and ssh-agent */ struct pkcs11_keyinfo { diff --git a/crypto/openssh/ssh.1 b/crypto/openssh/ssh.1 index e3a826e..80f8d8c 100644 --- a/crypto/openssh/ssh.1 +++ b/crypto/openssh/ssh.1 @@ -34,9 +34,9 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh.1,v 1.302 2010/03/05 10:28:21 djm Exp $ +.\" $OpenBSD: ssh.1,v 1.303 2010/03/26 00:26:58 djm Exp $ .\" $FreeBSD$ -.Dd March 5 2010 +.Dd March 26 2010 .Dt SSH 1 .Os .Sh NAME @@ -560,7 +560,10 @@ argument is the listen port will be dynamically allocated on the server and reported to the client at run time. .It Fl S Ar ctl_path -Specifies the location of a control socket for connection sharing. +Specifies the location of a control socket for connection sharing +or the string +.Dq none +to disable connection sharing. Refer to the description of .Cm ControlPath and diff --git a/crypto/openssh/ssh_config b/crypto/openssh/ssh_config index 1edf164..3bda1b9 100644 --- a/crypto/openssh/ssh_config +++ b/crypto/openssh/ssh_config @@ -46,4 +46,4 @@ # PermitLocalCommand no # VisualHostKey no # ProxyCommand ssh -q -W %h:%p gateway.example.com -# VersionAddendum FreeBSD-20100308 +# VersionAddendum FreeBSD-20100428 diff --git a/crypto/openssh/ssh_config.5 b/crypto/openssh/ssh_config.5 index 0f67fdc..88afdad 100644 --- a/crypto/openssh/ssh_config.5 +++ b/crypto/openssh/ssh_config.5 @@ -34,9 +34,9 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: ssh_config.5,v 1.129 2010/03/05 10:28:21 djm Exp $ +.\" $OpenBSD: ssh_config.5,v 1.130 2010/03/26 01:06:13 dtucker Exp $ .\" $FreeBSD$ -.Dd March 5 2010 +.Dd March 26 2010 .Dt SSH_CONFIG 5 .Os .Sh NAME @@ -735,11 +735,7 @@ This allows a client to prefer one method (e.g.\& over another method (e.g.\& .Cm password ) The default for this option is: -.Do gssapi-with-mic , -hostbased, -publickey, -keyboard-interactive, -password +.Do gssapi-with-mic,hostbased,publickey,keyboard-interactive,password .Dc . .It Cm Protocol Specifies the protocol versions @@ -1087,7 +1083,7 @@ in Specifies a string to append to the regular version string to identify OS- or site-specific modifications. The default is -.Dq FreeBSD-20100308 . +.Dq FreeBSD-20100428 . .It Cm VisualHostKey If this flag is set to .Dq yes , diff --git a/crypto/openssh/sshd_config b/crypto/openssh/sshd_config index 44b7582..3c700f0 100644 --- a/crypto/openssh/sshd_config +++ b/crypto/openssh/sshd_config @@ -14,7 +14,7 @@ # Note that some of FreeBSD's defaults differ from OpenBSD's, and # FreeBSD has a few additional options. -#VersionAddendum FreeBSD-20100308 +#VersionAddendum FreeBSD-20100428 #Port 22 #AddressFamily any diff --git a/crypto/openssh/sshd_config.5 b/crypto/openssh/sshd_config.5 index d0d3053..bd667d7 100644 --- a/crypto/openssh/sshd_config.5 +++ b/crypto/openssh/sshd_config.5 @@ -988,7 +988,7 @@ The default is Specifies a string to append to the regular version string to identify OS- or site-specific modifications. The default is -.Dq FreeBSD-20100308 . +.Dq FreeBSD-20100428 . .It Cm X11DisplayOffset Specifies the first display number available for .Xr sshd 8 Ns 's diff --git a/crypto/openssh/version.h b/crypto/openssh/version.h index d1d1452..6cc8d84 100644 --- a/crypto/openssh/version.h +++ b/crypto/openssh/version.h @@ -1,12 +1,12 @@ -/* $OpenBSD: version.h,v 1.57 2010/03/07 22:01:32 djm Exp $ */ +/* $OpenBSD: version.h,v 1.58 2010/03/16 16:36:49 djm Exp $ */ /* $FreeBSD$ */ #ifndef SSH_VERSION #define SSH_VERSION (ssh_version_get()) #define SSH_RELEASE (ssh_version_get()) -#define SSH_VERSION_BASE "OpenSSH_5.4p1" -#define SSH_VERSION_ADDENDUM "FreeBSD-20100308" +#define SSH_VERSION_BASE "OpenSSH_5.5p1" +#define SSH_VERSION_ADDENDUM "FreeBSD-20100428" const char *ssh_version_get(void); void ssh_version_set_addendum(const char *); -- cgit v1.1 From b7327995decf94e0a514d2e00db749b9df3edaa7 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Wed, 28 Apr 2010 10:57:27 +0000 Subject: Fix typos. Obtained from: DragonFlyBSD --- sbin/ifconfig/ifconfig.8 | 4 ++-- sbin/ifconfig/ifieee80211.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index eafd5d8..e26cbda 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -1163,9 +1163,9 @@ In particular the information elements included in management frames for old devices are different. When compatibility support is enabled both standard and compatible data will be provided. -Stations that associate using the compatiblity mechanisms are flagged +Stations that associate using the compatibility mechanisms are flagged in ``list sta''. -To disable compatiblity support use +To disable compatibility support use .Fl htcompat . .It Cm htprotmode Ar technique For interfaces operating in 802.11n, use the specified diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c index 6cb4d2c..6ec45ff 100644 --- a/sbin/ifconfig/ifieee80211.c +++ b/sbin/ifconfig/ifieee80211.c @@ -5027,7 +5027,7 @@ DECL_CMD_FUNC(set80211clone_wlanaddr, arg, d) ea = ether_aton(arg); if (ea == NULL) - errx(1, "%s: cannot parse addres", arg); + errx(1, "%s: cannot parse address", arg); memcpy(params.icp_macaddr, ea->octet, IEEE80211_ADDR_LEN); params.icp_flags |= IEEE80211_CLONE_MACADDR; } -- cgit v1.1 From ee8ca6996ca971eb6a46e10b00e39d48cd9ea964 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Wed, 28 Apr 2010 10:58:03 +0000 Subject: Bump man page date. --- sbin/ifconfig/ifconfig.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8 index e26cbda..65c240f 100644 --- a/sbin/ifconfig/ifconfig.8 +++ b/sbin/ifconfig/ifconfig.8 @@ -28,7 +28,7 @@ .\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94 .\" $FreeBSD$ .\" -.Dd February 20, 2010 +.Dd April 28, 2010 .Dt IFCONFIG 8 .Os .Sh NAME -- cgit v1.1 From 1a94039c1d3ea9f070566c69dca986e9eb17fe80 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Wed, 28 Apr 2010 10:58:50 +0000 Subject: Fix typo. No functional change. Obtained from: DragonFlyBSD --- sys/net80211/ieee80211_node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c index b17f42f..992ea0f 100644 --- a/sys/net80211/ieee80211_node.c +++ b/sys/net80211/ieee80211_node.c @@ -432,7 +432,7 @@ ieee80211_reset_bss(struct ieee80211vap *vap) ieee80211_reset_erp(ic); ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr); - KASSERT(ni != NULL, ("unable to setup inital BSS node")); + KASSERT(ni != NULL, ("unable to setup initial BSS node")); obss = vap->iv_bss; vap->iv_bss = ieee80211_ref_node(ni); if (obss != NULL) { -- cgit v1.1 From 98a310d9040e0dd2ab621b3b91d6402d28491075 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Wed, 28 Apr 2010 13:25:53 +0000 Subject: When in the RUN -> AUTH -> RUN FSM transition happens, we'll call the ratectl_node_init() functions and since ni_rtctls was already malloc'ed() we will panic. Fix this by using the already malloc'ed pointer. Found by: bschmidt Reviewed by: bschmidt --- sys/net80211/ieee80211_amrr.c | 20 ++++++++++---------- sys/net80211/ieee80211_rssadapt.c | 18 +++++++++++------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/sys/net80211/ieee80211_amrr.c b/sys/net80211/ieee80211_amrr.c index 6111058..7902545 100644 --- a/sys/net80211/ieee80211_amrr.c +++ b/sys/net80211/ieee80211_amrr.c @@ -136,16 +136,16 @@ amrr_node_init(struct ieee80211_node *ni) struct ieee80211_amrr *amrr = vap->iv_rs; struct ieee80211_amrr_node *amn; - KASSERT(ni->ni_rctls == NULL, ("%s: ni_rctls already initialized", - __func__)); - - ni->ni_rctls = amn = malloc(sizeof(struct ieee80211_amrr_node), - M_80211_RATECTL, M_NOWAIT|M_ZERO); - if (amn == NULL) { - if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl " - "structure\n"); - return; - } + if (ni->ni_rctls == NULL) { + ni->ni_rctls = amn = malloc(sizeof(struct ieee80211_amrr_node), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (amn == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl " + "structure\n"); + return; + } + } else + amn = ni->ni_rctls; amn->amn_amrr = amrr; amn->amn_success = 0; amn->amn_recovery = 0; diff --git a/sys/net80211/ieee80211_rssadapt.c b/sys/net80211/ieee80211_rssadapt.c index ad329e0..f82c01e 100644 --- a/sys/net80211/ieee80211_rssadapt.c +++ b/sys/net80211/ieee80211_rssadapt.c @@ -169,13 +169,17 @@ rssadapt_node_init(struct ieee80211_node *ni) struct ieee80211_rssadapt *rsa = vap->iv_rs; const struct ieee80211_rateset *rs = &ni->ni_rates; - ni->ni_rctls = ra = malloc(sizeof(struct ieee80211_rssadapt_node), - M_80211_RATECTL, M_NOWAIT|M_ZERO); - if (ra == NULL) { - if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl " - "structure\n"); - return; - } + if (ni->ni_rctls == NULL) { + ni->ni_rctls = ra = + malloc(sizeof(struct ieee80211_rssadapt_node), + M_80211_RATECTL, M_NOWAIT|M_ZERO); + if (ra == NULL) { + if_printf(vap->iv_ifp, "couldn't alloc per-node ratectl " + "structure\n"); + return; + } + } else + ra = ni->ni_rctls; ra->ra_rs = rsa; ra->ra_rates = *rs; rssadapt_updatestats(ra); -- cgit v1.1 From c10bf61669232d51b99e4d2e5248ed36a141e5c4 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Wed, 28 Apr 2010 13:29:48 +0000 Subject: Couple of fixes from DragonFly (typos). Obtained from: DragonFlyBSD --- share/man/man9/ieee80211.9 | 6 +++--- share/man/man9/ieee80211_node.9 | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/share/man/man9/ieee80211.9 b/share/man/man9/ieee80211.9 index ae92d5e..8fd6e0d 100644 --- a/share/man/man9/ieee80211.9 +++ b/share/man/man9/ieee80211.9 @@ -25,11 +25,11 @@ .\" .\" $FreeBSD$ .\" -.Dd March 29, 2010 -.Dt NET80211 9 +.Dd April 28, 2010 +.Dt IEEE80211 9 .Os .Sh NAME -.Nm net80211 +.Nm IEEE80211 .Nd 802.11 network layer .Sh SYNOPSIS .In net80211/ieee80211_var.h diff --git a/share/man/man9/ieee80211_node.9 b/share/man/man9/ieee80211_node.9 index be0b506..9389411 100644 --- a/share/man/man9/ieee80211_node.9 +++ b/share/man/man9/ieee80211_node.9 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 29, 2010 +.Dd April 28, 2010 .Dt IEEE80211_NODE 9 .Os .Sh NAME @@ -152,7 +152,7 @@ displays the contents of a single node while .Fn ieee80211_dump_nodes displays the contents of the specified node table. Nodes may also be displayed using -.Xr ddb 9 +.Xr ddb 4 with the .Dq show node directive and the station node table can be displayed with -- cgit v1.1 From 8b879379b5d5a5746905003923f9b5a269988650 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Wed, 28 Apr 2010 13:42:13 +0000 Subject: Add ic_rxstream and ic_txstream. These variables hold the number of RX streams and the number of TX streams respectively. Obtained from: //depot/user/rpaulo/80211n/... Sponsored by: iXsystems, inc. --- sys/net80211/ieee80211_var.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index ff3694f..eea8dbe 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -213,6 +213,8 @@ struct ieee80211com { enum ieee80211_protmode ic_htprotmode; /* HT protection mode */ int ic_lastnonerp; /* last time non-ERP sta noted*/ int ic_lastnonht; /* last time non-HT sta noted */ + uint8_t ic_rxstream; /* # RX streams */ + uint8_t ic_txstream; /* # TX streams */ /* optional state for Atheros SuperG protocol extensions */ struct ieee80211_superg *ic_superg; @@ -315,7 +317,6 @@ struct ieee80211com { void (*ic_ampdu_rx_stop)(struct ieee80211_node *, struct ieee80211_rx_ampdu *); uint64_t ic_spare[7]; - uint32_t ic_spare2; }; struct ieee80211_aclator; -- cgit v1.1 From 60e1354e61b43b340b1c25761d1b3d5fbc35b000 Mon Sep 17 00:00:00 2001 From: rpaulo Date: Wed, 28 Apr 2010 14:59:05 +0000 Subject: Add a private field to struct ieee80211_rx_ampdu do hold driver specific data. Sponsored by: iXsystems, inc --- sys/net80211/ieee80211_ht.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/net80211/ieee80211_ht.h b/sys/net80211/ieee80211_ht.h index 7b0eab7..21e7ff6 100644 --- a/sys/net80211/ieee80211_ht.h +++ b/sys/net80211/ieee80211_ht.h @@ -142,6 +142,7 @@ struct ieee80211_rx_ampdu { int rxa_age; /* age of oldest frame in window */ int rxa_nframes; /* frames since ADDBA */ struct mbuf *rxa_m[IEEE80211_AGGR_BAWMAX]; + void *rxa_private; uint64_t rxa_pad[4]; }; -- cgit v1.1 From 6dfd3f303086ff8e0db146c2e70c33de1a239696 Mon Sep 17 00:00:00 2001 From: attilio Date: Wed, 28 Apr 2010 15:38:01 +0000 Subject: - Extract the IODEV_PIO interface from ia64 and make it MI. In the end, it does help fixing /dev/io usage from multithreaded processes. - On i386 and amd64 the old behaviour is kept but multithreaded processes must use the new interface in order to work well. - Support for the other architectures is greatly improved, where necessary, by the necessity to define very small things now. Manpage update will happen shortly. Sponsored by: Sandvine Incorporated PR: threads/116181 Reviewed by: emaste, marcel MFC after: 3 weeks --- sys/amd64/amd64/io.c | 40 ++---------- sys/amd64/include/iodev.h | 21 +++++- sys/dev/io/iodev.c | 146 +++++++++++++++++++++++++++++++++++++++--- sys/dev/io/iodev.h | 44 +++++++++++++ sys/i386/i386/io.c | 40 ++---------- sys/i386/include/iodev.h | 21 +++++- sys/ia64/ia64/iodev_machdep.c | 104 ++---------------------------- sys/ia64/include/iodev.h | 33 +++++----- 8 files changed, 251 insertions(+), 198 deletions(-) create mode 100644 sys/dev/io/iodev.h diff --git a/sys/amd64/amd64/io.c b/sys/amd64/amd64/io.c index 09d6e89..c2d0d51 100644 --- a/sys/amd64/amd64/io.c +++ b/sys/amd64/amd64/io.c @@ -28,60 +28,32 @@ __FBSDID("$FreeBSD$"); #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include -#include -#include - -#include -#include - #include +#include -/* ARGSUSED */ int -ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_open(struct thread *td) { - int error; - - error = priv_check(td, PRIV_IO); - if (error != 0) - return (error); - error = securelevel_gt(td->td_ucred, 0); - if (error != 0) - return (error); td->td_frame->tf_rflags |= PSL_IOPL; - return (0); } -/* ARGSUSED */ int -ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_close(struct thread *td) { - td->td_frame->tf_rflags &= ~PSL_IOPL; + td->td_frame->tf_rflags &= ~PSL_IOPL; return (0); } /* ARGSUSED */ int -ioioctl(struct cdev *dev __unused, u_long cmd __unused, caddr_t data __unused, - int fflag __unused, struct thread *td __unused) +iodev_ioctl(u_long cmd __unused, caddr_t data __unused) { - return (ENXIO); + return (ENOIOCTL); } diff --git a/sys/amd64/include/iodev.h b/sys/amd64/include/iodev.h index 1a0a17a..9f53cac 100644 --- a/sys/amd64/include/iodev.h +++ b/sys/amd64/include/iodev.h @@ -25,7 +25,22 @@ * * $FreeBSD$ */ +#ifndef _MACHINE_IODEV_H_ +#define _MACHINE_IODEV_H_ -d_open_t ioopen; -d_close_t ioclose; -d_ioctl_t ioioctl; +#ifdef _KERNEL +#include + +#define iodev_read_1 inb +#define iodev_read_2 inw +#define iodev_read_4 inl +#define iodev_write_1 outb +#define iodev_write_2 outw +#define iodev_write_4 outl + +int iodev_open(struct thread *td); +int iodev_close(struct thread *td); +int iodev_ioctl(u_long cmd, caddr_t data); + +#endif /* _KERNEL */ +#endif /* _MACHINE_IODEV_H_ */ diff --git a/sys/dev/io/iodev.c b/sys/dev/io/iodev.c index b142a39..eae69f4 100644 --- a/sys/dev/io/iodev.c +++ b/sys/dev/io/iodev.c @@ -30,22 +30,27 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include -#include -#include +#include #include -#include +#include #include -#include #include -#include - -#include -#include #include +#include + +static int ioopen(struct cdev *dev, int flags, int fmt, + struct thread *td); +static int ioclose(struct cdev *dev, int flags, int fmt, + struct thread *td); +static int ioioctl(struct cdev *dev, u_long cmd, caddr_t data, + int fflag, struct thread *td); + +static int iopio_read(struct iodev_pio_req *req); +static int iopio_write(struct iodev_pio_req *req); + static struct cdev *iodev; static struct cdevsw io_cdevsw = { @@ -58,6 +63,129 @@ static struct cdevsw io_cdevsw = { /* ARGSUSED */ static int +ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, + struct thread *td) +{ + int error; + + error = priv_check(td, PRIV_IO); + if (error != 0) + return (error); + error = securelevel_gt(td->td_ucred, 0); + if (error != 0) + return (error); + error = iodev_open(td); + + return (error); +} + +/* ARGSUSED */ +static int +ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, + struct thread *td) +{ + + return (iodev_close(td)); +} + +/* ARGSUSED */ +static int +ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, + int fflag __unused, struct thread *td __unused) +{ + struct iodev_pio_req *pio_req; + int error; + + switch (cmd) { + case IODEV_PIO: + pio_req = (struct iodev_pio_req *)data; + switch (pio_req->access) { + case IODEV_PIO_READ: + error = iopio_read(pio_req); + break; + case IODEV_PIO_WRITE: + error = iopio_write(pio_req); + break; + default: + error = EINVAL; + break; + } + break; + default: + error = iodev_ioctl(cmd, data); + } + + return (error); +} + +static int +iopio_read(struct iodev_pio_req *req) +{ + + switch (req->width) { + case 1: + req->val = iodev_read_1(req->port); + break; + case 2: + if (req->port & 1) { + req->val = iodev_read_1(req->port); + req->val |= iodev_read_1(req->port + 1) << 8; + } else + req->val = iodev_read_2(req->port); + break; + case 4: + if (req->port & 1) { + req->val = iodev_read_1(req->port); + req->val |= iodev_read_2(req->port + 1) << 8; + req->val |= iodev_read_1(req->port + 3) << 24; + } else if (req->port & 2) { + req->val = iodev_read_2(req->port); + req->val |= iodev_read_2(req->port + 2) << 16; + } else + req->val = iodev_read_4(req->port); + break; + default: + return (EINVAL); + } + + return (0); +} + +static int +iopio_write(struct iodev_pio_req *req) +{ + + switch (req->width) { + case 1: + iodev_write_1(req->port, req->val); + break; + case 2: + if (req->port & 1) { + iodev_write_1(req->port, req->val); + iodev_write_1(req->port + 1, req->val >> 8); + } else + iodev_write_2(req->port, req->val); + break; + case 4: + if (req->port & 1) { + iodev_write_1(req->port, req->val); + iodev_write_2(req->port + 1, req->val >> 8); + iodev_write_1(req->port + 3, req->val >> 24); + } else if (req->port & 2) { + iodev_write_2(req->port, req->val); + iodev_write_2(req->port + 2, req->val >> 16); + } else + iodev_write_4(req->port, req->val); + break; + default: + return (EINVAL); + } + + return (0); +} + +/* ARGSUSED */ +static int io_modevent(module_t mod __unused, int type, void *data __unused) { switch(type) { diff --git a/sys/dev/io/iodev.h b/sys/dev/io/iodev.h new file mode 100644 index 0000000..d040fccc --- /dev/null +++ b/sys/dev/io/iodev.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2010 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _DEV_IODEV_H_ +#define _DEV_IODEV_H_ + +#define IODEV_PIO_READ 0 +#define IODEV_PIO_WRITE 1 + +struct iodev_pio_req { + u_int access; + u_int port; + u_int width; + u_int val; +}; + +#define IODEV_PIO _IOWR('I', 0, struct iodev_pio_req) + +#endif /* _DEV_IODEV_H_ */ diff --git a/sys/i386/i386/io.c b/sys/i386/i386/io.c index c392af5..152f6b1 100644 --- a/sys/i386/i386/io.c +++ b/sys/i386/i386/io.c @@ -28,60 +28,32 @@ __FBSDID("$FreeBSD$"); #include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include -#include -#include - -#include -#include - #include +#include -/* ARGSUSED */ int -ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_open(struct thread *td) { - int error; - - error = priv_check(td, PRIV_IO); - if (error != 0) - return (error); - error = securelevel_gt(td->td_ucred, 0); - if (error != 0) - return (error); td->td_frame->tf_eflags |= PSL_IOPL; - return (0); } -/* ARGSUSED */ int -ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_close(struct thread *td) { - td->td_frame->tf_eflags &= ~PSL_IOPL; + td->td_frame->tf_eflags &= ~PSL_IOPL; return (0); } /* ARGSUSED */ int -ioioctl(struct cdev *dev __unused, u_long cmd __unused, caddr_t data __unused, - int fflag __unused, struct thread *td __unused) +iodev_ioctl(u_long cmd __unused, caddr_t data __unused) { - return (ENXIO); + return (ENOIOCTL); } diff --git a/sys/i386/include/iodev.h b/sys/i386/include/iodev.h index 1a0a17a..9f53cac 100644 --- a/sys/i386/include/iodev.h +++ b/sys/i386/include/iodev.h @@ -25,7 +25,22 @@ * * $FreeBSD$ */ +#ifndef _MACHINE_IODEV_H_ +#define _MACHINE_IODEV_H_ -d_open_t ioopen; -d_close_t ioclose; -d_ioctl_t ioioctl; +#ifdef _KERNEL +#include + +#define iodev_read_1 inb +#define iodev_read_2 inw +#define iodev_read_4 inl +#define iodev_write_1 outb +#define iodev_write_2 outw +#define iodev_write_4 outl + +int iodev_open(struct thread *td); +int iodev_close(struct thread *td); +int iodev_ioctl(u_long cmd, caddr_t data); + +#endif /* _KERNEL */ +#endif /* _MACHINE_IODEV_H_ */ diff --git a/sys/ia64/ia64/iodev_machdep.c b/sys/ia64/ia64/iodev_machdep.c index d255aae..9d9057d 100644 --- a/sys/ia64/ia64/iodev_machdep.c +++ b/sys/ia64/ia64/iodev_machdep.c @@ -40,61 +40,33 @@ __FBSDID("$FreeBSD$"); #include #include -static int iodev_pio_read(struct iodev_pio_req *req); -static int iodev_pio_write(struct iodev_pio_req *req); - static int iodev_efivar_getvar(struct iodev_efivar_req *req); static int iodev_efivar_nextname(struct iodev_efivar_req *req); static int iodev_efivar_setvar(struct iodev_efivar_req *req); /* ARGSUSED */ int -ioopen(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td) +iodev_open(struct thread *td __unused) { - int error; - - error = priv_check(td, PRIV_IO); - if (error == 0) - error = securelevel_gt(td->td_ucred, 0); - return (error); + return (0); } /* ARGSUSED */ int -ioclose(struct cdev *dev __unused, int flags __unused, int fmt __unused, - struct thread *td __unused) +iodev_close(struct thread *td __unused) { return (0); } -/* ARGSUSED */ int -ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, - int fflag __unused, struct thread *td __unused) +iodev_ioctl(u_long cmd, caddr_t data) { struct iodev_efivar_req *efivar_req; - struct iodev_pio_req *pio_req; int error; - error = ENOIOCTL; switch (cmd) { - case IODEV_PIO: - pio_req = (struct iodev_pio_req *)data; - switch (pio_req->access) { - case IODEV_PIO_READ: - error = iodev_pio_read(pio_req); - break; - case IODEV_PIO_WRITE: - error = iodev_pio_write(pio_req); - break; - default: - error = EINVAL; - break; - } - break; case IODEV_EFIVAR: efivar_req = (struct iodev_efivar_req *)data; efivar_req->result = 0; /* So it's well-defined */ @@ -113,75 +85,11 @@ ioioctl(struct cdev *dev __unused, u_long cmd, caddr_t data, break; } break; - } - - return (error); -} - -static int -iodev_pio_read(struct iodev_pio_req *req) -{ - - switch (req->width) { - case 1: - req->val = bus_space_read_io_1(req->port); - break; - case 2: - if (req->port & 1) { - req->val = bus_space_read_io_1(req->port); - req->val |= bus_space_read_io_1(req->port + 1) << 8; - } else - req->val = bus_space_read_io_2(req->port); - break; - case 4: - if (req->port & 1) { - req->val = bus_space_read_io_1(req->port); - req->val |= bus_space_read_io_2(req->port + 1) << 8; - req->val |= bus_space_read_io_1(req->port + 3) << 24; - } else if (req->port & 2) { - req->val = bus_space_read_io_2(req->port); - req->val |= bus_space_read_io_2(req->port + 2) << 16; - } else - req->val = bus_space_read_io_4(req->port); - break; - default: - return (EINVAL); - } - - return (0); -} - -static int -iodev_pio_write(struct iodev_pio_req *req) -{ - - switch (req->width) { - case 1: - bus_space_write_io_1(req->port, req->val); - break; - case 2: - if (req->port & 1) { - bus_space_write_io_1(req->port, req->val); - bus_space_write_io_1(req->port + 1, req->val >> 8); - } else - bus_space_write_io_2(req->port, req->val); - break; - case 4: - if (req->port & 1) { - bus_space_write_io_1(req->port, req->val); - bus_space_write_io_2(req->port + 1, req->val >> 8); - bus_space_write_io_1(req->port + 3, req->val >> 24); - } else if (req->port & 2) { - bus_space_write_io_2(req->port, req->val); - bus_space_write_io_2(req->port + 2, req->val >> 16); - } else - bus_space_write_io_4(req->port, req->val); - break; default: - return (EINVAL); + error = ENOIOCTL; } - return (0); + return (error); } static int diff --git a/sys/ia64/include/iodev.h b/sys/ia64/include/iodev.h index 6d2ae19..cf349d9 100644 --- a/sys/ia64/include/iodev.h +++ b/sys/ia64/include/iodev.h @@ -31,22 +31,16 @@ #include -struct iodev_pio_req { - u_int access; -#define IODEV_PIO_READ 0 -#define IODEV_PIO_WRITE 1 - u_int port; - u_int width; - u_int val; -}; - -#define IODEV_PIO _IOWR('I', 0, struct iodev_pio_req) +#ifdef _KERNEL +#include +#endif -struct iodev_efivar_req { - u_int access; #define IODEV_EFIVAR_GETVAR 0 #define IODEV_EFIVAR_NEXTNAME 1 #define IODEV_EFIVAR_SETVAR 2 + +struct iodev_efivar_req { + u_int access; u_int result; /* errno value */ size_t namesize; u_short *name; /* UCS-2 */ @@ -59,11 +53,16 @@ struct iodev_efivar_req { #define IODEV_EFIVAR _IOWR('I', 1, struct iodev_efivar_req) #ifdef _KERNEL +#define iodev_read_1 bus_space_read_io_1 +#define iodev_read_2 bus_space_read_io_2 +#define iodev_read_4 bus_space_read_io_4 +#define iodev_write_1 bus_space_write_io_1 +#define iodev_write_2 bus_space_write_io_2 +#define iodev_write_4 bus_space_write_io_4 -d_open_t ioopen; -d_close_t ioclose; -d_ioctl_t ioioctl; - -#endif +int iodev_open(struct thread *td); +int iodev_close(struct thread *td); +int iodev_ioctl(u_long, caddr_t data); +#endif /* _KERNEL */ #endif /* _MACHINE_IODEV_H_ */ -- cgit v1.1 From 1aa9abc305b1f0648f36db49db5a763e21e450d4 Mon Sep 17 00:00:00 2001 From: jkim Date: Wed, 28 Apr 2010 17:26:05 +0000 Subject: Remove dead code. Calculated greatest common divisor was not used at all. On top of that, LLVM+Clang mis-compiles this code because of its register allocator bug. Analyzed by: Andrew Reilly (areilly at bigpond dot net dot au) Reviewed by: ariff, rdivacky MFC after: 3 days --- sys/dev/sound/pcm/buffer.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c index 6e82592..a9053d7 100644 --- a/sys/dev/sound/pcm/buffer.c +++ b/sys/dev/sound/pcm/buffer.c @@ -568,7 +568,6 @@ sndbuf_updateprevtotal(struct snd_dbuf *b) unsigned int snd_xbytes(unsigned int v, unsigned int from, unsigned int to) { - unsigned int w, x, y; if (from == to) return v; @@ -576,16 +575,6 @@ snd_xbytes(unsigned int v, unsigned int from, unsigned int to) if (from == 0 || to == 0 || v == 0) return 0; - x = from; - y = to; - while (y != 0) { - w = x % y; - x = y; - y = w; - } - from /= x; - to /= x; - return (unsigned int)(((u_int64_t)v * to) / from); } -- cgit v1.1 From b727d91e59f7179be035688dd4e922b80a1c3ec7 Mon Sep 17 00:00:00 2001 From: jfv Date: Wed, 28 Apr 2010 17:37:30 +0000 Subject: Change default WOL back to MAGIC only, having multicast enabled causes problems in man environments. --- sys/dev/e1000/if_em.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 1db9012..fcebc02 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -2707,10 +2707,10 @@ em_setup_interface(device_t dev, struct adapter *adapter) ifp->if_capabilities |= IFCAP_POLLING; #endif - /* Enable All WOL methods by default */ + /* Enable only WOL MAGIC by default */ if (adapter->wol) { ifp->if_capabilities |= IFCAP_WOL; - ifp->if_capenable |= IFCAP_WOL; + ifp->if_capenable |= IFCAP_WOL_MAGIC; } /* -- cgit v1.1 From c08f91598386a9a8c862c74f597cb9741b3dd67c Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 28 Apr 2010 18:29:48 +0000 Subject: Backport fix for 'zfs_znode_dmu_init: existing znode for dbuf' panic from OpenSolaris. PR: kern/144402 Reported by: Alex Bakhtin Tested by: Alex Bakhtin Obtained from: OpenSolaris, Bug ID 6895088 MFC after: 3 days --- .../opensolaris/uts/common/fs/zfs/zfs_znode.c | 43 ++++++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c index 900087b..947f9dd 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c @@ -704,6 +704,8 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, DMU_OT_ZNODE, sizeof (znode_phys_t) + bonuslen, tx); } } + + ZFS_OBJ_HOLD_ENTER(zfsvfs, obj); VERIFY(0 == dmu_bonus_hold(zfsvfs->z_os, obj, NULL, &db)); dmu_buf_will_dirty(db, tx); @@ -765,9 +767,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, pzp->zp_mode = MAKEIMODE(vap->va_type, vap->va_mode); if (!(flag & IS_ROOT_NODE)) { - ZFS_OBJ_HOLD_ENTER(zfsvfs, obj); *zpp = zfs_znode_alloc(zfsvfs, db, 0); - ZFS_OBJ_HOLD_EXIT(zfsvfs, obj); } else { /* * If we are creating the root node, the "parent" we @@ -776,6 +776,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr, *zpp = dzp; } zfs_perm_init(*zpp, dzp, flag, vap, tx, cr, setaclp, fuidp); + ZFS_OBJ_HOLD_EXIT(zfsvfs, obj); if (!(flag & IS_ROOT_NODE)) { vnode_t *vp; @@ -939,19 +940,31 @@ again: /* * Not found create new znode/vnode + * but only if file exists. + * + * There is a small window where zfs_vget() could + * find this object while a file create is still in + * progress. Since a gen number can never be zero + * we will check that to determine if its an allocated + * file. */ - zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size); - - vp = ZTOV(zp); - vp->v_vflag |= VV_FORCEINSMQ; - err = insmntque(vp, zfsvfs->z_vfs); - vp->v_vflag &= ~VV_FORCEINSMQ; - KASSERT(err == 0, ("insmntque() failed: error %d", err)); - VOP_UNLOCK(vp, 0); + if (((znode_phys_t *)db->db_data)->zp_gen != 0) { + zp = zfs_znode_alloc(zfsvfs, db, doi.doi_data_block_size); + *zpp = zp; + vp = ZTOV(zp); + vp->v_vflag |= VV_FORCEINSMQ; + err = insmntque(vp, zfsvfs->z_vfs); + vp->v_vflag &= ~VV_FORCEINSMQ; + KASSERT(err == 0, ("insmntque() failed: error %d", err)); + VOP_UNLOCK(vp, 0); + err = 0; + } else { + dmu_buf_rele(db, NULL); + err = ENOENT; + } ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num); - *zpp = zp; - return (0); + return (err); } int @@ -1440,6 +1453,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) uint64_t norm = 0; nvpair_t *elem; int error; + int i; znode_t *rootzp = NULL; vnode_t vnode; vattr_t vattr; @@ -1537,6 +1551,9 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) list_create(&zfsvfs.z_all_znodes, sizeof (znode_t), offsetof(znode_t, z_link_node)); + for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) + mutex_init(&zfsvfs.z_hold_mtx[i], NULL, MUTEX_DEFAULT, NULL); + ASSERT(!POINTER_IS_VALID(rootzp->z_zfsvfs)); rootzp->z_zfsvfs = &zfsvfs; zfs_mknode(rootzp, &vattr, tx, cr, IS_ROOT_NODE, &zp, 0, NULL, NULL); @@ -1547,6 +1564,8 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) dmu_buf_rele(rootzp->z_dbuf, NULL); rootzp->z_dbuf = NULL; + for (i = 0; i != ZFS_OBJ_MTX_SZ; i++) + mutex_destroy(&zfsvfs.z_hold_mtx[i]); mutex_destroy(&zfsvfs.z_znodes_lock); rootzp->z_vnode = NULL; kmem_cache_free(znode_cache, rootzp); -- cgit v1.1 From 5b51584fbcf94586ba465306cb52b8b8b48a6b43 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 28 Apr 2010 18:49:45 +0000 Subject: Initialize the callout structure earlier in attach before calling any routines that can fail since ciss_free() always tries to stop and drain the callout. --- sys/dev/ciss/ciss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c index 7293bb1..2a4fb27 100644 --- a/sys/dev/ciss/ciss.c +++ b/sys/dev/ciss/ciss.c @@ -417,6 +417,7 @@ ciss_attach(device_t dev) sc = device_get_softc(dev); sc->ciss_dev = dev; mtx_init(&sc->ciss_mtx, "cissmtx", NULL, MTX_DEF); + callout_init_mtx(&sc->ciss_periodic, &sc->ciss_mtx, 0); /* * Do PCI-specific init. @@ -429,7 +430,6 @@ ciss_attach(device_t dev) */ ciss_initq_free(sc); ciss_initq_notify(sc); - callout_init_mtx(&sc->ciss_periodic, &sc->ciss_mtx, 0); /* * Initalize device sysctls. -- cgit v1.1 From 1b3b15fdbb3d5610779b9ec6005860287d411653 Mon Sep 17 00:00:00 2001 From: jfv Date: Wed, 28 Apr 2010 19:22:52 +0000 Subject: Address the LOD that some are seeing, put the RX lock back in rxeof (I could see little point in taking it out), and now release it before the stack entry. Also, make it so the 82574 does not configure for multiqueue when its not used in the stack. --- sys/dev/e1000/if_em.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index fcebc02..2fb4f17 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -347,8 +347,13 @@ static int em_debug_sbp = FALSE; TUNABLE_INT("hw.em.sbp", &em_debug_sbp); /* Local controls for MSI/MSIX */ +#ifdef EM_MULTIQUEUE static int em_enable_msix = TRUE; static int em_msix_queues = 2; /* for 82574, can be 1 or 2 */ +#else +static int em_enable_msix = FALSE; +static int em_msix_queues = 0; /* disable */ +#endif TUNABLE_INT("hw.em.enable_msix", &em_enable_msix); TUNABLE_INT("hw.em.msix_queues", &em_msix_queues); @@ -1371,9 +1376,7 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) } EM_CORE_UNLOCK(adapter); - EM_RX_LOCK(rxr); rx_done = em_rxeof(rxr, count); - EM_RX_UNLOCK(rxr); EM_TX_LOCK(txr); em_txeof(txr); @@ -1449,9 +1452,7 @@ em_handle_que(void *context, int pending) if (ifp->if_drv_flags & IFF_DRV_RUNNING) { - EM_RX_LOCK(rxr); more_rx = em_rxeof(rxr, adapter->rx_process_limit); - EM_RX_UNLOCK(rxr); EM_TX_LOCK(txr); em_txeof(txr); @@ -1511,10 +1512,8 @@ em_msix_rx(void *arg) struct adapter *adapter = rxr->adapter; bool more; - EM_RX_LOCK(rxr); ++rxr->rx_irq; more = em_rxeof(rxr, adapter->rx_process_limit); - EM_RX_UNLOCK(rxr); if (more) taskqueue_enqueue(rxr->tq, &rxr->rx_task); else @@ -1553,9 +1552,7 @@ em_handle_rx(void *context, int pending) struct adapter *adapter = rxr->adapter; bool more; - EM_RX_LOCK(rxr); more = em_rxeof(rxr, adapter->rx_process_limit); - EM_RX_UNLOCK(rxr); if (more) taskqueue_enqueue(rxr->tq, &rxr->rx_task); else @@ -4100,7 +4097,7 @@ em_rxeof(struct rx_ring *rxr, int count) bool eop; struct e1000_rx_desc *cur; - EM_RX_LOCK_ASSERT(rxr); + EM_RX_LOCK(rxr); for (i = rxr->next_to_check, processed = 0; count != 0;) { @@ -4194,8 +4191,13 @@ skip: i = 0; /* Send to the stack */ - if (sendmp != NULL) + if (sendmp != NULL) { + rxr->next_to_check = i; + EM_RX_UNLOCK(rxr); (*ifp->if_input)(ifp, sendmp); + EM_RX_LOCK(rxr); + i = rxr->next_to_check; + } /* Only refresh mbufs every 8 descriptors */ if (processed == 8) { @@ -4211,6 +4213,7 @@ skip: } rxr->next_to_check = i; + EM_RX_UNLOCK(rxr); #ifdef DEVICE_POLLING return (rxdone); -- cgit v1.1 From 4bf52321c35e1ae073f65020f92e80d53bdf79d8 Mon Sep 17 00:00:00 2001 From: jkim Date: Wed, 28 Apr 2010 21:50:57 +0000 Subject: Import ACPICA 20100428. --- changes.txt | 66 + common/adisasm.c | 6 +- compiler/Makefile | 38 +- compiler/aslcompile.c | 6 +- compiler/aslcompiler.h | 100 +- compiler/asldefine.h | 2 +- compiler/aslfiles.c | 30 + compiler/aslglobal.h | 3 + compiler/asllisting.c | 247 +- compiler/aslmain.c | 31 +- compiler/aslpredef.c | 78 +- compiler/aslresource.c | 294 +- compiler/aslrestype1.c | 562 +- compiler/aslrestype1i.c | 668 +++ compiler/aslrestype2.c | 2398 +------- compiler/aslrestype2d.c | 814 +++ compiler/aslrestype2e.c | 646 ++ compiler/aslrestype2q.c | 793 +++ compiler/aslrestype2w.c | 774 +++ compiler/asltypes.h | 22 +- debugger/dbcmds.c | 2 +- debugger/dbdisply.c | 14 +- events/evgpe.c | 2 +- events/evgpeblk.c | 774 +-- events/evgpeinit.c | 763 +++ events/evgpeutil.c | 452 ++ executer/exconfig.c | 21 +- executer/exoparg1.c | 2 +- executer/exsystem.c | 8 +- include/acevents.h | 74 +- include/acglobal.h | 7 +- include/acinterp.h | 2 +- include/aclocal.h | 16 +- include/acpiosxf.h | 4 +- include/acpixf.h | 30 +- include/actypes.h | 2 +- include/amlresrc.h | 6 + os_specific/service_layers/osunixxf.c | 4 +- os_specific/service_layers/oswinxf.c | 4 +- osunixxf.c | 4 +- tables/tbfind.c | 2 +- tables/tbinstal.c | 52 +- tables/tbutils.c | 15 +- tables/tbxface.c | 20 +- tests/misc/badcode.asl | 295 + tests/misc/grammar.asl | 10266 ++++++++++++++++++++++++++++++++ tools/acpiexec/Makefile | 4 +- tools/acpiexec/aeexec.c | 1 - tools/acpiexec/aetables.c | 141 +- tools/acpisrc/astable.c | 1 - utilities/utcopy.c | 20 +- utilities/utglobal.c | 4 +- utilities/uttrack.c | 108 +- 53 files changed, 16775 insertions(+), 3923 deletions(-) create mode 100644 compiler/aslrestype1i.c create mode 100644 compiler/aslrestype2d.c create mode 100644 compiler/aslrestype2e.c create mode 100644 compiler/aslrestype2q.c create mode 100644 compiler/aslrestype2w.c create mode 100644 events/evgpeinit.c create mode 100644 events/evgpeutil.c create mode 100644 tests/misc/badcode.asl create mode 100644 tests/misc/grammar.asl diff --git a/changes.txt b/changes.txt index d2c8c0e..fed0395 100644 --- a/changes.txt +++ b/changes.txt @@ -1,4 +1,70 @@ ---------------------------------------- +28 April 2010. Summary of changes for version 20100428: + +1) ACPI CA Core Subsystem: + +Implemented GPE support for dynamically loaded ACPI tables. For all GPEs, +including FADT-based and GPE Block Devices, execute any _PRW methods in the +new table, and process any _Lxx/_Exx GPE methods in the new table. Any +runtime GPE that is referenced by an _Lxx/_Exx method in the new table is +immediately enabled. Handles the FADT-defined GPEs as well as GPE Block +Devices. Provides compatibility with other ACPI implementations. Two new +files added, evgpeinit.c and evgpeutil.c. ACPICA BZ 833. Lin Ming, Bob Moore. + +Fixed a regression introduced in version 20100331 within the table manager +where initial table loading could fail. This was introduced in the fix for +AcpiReallocateRootTable. Also, renamed some of fields in the table manager +data structures to clarify their meaning and use. + +Fixed a possible allocation overrun during internal object copy in +AcpiUtCopySimpleObject. The original code did not correctly handle the case +where the object to be copied was a namespace node. Lin Ming. ACPICA BZ 847. + +Updated the allocation dump routine, AcpiUtDumpAllocation and fixed a +possible access beyond end-of-allocation. Also, now fully validate descriptor +(size and type) before output. Lin Ming, Bob Moore. ACPICA BZ 847 + +Example Code and Data Size: These are the sizes for the OS-independent +acpica.lib produced by the Microsoft Visual C++ 6.0 32-bit compiler. The +debug version of the code includes the debug output trace mechanism and has a +much larger code and data size. + + Previous Release: + Non-Debug Version: 87.9K Code, 18.6K Data, 106.5K Total + Debug Version: 163.5K Code, 51.3K Data, 214.8K Total + Current Release: + Non-Debug Version: 88.4K Code, 18.8K Data, 107.2K Total + Debug Version: 164.2K Code, 51.5K Data, 215.7K Total + +2) iASL Compiler/Disassembler and Tools: + +iASL: Implemented Min/Max/Len/Gran validation for address resource +descriptors. This change implements validation for the address fields that +are common to all address-type resource descriptors. These checks are +implemented: Checks for valid Min/Max, length within the Min/Max window, +valid granularity, Min/Max a multiple of granularity, and _MIF/_MAF as per +table 6-40 in the ACPI 4.0a specification. Also split the large aslrestype1.c +and aslrestype2.c files into five new files. ACPICA BZ 840. + +iASL: Added support for the _Wxx predefined names. This support was missing +and these names were not recognized by the compiler as valid predefined +names. ACPICA BZ 851. + +iASL: Added an error for all predefined names that are defined to return no +value and thus must be implemented as Control Methods. These include all of +the _Lxx, _Exx, _Wxx, and _Qxx names, as well as some other miscellaneous +names such as _DIS, _INI, _IRC, _OFF, _ON, and _PSx. ACPICA BZ 850, 856. + +iASL: Implemented the -ts option to emit hex AML data in ASL format, as an +ASL Buffer. Allows ACPI tables to be easily included within ASL files, to be +dynamically loaded via the Load() operator. Also cleaned up output for the - +ta and -tc options. ACPICA BZ 853. + +Tests: Added a new file with examples of extended iASL error checking. +Demonstrates the advanced error checking ability of the iASL compiler. +Available at tests/misc/badcode.asl. + +---------------------------------------- 31 March 2010. Summary of changes for version 20100331: 1) ACPI CA Core Subsystem: diff --git a/common/adisasm.c b/common/adisasm.c index 093cfe5..eced93d 100644 --- a/common/adisasm.c +++ b/common/adisasm.c @@ -282,8 +282,8 @@ AdInitialize ( /* Setup the Table Manager (cheat - there is no RSDT) */ - AcpiGbl_RootTableList.Size = 1; - AcpiGbl_RootTableList.Count = 0; + AcpiGbl_RootTableList.MaxTableCount = 1; + AcpiGbl_RootTableList.CurrentTableCount = 0; AcpiGbl_RootTableList.Tables = LocalTables; return (Status); @@ -1156,7 +1156,7 @@ AdParseTable ( /* If LoadTable is FALSE, we are parsing the last loaded table */ - TableIndex = AcpiGbl_RootTableList.Count - 1; + TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1; /* Pass 2 */ diff --git a/compiler/Makefile b/compiler/Makefile index b4c03fd..2bdd0d3 100644 --- a/compiler/Makefile +++ b/compiler/Makefile @@ -1,11 +1,37 @@ - PROG= iasl -SRCS= aslcompilerparse.c aslcompilerlex.c aslanalyze.c aslcodegen.c \ - aslcompile.c aslerror.c aslfiles.c asllength.c \ - asllisting.c aslload.c asllookup.c aslmain.c aslmap.c aslopcodes.c \ - asloperands.c aslpredef.c aslresource.c aslrestype1.c aslrestype2.c aslstartup.c \ - asltree.c aslutils.c asltransform.c aslfold.c aslstubs.c aslopt.c \ +SRCS= \ + aslcompilerparse.c \ + aslcompilerlex.c \ + aslanalyze.c \ + aslcodegen.c \ + aslcompile.c \ + aslerror.c \ + aslfiles.c \ + aslfold.c \ + asllength.c \ + asllisting.c \ + aslload.c \ + asllookup.c \ + aslmain.c \ + aslmap.c \ + aslopcodes.c \ + asloperands.c \ + aslopt.c \ + aslpredef.c \ + aslresource.c \ + aslrestype1.c \ + aslrestype1i.c \ + aslrestype2.c \ + aslrestype2d.c \ + aslrestype2e.c \ + aslrestype2q.c \ + aslrestype2w.c \ + aslstartup.c \ + aslstubs.c \ + asltransform.c \ + asltree.c \ + aslutils.c \ ../common/getopt.c \ ../utilities/utalloc.c \ ../utilities/utcache.c \ diff --git a/compiler/aslcompile.c b/compiler/aslcompile.c index 90e9099..d6cb8ad 100644 --- a/compiler/aslcompile.c +++ b/compiler/aslcompile.c @@ -177,7 +177,8 @@ AslCompilerSignon ( { Prefix = "; "; } - else if (Gbl_HexOutputFlag == HEX_OUTPUT_C) + else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) || + (Gbl_HexOutputFlag == HEX_OUTPUT_ASL)) { FlPrintFile (ASL_FILE_HEX_OUTPUT, "/*\n"); Prefix = " * "; @@ -265,7 +266,8 @@ AslCompilerFileHeader ( { Prefix = "; "; } - else if (Gbl_HexOutputFlag == HEX_OUTPUT_C) + else if ((Gbl_HexOutputFlag == HEX_OUTPUT_C) || + (Gbl_HexOutputFlag == HEX_OUTPUT_ASL)) { Prefix = " * "; } diff --git a/compiler/aslcompiler.h b/compiler/aslcompiler.h index 5083798..804713b 100644 --- a/compiler/aslcompiler.h +++ b/compiler/aslcompiler.h @@ -592,6 +592,10 @@ FlFileError ( UINT32 FileId, UINT8 ErrorId); +UINT32 +FlGetFileSize ( + UINT32 FileId); + ACPI_STATUS FlReadFile ( UINT32 FileId, @@ -750,6 +754,34 @@ UtDoConstant ( /* * aslresource - Resource template generation utilities */ +void +RsSmallAddressCheck ( + UINT8 Type, + UINT32 Minimum, + UINT32 Maximum, + UINT32 Length, + UINT32 Alignment, + ACPI_PARSE_OBJECT *MinOp, + ACPI_PARSE_OBJECT *MaxOp, + ACPI_PARSE_OBJECT *LengthOp, + ACPI_PARSE_OBJECT *AlignOp); + +void +RsLargeAddressCheck ( + UINT64 Minimum, + UINT64 Maximum, + UINT64 Length, + UINT64 Granularity, + UINT8 Flags, + ACPI_PARSE_OBJECT *MinOp, + ACPI_PARSE_OBJECT *MaxOp, + ACPI_PARSE_OBJECT *LengthOp, + ACPI_PARSE_OBJECT *GranOp); + +UINT16 +RsGetStringDataLength ( + ACPI_PARSE_OBJECT *InitializerOp); + ASL_RESOURCE_NODE * RsAllocateResourceNode ( UINT32 Size); @@ -805,7 +837,7 @@ RsDoResourceTemplate ( /* - * aslrestype1 - generate Small descriptors + * aslrestype1 - Miscellaneous Small descriptors */ ASL_RESOURCE_NODE * RsDoEndTagDescriptor ( @@ -813,68 +845,72 @@ RsDoEndTagDescriptor ( UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoDmaDescriptor ( +RsDoEndDependentDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoEndDependentDescriptor ( +RsDoMemory24Descriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoFixedIoDescriptor ( +RsDoMemory32Descriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoIoDescriptor ( +RsDoMemory32FixedDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoIrqDescriptor ( +RsDoStartDependentDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoIrqNoFlagsDescriptor ( +RsDoStartDependentNoPriDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoMemory24Descriptor ( +RsDoVendorSmallDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); + +/* + * aslrestype1i - I/O-related Small descriptors + */ ASL_RESOURCE_NODE * -RsDoMemory32Descriptor ( +RsDoDmaDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoMemory32FixedDescriptor ( +RsDoFixedIoDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoStartDependentDescriptor ( +RsDoIoDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoStartDependentNoPriDescriptor ( +RsDoIrqDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * -RsDoVendorSmallDescriptor ( +RsDoIrqNoFlagsDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); /* - * aslrestype2 - generate Large descriptors + * aslrestype2 - Large resource descriptors */ ASL_RESOURCE_NODE * RsDoInterruptDescriptor ( @@ -882,6 +918,20 @@ RsDoInterruptDescriptor ( UINT32 CurrentByteOffset); ASL_RESOURCE_NODE * +RsDoVendorLargeDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + +ASL_RESOURCE_NODE * +RsDoGeneralRegisterDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset); + + +/* + * aslrestype2d - DWord address descriptors + */ +ASL_RESOURCE_NODE * RsDoDwordIoDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); @@ -896,6 +946,10 @@ RsDoDwordSpaceDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); + +/* + * aslrestype2e - Extended address descriptors + */ ASL_RESOURCE_NODE * RsDoExtendedIoDescriptor ( ACPI_PARSE_OBJECT *Op, @@ -911,6 +965,10 @@ RsDoExtendedSpaceDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); + +/* + * aslrestype2q - QWord address descriptors + */ ASL_RESOURCE_NODE * RsDoQwordIoDescriptor ( ACPI_PARSE_OBJECT *Op, @@ -926,6 +984,10 @@ RsDoQwordSpaceDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); + +/* + * aslrestype2w - Word address descriptors + */ ASL_RESOURCE_NODE * RsDoWordIoDescriptor ( ACPI_PARSE_OBJECT *Op, @@ -941,15 +1003,5 @@ RsDoWordBusNumberDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset); -ASL_RESOURCE_NODE * -RsDoVendorLargeDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset); - -ASL_RESOURCE_NODE * -RsDoGeneralRegisterDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset); - #endif /* __ASLCOMPILER_H */ diff --git a/compiler/asldefine.h b/compiler/asldefine.h index 75345a5..cff4ecf 100644 --- a/compiler/asldefine.h +++ b/compiler/asldefine.h @@ -128,7 +128,7 @@ #define CompilerId "ASL Optimizing Compiler" #define DisassemblerId "AML Disassembler" #define CompilerCopyright "Copyright (c) 2000 - 2010 Intel Corporation" -#define CompilerCompliance "Supports ACPI Specification Revision 4.0" +#define CompilerCompliance "Supports ACPI Specification Revision 4.0a" #define CompilerName "iasl" #define CompilerCreatorId "INTL" diff --git a/compiler/aslfiles.c b/compiler/aslfiles.c index ebf59a4..8f498a1 100644 --- a/compiler/aslfiles.c +++ b/compiler/aslfiles.c @@ -236,6 +236,36 @@ FlOpenFile ( /******************************************************************************* * + * FUNCTION: FlGetFileSize + * + * PARAMETERS: FileId - Index into file info array + * + * RETURN: File Size + * + * DESCRIPTION: Get current file size. Uses seek-to-EOF. File must be open. + * + ******************************************************************************/ + +UINT32 +FlGetFileSize ( + UINT32 FileId) +{ + FILE *fp; + UINT32 FileSize; + + + fp = Gbl_Files[FileId].Handle; + + fseek (fp, 0, SEEK_END); + FileSize = (UINT32) ftell (fp); + fseek (fp, 0, SEEK_SET); + + return (FileSize); +} + + +/******************************************************************************* + * * FUNCTION: FlReadFile * * PARAMETERS: FileId - Index into file info array diff --git a/compiler/aslglobal.h b/compiler/aslglobal.h index 01ab931..85bb3e2 100644 --- a/compiler/aslglobal.h +++ b/compiler/aslglobal.h @@ -188,6 +188,7 @@ ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_CompileTimesFlag, FALSE ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_FoldConstants, TRUE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_VerboseErrors, TRUE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_NoErrors, FALSE); +ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_NoResourceChecking, FALSE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_DisasmFlag, FALSE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_GetAllTables, FALSE); ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_IntegerOptimizationFlag, TRUE); @@ -200,6 +201,8 @@ ASL_EXTERN UINT8 ASL_INIT_GLOBAL (Gbl_WarningLevel, ASL_WARNI #define HEX_OUTPUT_NONE 0 #define HEX_OUTPUT_C 1 #define HEX_OUTPUT_ASM 2 +#define HEX_OUTPUT_ASL 3 + ASL_EXTERN BOOLEAN ASL_INIT_GLOBAL (Gbl_HexOutputFlag, HEX_OUTPUT_NONE); diff --git a/compiler/asllisting.c b/compiler/asllisting.c index c4253c2..93f83ad 100644 --- a/compiler/asllisting.c +++ b/compiler/asllisting.c @@ -198,6 +198,10 @@ static void LsDoHexOutputAsm ( void); +static void +LsDoHexOutputAsl ( + void); + ACPI_STATUS LsTreeWriteWalk ( ACPI_PARSE_OBJECT *Op, @@ -1337,6 +1341,11 @@ LsDoHexOutput ( LsDoHexOutputAsm (); break; + case HEX_OUTPUT_ASL: + + LsDoHexOutputAsl (); + break; + default: /* No other output types supported */ break; @@ -1362,60 +1371,160 @@ static void LsDoHexOutputC ( void) { - UINT32 j; - UINT8 FileByte[HEX_TABLE_LINE_SIZE]; - UINT8 Buffer[4]; + UINT8 FileData[HEX_TABLE_LINE_SIZE]; + UINT32 LineLength; UINT32 Offset = 0; + UINT32 AmlFileSize; + UINT32 i; + + + /* Get AML size, seek back to start */ + AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); - FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n *\n */\n"); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " * C source code output\n"); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n", + AmlFileSize); FlPrintFile (ASL_FILE_HEX_OUTPUT, "unsigned char AmlCode[] =\n{\n"); - /* Start at the beginning of the AML file */ + while (Offset < AmlFileSize) + { + /* Read enough bytes needed for one output line */ - FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, + Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); + if (!LineLength) + { + break; + } - /* Process all AML bytes in the AML file */ + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); - j = 0; - while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte[j], 1) == AE_OK) - { - if (j == 0) + for (i = 0; i < LineLength; i++) { - FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + /* + * Print each hex byte. + * Add a comma until the very last byte of the AML file + * (Some C compilers complain about a trailing comma) + */ + FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]); + if ((Offset + i + 1) < AmlFileSize) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); + } + else + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + } } - /* Convert each AML byte to hex */ + /* Add fill spaces if needed for last line */ - UtConvertByteToHex (FileByte[j], Buffer); - FlWriteFile (ASL_FILE_HEX_OUTPUT, Buffer, 4); - FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); + if (LineLength < HEX_TABLE_LINE_SIZE) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", + 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); + } - /* An occasional linefeed improves readability */ + /* Emit the offset and ascii dump for the entire line */ - Offset++; - j++; + FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset); + LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n", + HEX_TABLE_LINE_SIZE - LineLength + 1, " "); - if (j >= HEX_TABLE_LINE_SIZE) - { - /* End of line, emit the ascii dump of the entire line */ + Offset += LineLength; + } - FlPrintFile (ASL_FILE_HEX_OUTPUT, - " /* %8.8X", Offset - HEX_TABLE_LINE_SIZE); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "};\n"); + FlCloseFile (ASL_FILE_HEX_OUTPUT); +} - /* Write the ASCII character associated with each of the bytes */ - LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, - HEX_TABLE_LINE_SIZE, FileByte); - FlPrintFile (ASL_FILE_HEX_OUTPUT, " */\n"); +/******************************************************************************* + * + * FUNCTION: LsDoHexOutputAsl + * + * PARAMETERS: None + * + * RETURN: None. + * + * DESCRIPTION: Create the hex output file. This is the same data as the AML + * output file, but formatted into hex/ascii bytes suitable for + * inclusion into a C source file. + * + ******************************************************************************/ - /* Start new line */ +static void +LsDoHexOutputAsl ( + void) +{ + UINT8 FileData[HEX_TABLE_LINE_SIZE]; + UINT32 LineLength; + UINT32 Offset = 0; + UINT32 AmlFileSize; + UINT32 i; - j = 0; + + /* Get AML size, seek back to start */ + + AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " * ASL source code output\n"); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " * AML code block contains 0x%X bytes\n *\n */\n", + AmlFileSize); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " Name (BUF1, Buffer()\n {\n"); + + while (Offset < AmlFileSize) + { + /* Read enough bytes needed for one output line */ + + LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, + Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); + if (!LineLength) + { + break; + } + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + + for (i = 0; i < LineLength; i++) + { + /* + * Print each hex byte. + * Add a comma until the very last byte of the AML file + * (Some C compilers complain about a trailing comma) + */ + FlPrintFile (ASL_FILE_HEX_OUTPUT, "0x%2.2X", FileData[i]); + if ((Offset + i + 1) < AmlFileSize) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); + } + else + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); + } + } + + /* Add fill spaces if needed for last line */ + + if (LineLength < HEX_TABLE_LINE_SIZE) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", + 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); } + + /* Emit the offset and ascii dump for the entire line */ + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " /* %8.8X", Offset); + LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s*/\n", + HEX_TABLE_LINE_SIZE - LineLength + 1, " "); + + Offset += LineLength; } - FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n};\n"); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " })\n"); FlCloseFile (ASL_FILE_HEX_OUTPUT); } @@ -1438,58 +1547,64 @@ static void LsDoHexOutputAsm ( void) { - UINT32 j; - UINT8 FileByte[HEX_TABLE_LINE_SIZE]; - UINT8 Buffer[4]; + UINT8 FileData[HEX_TABLE_LINE_SIZE]; + UINT32 LineLength; UINT32 Offset = 0; - BOOLEAN DoComma = FALSE; + UINT32 AmlFileSize; + UINT32 i; - FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n;\n"); + /* Get AML size, seek back to start */ - /* Start at the beginning of the AML file */ + AmlFileSize = FlGetFileSize (ASL_FILE_AML_OUTPUT); - FlSeekFile (ASL_FILE_AML_OUTPUT, 0); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "; Assembly code source output\n"); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "; AML code block contains 0x%X bytes\n;\n", + AmlFileSize); - /* Process all AML bytes in the AML file */ - - j = 0; - while (FlReadFile (ASL_FILE_AML_OUTPUT, &FileByte[j], 1) == AE_OK) + while (Offset < AmlFileSize) { - if (j == 0) + /* Read enough bytes needed for one output line */ + + LineLength = fread (FileData, 1, HEX_TABLE_LINE_SIZE, + Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); + if (!LineLength) { - FlPrintFile (ASL_FILE_HEX_OUTPUT, " db "); + break; } - else if (DoComma) + + FlPrintFile (ASL_FILE_HEX_OUTPUT, " db "); + + for (i = 0; i < LineLength; i++) { - FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); - DoComma = FALSE; + /* + * Print each hex byte. + * Add a comma until the last byte of the line + */ + FlPrintFile (ASL_FILE_HEX_OUTPUT, "0%2.2Xh", FileData[i]); + if ((i + 1) < LineLength) + { + FlPrintFile (ASL_FILE_HEX_OUTPUT, ","); + } } - /* Convert each AML byte to hex */ - - UtConvertByteToAsmHex (FileByte[j], Buffer); - FlWriteFile (ASL_FILE_HEX_OUTPUT, Buffer, 4); + FlPrintFile (ASL_FILE_HEX_OUTPUT, " "); - /* An occasional linefeed improves readability */ + /* Add fill spaces if needed for last line */ - Offset++; - j++; - if (j >= HEX_TABLE_LINE_SIZE) + if (LineLength < HEX_TABLE_LINE_SIZE) { - FlPrintFile (ASL_FILE_HEX_OUTPUT, - " ;%8.8X", Offset - HEX_TABLE_LINE_SIZE); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "%*s", + 5 * (HEX_TABLE_LINE_SIZE - LineLength), " "); + } - /* Write the ASCII character associated with each of the bytes */ + /* Emit the offset and ascii dump for the entire line */ - LsDumpAscii (ASL_FILE_HEX_OUTPUT, HEX_TABLE_LINE_SIZE, FileByte); - FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n"); - j = 0; - } - else - { - DoComma = TRUE; - } + FlPrintFile (ASL_FILE_HEX_OUTPUT, " ; %8.8X", Offset); + LsDumpAsciiInComment (ASL_FILE_HEX_OUTPUT, LineLength, FileData); + FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n"); + + Offset += LineLength; } FlPrintFile (ASL_FILE_HEX_OUTPUT, "\n"); diff --git a/compiler/aslmain.c b/compiler/aslmain.c index 59b5880..42127c0 100644 --- a/compiler/aslmain.c +++ b/compiler/aslmain.c @@ -167,7 +167,7 @@ AslDoResponseFile ( #define ASL_TOKEN_SEPARATORS " \t\n" -#define ASL_SUPPORTED_OPTIONS "@:2b:cd^e:fgh^i^I:l^o:p:r:s:t:v:w:x:" +#define ASL_SUPPORTED_OPTIONS "@:2b:c:d^e:fgh^i^I:l^no:p:r:s:t:v:w:x:" /******************************************************************************* @@ -203,13 +203,14 @@ Options ( printf ("\nAML Output Files:\n"); printf (" -s Create AML in assembler or C source file (*.asm or *.c)\n"); printf (" -i Create assembler or C include file (*.inc or *.h)\n"); - printf (" -t Create AML in assembler or C hex table (*.hex)\n"); + printf (" -t Create AML in assembler, C, or ASL hex table (*.hex)\n"); printf ("\nAML Code Generation:\n"); printf (" -oa Disable all optimizations (compatibility mode)\n"); printf (" -of Disable constant folding\n"); printf (" -oi Disable integer optimization to Zero/One/Ones\n"); printf (" -on Disable named reference string optimization\n"); + printf (" -cr Disable Resource Descriptor error checking\n"); printf (" -r Override table header Revision (1-255)\n"); printf ("\nListings:\n"); @@ -264,7 +265,7 @@ HelpMessage ( printf (" -b Create compiler debug/trace file (*.txt)\n"); printf (" Types: Parse/Tree/Both\n"); printf (" -f Ignore errors, force creation of AML output file(s)\n"); - printf (" -c Parse only, no output generation\n"); + printf (" -n Parse only, no output generation\n"); printf (" -ot Display compile times\n"); printf (" -x Set debug level for trace output\n"); } @@ -507,10 +508,16 @@ AslDoOptions ( case 'c': + switch (AcpiGbl_Optarg[0]) + { + case 'r': + Gbl_NoResourceChecking = TRUE; + break; - /* Parse only */ - - Gbl_ParseOnlyFlag = TRUE; + default: + printf ("Unknown option: -c%s\n", AcpiGbl_Optarg); + return (-1); + } break; @@ -688,6 +695,14 @@ AslDoOptions ( break; + case 'n': + + /* Parse only */ + + Gbl_ParseOnlyFlag = TRUE; + break; + + case 'p': /* Override default AML output filename */ @@ -741,6 +756,10 @@ AslDoOptions ( Gbl_HexOutputFlag = HEX_OUTPUT_C; break; + case 's': + Gbl_HexOutputFlag = HEX_OUTPUT_ASL; + break; + default: printf ("Unknown option: -t%s\n", AcpiGbl_Optarg); return (-1); diff --git a/compiler/aslpredef.c b/compiler/aslpredef.c index 6346baf..ae1b773 100644 --- a/compiler/aslpredef.c +++ b/compiler/aslpredef.c @@ -243,11 +243,11 @@ ApCheckForPredefinedMethod ( break; - case ACPI_EVENT_RESERVED_NAME: /* _Lxx, _Exx, and _Qxx methods */ + case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */ Gbl_ReservedMethods++; - /* NumArguments must be zero for all _Lxx, _Exx, and _Qxx methods */ + /* NumArguments must be zero for all _Lxx/_Exx/_Wxx/_Qxx methods */ if (MethodInfo->NumArguments != 0) { @@ -346,12 +346,12 @@ ApCheckPredefinedReturnValue ( case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */ case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */ case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */ - case ACPI_EVENT_RESERVED_NAME: /* _Lxx, _Exx, and _Qxx methods */ + case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */ /* Just return, nothing to do */ return; - default: /* a real predefined ACPI name */ + default: /* A standard predefined ACPI name */ /* Exit if no return value expected */ @@ -425,29 +425,59 @@ ApCheckForPredefinedObject ( * or a predefined scope name */ Index = ApCheckForPredefinedName (Op, Name); - if (Index > ACPI_VALID_RESERVED_NAME_MAX) + + switch (Index) { + case ACPI_NOT_RESERVED_NAME: /* No underscore or _Txx or _xxx name not matched */ + case ACPI_PREDEFINED_NAME: /* Resource Name or reserved scope name */ + case ACPI_COMPILER_RESERVED_NAME: /* A _Txx that was not emitted by compiler */ + + /* Nothing to do */ return; - } - /* - * We found a matching predefind name. - * Check if this predefined name requires input arguments - */ - if (PredefinedNames[Index].Info.ParamCount > 0) - { + case ACPI_EVENT_RESERVED_NAME: /* _Lxx/_Exx/_Wxx/_Qxx methods */ + /* - * This predefined name must always be defined as a control - * method because it is required to have input arguments. + * These names must be control methods, by definition in ACPI spec. + * Also because they are defined to return no value. None of them + * require any arguments. */ AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, - "with arguments"); - } + "with zero arguments"); + return; - /* Typecheck the actual object, it is the next argument */ + default: /* A standard predefined ACPI name */ - ApCheckObjectType (Op->Asl.Child->Asl.Next, - PredefinedNames[Index].Info.ExpectedBtypes); + /* + * If this predefined name requires input arguments, then + * it must be implemented as a control method + */ + if (PredefinedNames[Index].Info.ParamCount > 0) + { + AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, + "with arguments"); + return; + } + + /* + * If no return value is expected from this predefined name, then + * it follows that it must be implemented as a control method + * (with zero args, because the args > 0 case was handled above) + * Examples are: _DIS, _INI, _IRC, _OFF, _ON, _PSx + */ + if (!PredefinedNames[Index].Info.ExpectedBtypes) + { + AslError (ASL_ERROR, ASL_MSG_RESERVED_METHOD, Op, + "with zero arguments"); + return; + } + + /* Typecheck the actual object, it is the next argument */ + + ApCheckObjectType (Op->Asl.Child->Asl.Next, + PredefinedNames[Index].Info.ExpectedBtypes); + return; + } } @@ -514,7 +544,7 @@ ApCheckForPredefinedName ( } } - /* Check for _Lxx, _Exx, _Qxx, _T_x. Warning if unknown predefined name */ + /* Check for _Lxx/_Exx/_Wxx/_Qxx/_T_x. Warning if unknown predefined name */ return (ApCheckForSpecialName (Op, Name)); } @@ -530,7 +560,7 @@ ApCheckForPredefinedName ( * RETURN: None * * DESCRIPTION: Check for the "special" predefined names - - * _Lxx, _Exx, _Qxx, and _T_x + * _Lxx, _Exx, _Qxx, _Wxx, and _T_x * ******************************************************************************/ @@ -541,14 +571,16 @@ ApCheckForSpecialName ( { /* - * Check for the "special" predefined names. We know the first char is an - * underscore already. + * Check for the "special" predefined names. We already know that the + * first character is an underscore. * GPE: _Lxx * GPE: _Exx + * GPE: _Wxx * EC: _Qxx */ if ((Name[1] == 'L') || (Name[1] == 'E') || + (Name[1] == 'W') || (Name[1] == 'Q')) { /* The next two characters must be hex digits */ diff --git a/compiler/aslresource.c b/compiler/aslresource.c index 421fde3..67aabca 100644 --- a/compiler/aslresource.c +++ b/compiler/aslresource.c @@ -1,7 +1,7 @@ /****************************************************************************** * - * Module Name: aslresource - Resource templates and descriptors + * Module Name: aslresource - Resource template/descriptor utilities * *****************************************************************************/ @@ -126,6 +126,298 @@ /******************************************************************************* * + * FUNCTION: RsSmallAddressCheck + * + * PARAMETERS: Minimum - Address Min value + * Maximum - Address Max value + * Length - Address range value + * Alignment - Address alignment value + * MinOp - Original Op for Address Min + * MaxOp - Original Op for Address Max + * LengthOp - Original Op for address range + * AlignOp - Original Op for address alignment. If + * NULL, means "zero value for alignment is + * OK, and means 64K alignment" (for + * Memory24 descriptor) + * + * RETURN: None. Adds error messages to error log if necessary + * + * DESCRIPTION: Perform common value checks for "small" address descriptors. + * Currently: + * Io, Memory24, Memory32 + * + ******************************************************************************/ + +void +RsSmallAddressCheck ( + UINT8 Type, + UINT32 Minimum, + UINT32 Maximum, + UINT32 Length, + UINT32 Alignment, + ACPI_PARSE_OBJECT *MinOp, + ACPI_PARSE_OBJECT *MaxOp, + ACPI_PARSE_OBJECT *LengthOp, + ACPI_PARSE_OBJECT *AlignOp) +{ + + if (Gbl_NoResourceChecking) + { + return; + } + + /* Special case for Memory24, values are compressed */ + + if (Type == ACPI_RESOURCE_NAME_MEMORY24) + { + if (!Alignment) /* Alignment==0 means 64K - no invalid alignment */ + { + Alignment = ACPI_UINT16_MAX + 1; + } + + Minimum <<= 8; + Maximum <<= 8; + Length *= 256; + } + + /* IO descriptor has different definition of min/max, don't check */ + + if (Type != ACPI_RESOURCE_NAME_IO) + { + /* Basic checks on Min/Max/Length */ + + if (Minimum > Maximum) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL); + } + else if (Length > (Maximum - Minimum + 1)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL); + } + } + + /* Alignment of zero is not in ACPI spec, but is used to mean byte acc */ + + if (!Alignment) + { + Alignment = 1; + } + + /* Addresses must be an exact multiple of the alignment value */ + + if (Minimum % Alignment) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL); + } + if (Maximum % Alignment) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, NULL); + } +} + + +/******************************************************************************* + * + * FUNCTION: RsLargeAddressCheck + * + * PARAMETERS: Minimum - Address Min value + * Maximum - Address Max value + * Length - Address range value + * Granularity - Address granularity value + * Flags - General flags for address descriptors: + * _MIF, _MAF, _DEC + * MinOp - Original Op for Address Min + * MaxOp - Original Op for Address Max + * LengthOp - Original Op for address range + * GranOp - Original Op for address granularity + * + * RETURN: None. Adds error messages to error log if necessary + * + * DESCRIPTION: Perform common value checks for "large" address descriptors. + * Currently: + * WordIo, WordBusNumber, WordSpace + * DWordIo, DWordMemory, DWordSpace + * QWordIo, QWordMemory, QWordSpace + * ExtendedIo, ExtendedMemory, ExtendedSpace + * + * _MIF flag set means that the minimum address is fixed and is not relocatable + * _MAF flag set means that the maximum address is fixed and is not relocatable + * Length of zero means that the record size is variable + * + * This function implements the LEN/MIF/MAF/MIN/MAX/GRA rules within Table 6-40 + * of the ACPI 4.0a specification. Added 04/2010. + * + ******************************************************************************/ + +void +RsLargeAddressCheck ( + UINT64 Minimum, + UINT64 Maximum, + UINT64 Length, + UINT64 Granularity, + UINT8 Flags, + ACPI_PARSE_OBJECT *MinOp, + ACPI_PARSE_OBJECT *MaxOp, + ACPI_PARSE_OBJECT *LengthOp, + ACPI_PARSE_OBJECT *GranOp) +{ + + if (Gbl_NoResourceChecking) + { + return; + } + + /* Basic checks on Min/Max/Length */ + + if (Minimum > Maximum) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_MIN_MAX, MinOp, NULL); + return; + } + else if (Length > (Maximum - Minimum + 1)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH, LengthOp, NULL); + return; + } + + /* If specified (non-zero), ensure granularity is a power-of-two minus one */ + + if (Granularity) + { + if ((Granularity + 1) & + Granularity) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_GRANULARITY, GranOp, NULL); + return; + } + } + + /* + * Check the various combinations of Length, MinFixed, and MaxFixed + */ + if (Length) + { + /* Fixed non-zero length */ + + switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF)) + { + case 0: + /* + * Fixed length, variable locations (both _MIN and _MAX). + * Length must be a multiple of granularity + */ + if (Granularity & Length) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, LengthOp, NULL); + } + break; + + case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF): + + /* Fixed length, fixed location. Granularity must be zero */ + + if (Granularity != 0) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_GRAN_FIXED, GranOp, NULL); + } + + /* Length must be exactly the size of the min/max window */ + + if (Length != (Maximum - Minimum + 1)) + { + AslError (ASL_ERROR, ASL_MSG_INVALID_LENGTH_FIXED, LengthOp, NULL); + } + break; + + /* All other combinations are invalid */ + + case ACPI_RESOURCE_FLAG_MIF: + case ACPI_RESOURCE_FLAG_MAF: + default: + AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL); + } + } + else + { + /* Variable length (length==0) */ + + switch (Flags & (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF)) + { + case 0: + /* + * Both _MIN and _MAX are variable. + * No additional requirements, just exit + */ + break; + + case ACPI_RESOURCE_FLAG_MIF: + + /* _MIN is fixed. _MIN must be multiple of _GRA */ + + /* + * The granularity is defined by the ACPI specification to be a + * power-of-two minus one, therefore the granularity is a + * bitmask which can be used to easily validate the addresses. + */ + if (Granularity & Minimum) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MinOp, NULL); + } + break; + + case ACPI_RESOURCE_FLAG_MAF: + + /* _MAX is fixed. (_MAX + 1) must be multiple of _GRA */ + + if (Granularity & (Maximum + 1)) + { + AslError (ASL_ERROR, ASL_MSG_ALIGNMENT, MaxOp, "-1"); + } + break; + + /* Both MIF/MAF set is invalid if length is zero */ + + case (ACPI_RESOURCE_FLAG_MIF | ACPI_RESOURCE_FLAG_MAF): + default: + AslError (ASL_ERROR, ASL_MSG_INVALID_ADDR_FLAGS, LengthOp, NULL); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: RsGetStringDataLength + * + * PARAMETERS: InitializerOp - Start of a subtree of init nodes + * + * RETURN: Valid string length if a string node is found (otherwise 0) + * + * DESCRIPTION: In a list of peer nodes, find the first one that contains a + * string and return the length of the string. + * + ******************************************************************************/ + +UINT16 +RsGetStringDataLength ( + ACPI_PARSE_OBJECT *InitializerOp) +{ + + while (InitializerOp) + { + if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) + { + return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1)); + } + InitializerOp = ASL_GET_PEER_NODE (InitializerOp); + } + + return 0; +} + + +/******************************************************************************* + * * FUNCTION: RsAllocateResourceNode * * PARAMETERS: Size - Size of node in bytes diff --git a/compiler/aslrestype1.c b/compiler/aslrestype1.c index 1dbff031..381fb53 100644 --- a/compiler/aslrestype1.c +++ b/compiler/aslrestype1.c @@ -1,7 +1,7 @@ /****************************************************************************** * - * Module Name: aslrestype1 - Short (type1) resource templates and descriptors + * Module Name: aslrestype1 - Miscellaneous small resource descriptors * *****************************************************************************/ @@ -121,6 +121,18 @@ #define _COMPONENT ACPI_COMPILER ACPI_MODULE_NAME ("aslrestype1") +/* + * This module contains miscellaneous small resource descriptors: + * + * EndTag + * EndDependentFn + * Memory24 + * Memory32 + * Memory32Fixed + * StartDependentFn + * StartDependentFnNoPri + * VendorShort + */ /******************************************************************************* * @@ -158,127 +170,6 @@ RsDoEndTagDescriptor ( /******************************************************************************* * - * FUNCTION: RsDoDmaDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a short "DMA" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoDmaDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT32 i; - UINT8 DmaChannelMask = 0; - UINT8 DmaChannels = 0; - - - InitializerOp = Op->Asl.Child; - Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_DMA)); - - Descriptor = Rnode->Buffer; - Descriptor->Dma.DescriptorType = ACPI_RESOURCE_NAME_DMA | - ASL_RDESC_DMA_SIZE; - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* DMA type */ - - RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 5, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DMATYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 5); - break; - - case 1: /* Bus Master */ - - RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_BUSMASTER, - CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 2); - break; - - case 2: /* Xfer Type (transfer width) */ - - RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 0, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_XFERTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 0); - break; - - case 3: /* Name */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - /* All DMA channel bytes are handled here, after flags and name */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - /* Up to 8 channels can be specified in the list */ - - DmaChannels++; - if (DmaChannels > 8) - { - AslError (ASL_ERROR, ASL_MSG_DMA_LIST, - InitializerOp, NULL); - return (Rnode); - } - - /* Only DMA channels 0-7 are allowed (mask is 8 bits) */ - - if (InitializerOp->Asl.Value.Integer > 7) - { - AslError (ASL_ERROR, ASL_MSG_DMA_CHANNEL, - InitializerOp, NULL); - } - - /* Build the mask */ - - DmaChannelMask |= - (1 << ((UINT8) InitializerOp->Asl.Value.Integer)); - } - - if (i == 4) /* case 4: First DMA byte */ - { - /* Check now for duplicates in list */ - - RsCheckListForDuplicates (InitializerOp); - - /* Create a named field at the start of the list */ - - RsCreateByteField (InitializerOp, ACPI_RESTAG_DMA, - CurrentByteOffset + - ASL_RESDESC_OFFSET (Dma.DmaChannelMask)); - } - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - /* Now we can set the channel mask */ - - Descriptor->Dma.DmaChannelMask = DmaChannelMask; - return (Rnode); -} - - -/******************************************************************************* - * * FUNCTION: RsDoEndDependentDescriptor * * PARAMETERS: Op - Parent resource descriptor parse node @@ -311,396 +202,6 @@ RsDoEndDependentDescriptor ( /******************************************************************************* * - * FUNCTION: RsDoFixedIoDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a short "FixedIO" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoFixedIoDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT32 i; - - - InitializerOp = Op->Asl.Child; - Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_IO)); - - Descriptor = Rnode->Buffer; - Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_FIXED_IO | - ASL_RDESC_FIXED_IO_SIZE; - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Base Address */ - - Descriptor->FixedIo.Address = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_BASEADDRESS, - CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.Address)); - break; - - case 1: /* Length */ - - Descriptor->FixedIo.AddressLength = - (UINT8) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.AddressLength)); - break; - - case 2: /* Name */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoIoDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a short "IO" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoIoDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT32 i; - - - InitializerOp = Op->Asl.Child; - Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IO)); - - Descriptor = Rnode->Buffer; - Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_IO | - ASL_RDESC_IO_SIZE; - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Decode size */ - - RsSetFlagBits (&Descriptor->Io.Flags, InitializerOp, 0, 1); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Flags), 0); - break; - - case 1: /* Min Address */ - - Descriptor->Io.Minimum = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Minimum)); - break; - - case 2: /* Max Address */ - - Descriptor->Io.Maximum = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Maximum)); - break; - - case 3: /* Alignment */ - - Descriptor->Io.Alignment = - (UINT8) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT, - CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Alignment)); - break; - - case 4: /* Length */ - - Descriptor->Io.AddressLength = - (UINT8) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Io.AddressLength)); - break; - - case 5: /* Name */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoIrqDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a short "IRQ" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoIrqDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT32 Interrupts = 0; - UINT16 IrqMask = 0; - UINT32 i; - - - InitializerOp = Op->Asl.Child; - Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ)); - - /* Length = 3 (with flag byte) */ - - Descriptor = Rnode->Buffer; - Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ | - (ASL_RDESC_IRQ_SIZE + 0x01); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Interrupt Type (or Mode - edge/level) */ - - RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 0, 1); - RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 0); - break; - - case 1: /* Interrupt Level (or Polarity - Active high/low) */ - - RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL, - CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 3); - break; - - case 2: /* Share Type - Default: exclusive (0) */ - - RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 4, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 4); - break; - - case 3: /* Name */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - /* All IRQ bytes are handled here, after the flags and name */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - /* Up to 16 interrupts can be specified in the list */ - - Interrupts++; - if (Interrupts > 16) - { - AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST, - InitializerOp, NULL); - return (Rnode); - } - - /* Only interrupts 0-15 are allowed (mask is 16 bits) */ - - if (InitializerOp->Asl.Value.Integer > 15) - { - AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER, - InitializerOp, NULL); - } - else - { - IrqMask |= (1 << (UINT8) InitializerOp->Asl.Value.Integer); - } - } - - /* Case 4: First IRQ value in list */ - - if (i == 4) - { - /* Check now for duplicates in list */ - - RsCheckListForDuplicates (InitializerOp); - - /* Create a named field at the start of the list */ - - RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT, - CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask)); - } - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - /* Now we can set the channel mask */ - - Descriptor->Irq.IrqMask = IrqMask; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoIrqNoFlagsDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a short "IRQNoFlags" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoIrqNoFlagsDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT16 IrqMask = 0; - UINT32 Interrupts = 0; - UINT32 i; - - - InitializerOp = Op->Asl.Child; - Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ_NOFLAGS)); - - Descriptor = Rnode->Buffer; - Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ | - ASL_RDESC_IRQ_SIZE; - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Name */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - /* IRQ bytes are handled here, after the flags and name */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - /* Up to 16 interrupts can be specified in the list */ - - Interrupts++; - if (Interrupts > 16) - { - AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST, - InitializerOp, NULL); - return (Rnode); - } - - /* Only interrupts 0-15 are allowed (mask is 16 bits) */ - - if (InitializerOp->Asl.Value.Integer > 15) - { - AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER, - InitializerOp, NULL); - } - else - { - IrqMask |= (1 << ((UINT8) InitializerOp->Asl.Value.Integer)); - } - } - - /* Case 1: First IRQ value in list */ - - if (i == 1) - { - /* Check now for duplicates in list */ - - RsCheckListForDuplicates (InitializerOp); - - /* Create a named field at the start of the list */ - - RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT, - CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask)); - } - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - /* Now we can set the interrupt mask */ - - Descriptor->Irq.IrqMask = IrqMask; - return (Rnode); -} - - -/******************************************************************************* - * * FUNCTION: RsDoMemory24Descriptor * * PARAMETERS: Op - Parent resource descriptor parse node @@ -720,6 +221,10 @@ RsDoMemory24Descriptor ( { AML_RESOURCE *Descriptor; ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *AlignOp = NULL; ASL_RESOURCE_NODE *Rnode; UINT32 i; @@ -749,6 +254,7 @@ RsDoMemory24Descriptor ( Descriptor->Memory24.Minimum = (UINT16) InitializerOp->Asl.Value.Integer; RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Minimum)); + MinOp = InitializerOp; break; case 2: /* Max Address */ @@ -756,6 +262,7 @@ RsDoMemory24Descriptor ( Descriptor->Memory24.Maximum = (UINT16) InitializerOp->Asl.Value.Integer; RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Maximum)); + MaxOp = InitializerOp; break; case 3: /* Alignment */ @@ -763,6 +270,7 @@ RsDoMemory24Descriptor ( Descriptor->Memory24.Alignment = (UINT16) InitializerOp->Asl.Value.Integer; RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT, CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.Alignment)); + AlignOp = InitializerOp; break; case 4: /* Length */ @@ -770,6 +278,7 @@ RsDoMemory24Descriptor ( Descriptor->Memory24.AddressLength = (UINT16) InitializerOp->Asl.Value.Integer; RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, CurrentByteOffset + ASL_RESDESC_OFFSET (Memory24.AddressLength)); + LengthOp = InitializerOp; break; case 5: /* Name */ @@ -786,6 +295,15 @@ RsDoMemory24Descriptor ( InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); } + /* Validate the Min/Max/Len/Align values (Alignment==0 means 64K) */ + + RsSmallAddressCheck (ACPI_RESOURCE_NAME_MEMORY24, + Descriptor->Memory24.Minimum, + Descriptor->Memory24.Maximum, + Descriptor->Memory24.AddressLength, + Descriptor->Memory24.Alignment, + MinOp, MaxOp, LengthOp, NULL); + return (Rnode); } @@ -811,6 +329,10 @@ RsDoMemory32Descriptor ( { AML_RESOURCE *Descriptor; ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *AlignOp = NULL; ASL_RESOURCE_NODE *Rnode; UINT32 i; @@ -840,6 +362,7 @@ RsDoMemory32Descriptor ( Descriptor->Memory32.Minimum = (UINT32) InitializerOp->Asl.Value.Integer; RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Minimum)); + MinOp = InitializerOp; break; case 2: /* Max Address */ @@ -847,6 +370,7 @@ RsDoMemory32Descriptor ( Descriptor->Memory32.Maximum = (UINT32) InitializerOp->Asl.Value.Integer; RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Maximum)); + MaxOp = InitializerOp; break; case 3: /* Alignment */ @@ -854,6 +378,7 @@ RsDoMemory32Descriptor ( Descriptor->Memory32.Alignment = (UINT32) InitializerOp->Asl.Value.Integer; RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT, CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.Alignment)); + AlignOp = InitializerOp; break; case 4: /* Length */ @@ -861,6 +386,7 @@ RsDoMemory32Descriptor ( Descriptor->Memory32.AddressLength = (UINT32) InitializerOp->Asl.Value.Integer; RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, CurrentByteOffset + ASL_RESDESC_OFFSET (Memory32.AddressLength)); + LengthOp = InitializerOp; break; case 5: /* Name */ @@ -877,6 +403,15 @@ RsDoMemory32Descriptor ( InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); } + /* Validate the Min/Max/Len/Align values */ + + RsSmallAddressCheck (ACPI_RESOURCE_NAME_MEMORY32, + Descriptor->Memory32.Minimum, + Descriptor->Memory32.Maximum, + Descriptor->Memory32.AddressLength, + Descriptor->Memory32.Alignment, + MinOp, MaxOp, LengthOp, AlignOp); + return (Rnode); } @@ -1027,6 +562,7 @@ RsDoStartDependentDescriptor ( break; default: + NextRnode = RsDoOneResourceDescriptor (InitializerOp, CurrentByteOffset, &State); @@ -1036,7 +572,6 @@ RsDoStartDependentDescriptor ( * must keep track of the offset of not only each descriptor, but each * element (field) within each descriptor as well. */ - CurrentByteOffset += RsLinkDescriptorChain (&PreviousRnode, NextRnode); break; @@ -1182,4 +717,3 @@ RsDoVendorSmallDescriptor ( return (Rnode); } - diff --git a/compiler/aslrestype1i.c b/compiler/aslrestype1i.c new file mode 100644 index 0000000..239c500 --- /dev/null +++ b/compiler/aslrestype1i.c @@ -0,0 +1,668 @@ + +/****************************************************************************** + * + * Module Name: aslrestype1i - Small I/O-related resource descriptors + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + *****************************************************************************/ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype1i") + +/* + * This module contains the I/O-related small resource descriptors: + * + * DMA + * FixedIO + * IO + * IRQ + * IRQNoFlags + */ + +/******************************************************************************* + * + * FUNCTION: RsDoDmaDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "DMA" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoDmaDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + UINT8 DmaChannelMask = 0; + UINT8 DmaChannels = 0; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_DMA)); + + Descriptor = Rnode->Buffer; + Descriptor->Dma.DescriptorType = ACPI_RESOURCE_NAME_DMA | + ASL_RDESC_DMA_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* DMA type */ + + RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DMATYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 5); + break; + + case 1: /* Bus Master */ + + RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_BUSMASTER, + CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 2); + break; + + case 2: /* Xfer Type (transfer width) */ + + RsSetFlagBits (&Descriptor->Dma.Flags, InitializerOp, 0, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_XFERTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Dma.Flags), 0); + break; + + case 3: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + /* All DMA channel bytes are handled here, after flags and name */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Up to 8 channels can be specified in the list */ + + DmaChannels++; + if (DmaChannels > 8) + { + AslError (ASL_ERROR, ASL_MSG_DMA_LIST, + InitializerOp, NULL); + return (Rnode); + } + + /* Only DMA channels 0-7 are allowed (mask is 8 bits) */ + + if (InitializerOp->Asl.Value.Integer > 7) + { + AslError (ASL_ERROR, ASL_MSG_DMA_CHANNEL, + InitializerOp, NULL); + } + + /* Build the mask */ + + DmaChannelMask |= + (1 << ((UINT8) InitializerOp->Asl.Value.Integer)); + } + + if (i == 4) /* case 4: First DMA byte */ + { + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateByteField (InitializerOp, ACPI_RESTAG_DMA, + CurrentByteOffset + + ASL_RESDESC_OFFSET (Dma.DmaChannelMask)); + } + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Now we can set the channel mask */ + + Descriptor->Dma.DmaChannelMask = DmaChannelMask; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoFixedIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "FixedIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoFixedIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *AddressOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_FIXED_IO)); + + Descriptor = Rnode->Buffer; + Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_FIXED_IO | + ASL_RDESC_FIXED_IO_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Base Address */ + + Descriptor->FixedIo.Address = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_BASEADDRESS, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.Address)); + AddressOp = InitializerOp; + break; + + case 1: /* Length */ + + Descriptor->FixedIo.AddressLength = + (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (FixedIo.AddressLength)); + break; + + case 2: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Error checks */ + + if (Descriptor->FixedIo.Address > 0x03FF) + { + AslError (ASL_WARNING, ASL_MSG_ISA_ADDRESS, AddressOp, NULL); + } + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "IO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *AlignOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IO)); + + Descriptor = Rnode->Buffer; + Descriptor->Io.DescriptorType = ACPI_RESOURCE_NAME_IO | + ASL_RDESC_IO_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Decode size */ + + RsSetFlagBits (&Descriptor->Io.Flags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Flags), 0); + break; + + case 1: /* Min Address */ + + Descriptor->Io.Minimum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Minimum)); + MinOp = InitializerOp; + break; + + case 2: /* Max Address */ + + Descriptor->Io.Maximum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Maximum)); + MaxOp = InitializerOp; + break; + + case 3: /* Alignment */ + + Descriptor->Io.Alignment = + (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_ALIGNMENT, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.Alignment)); + AlignOp = InitializerOp; + break; + + case 4: /* Length */ + + Descriptor->Io.AddressLength = + (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Io.AddressLength)); + LengthOp = InitializerOp; + break; + + case 5: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Align values */ + + RsSmallAddressCheck (ACPI_RESOURCE_NAME_IO, + Descriptor->Io.Minimum, + Descriptor->Io.Maximum, + Descriptor->Io.AddressLength, + Descriptor->Io.Alignment, + MinOp, MaxOp, LengthOp, AlignOp); + + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoIrqDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "IRQ" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoIrqDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT32 Interrupts = 0; + UINT16 IrqMask = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ)); + + /* Length = 3 (with flag byte) */ + + Descriptor = Rnode->Buffer; + Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ | + (ASL_RDESC_IRQ_SIZE + 0x01); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Interrupt Type (or Mode - edge/level) */ + + RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 0); + break; + + case 1: /* Interrupt Level (or Polarity - Active high/low) */ + + RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTLEVEL, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 3); + break; + + case 2: /* Share Type - Default: exclusive (0) */ + + RsSetFlagBits (&Descriptor->Irq.Flags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_INTERRUPTSHARE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.Flags), 4); + break; + + case 3: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + /* All IRQ bytes are handled here, after the flags and name */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Up to 16 interrupts can be specified in the list */ + + Interrupts++; + if (Interrupts > 16) + { + AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST, + InitializerOp, NULL); + return (Rnode); + } + + /* Only interrupts 0-15 are allowed (mask is 16 bits) */ + + if (InitializerOp->Asl.Value.Integer > 15) + { + AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER, + InitializerOp, NULL); + } + else + { + IrqMask |= (1 << (UINT8) InitializerOp->Asl.Value.Integer); + } + } + + /* Case 4: First IRQ value in list */ + + if (i == 4) + { + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask)); + } + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Now we can set the channel mask */ + + Descriptor->Irq.IrqMask = IrqMask; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoIrqNoFlagsDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a short "IRQNoFlags" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoIrqNoFlagsDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ASL_RESOURCE_NODE *Rnode; + UINT16 IrqMask = 0; + UINT32 Interrupts = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_IRQ_NOFLAGS)); + + Descriptor = Rnode->Buffer; + Descriptor->Irq.DescriptorType = ACPI_RESOURCE_NAME_IRQ | + ASL_RDESC_IRQ_SIZE; + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Name */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + /* IRQ bytes are handled here, after the flags and name */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Up to 16 interrupts can be specified in the list */ + + Interrupts++; + if (Interrupts > 16) + { + AslError (ASL_ERROR, ASL_MSG_INTERRUPT_LIST, + InitializerOp, NULL); + return (Rnode); + } + + /* Only interrupts 0-15 are allowed (mask is 16 bits) */ + + if (InitializerOp->Asl.Value.Integer > 15) + { + AslError (ASL_ERROR, ASL_MSG_INTERRUPT_NUMBER, + InitializerOp, NULL); + } + else + { + IrqMask |= (1 << ((UINT8) InitializerOp->Asl.Value.Integer)); + } + } + + /* Case 1: First IRQ value in list */ + + if (i == 1) + { + /* Check now for duplicates in list */ + + RsCheckListForDuplicates (InitializerOp); + + /* Create a named field at the start of the list */ + + RsCreateByteField (InitializerOp, ACPI_RESTAG_INTERRUPT, + CurrentByteOffset + ASL_RESDESC_OFFSET (Irq.IrqMask)); + } + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Now we can set the interrupt mask */ + + Descriptor->Irq.IrqMask = IrqMask; + return (Rnode); +} diff --git a/compiler/aslrestype2.c b/compiler/aslrestype2.c index 7ca8eeb..a9aeda7 100644 --- a/compiler/aslrestype2.c +++ b/compiler/aslrestype2.c @@ -1,7 +1,7 @@ /****************************************************************************** * - * Module Name: aslrestype2 - Long (type2) resource templates and descriptors + * Module Name: aslrestype2 - Miscellaneous Large resource descriptors * *****************************************************************************/ @@ -117,2147 +117,22 @@ #include "aslcompiler.h" #include "aslcompiler.y.h" +#include "amlcode.h" #define _COMPONENT ACPI_COMPILER ACPI_MODULE_NAME ("aslrestype2") -/* Local prototypes */ - -static UINT16 -RsGetStringDataLength ( - ACPI_PARSE_OBJECT *InitializerOp); - - -/******************************************************************************* - * - * FUNCTION: RsGetStringDataLength - * - * PARAMETERS: InitializerOp - Start of a subtree of init nodes - * - * RETURN: Valid string length if a string node is found (otherwise 0) - * - * DESCRIPTION: In a list of peer nodes, find the first one that contains a - * string and return the length of the string. - * - ******************************************************************************/ - -static UINT16 -RsGetStringDataLength ( - ACPI_PARSE_OBJECT *InitializerOp) -{ - - while (InitializerOp) - { - if (InitializerOp->Asl.ParseOpcode == PARSEOP_STRING_LITERAL) - { - return ((UINT16) (strlen (InitializerOp->Asl.Value.String) + 1)); - } - InitializerOp = ASL_GET_PEER_NODE (InitializerOp); - } - - return 0; -} - - -/******************************************************************************* - * - * FUNCTION: RsDoDwordIoDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "DwordIO" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoDwordIoDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; - UINT8 *OptionalFields; - UINT32 i; - BOOLEAN ResSourceIndex = FALSE; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; - Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); - Descriptor->Address32.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS32) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); - break; - - case 1: /* MinType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); - break; - - case 2: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); - break; - - case 3: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); - break; - - case 4: /* Range Type */ - - RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 3); - RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0); - break; - - case 5: /* Address Granularity */ - - Descriptor->Address32.Granularity = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); - break; - - case 6: /* Address Min */ - - Descriptor->Address32.Minimum = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); - break; - - case 7: /* Address Max */ - - Descriptor->Address32.Maximum = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); - break; - - case 8: /* Translation Offset */ - - Descriptor->Address32.TranslationOffset = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); - break; - - case 9: /* Address Length */ - - Descriptor->Address32.AddressLength = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); - break; - - case 10: /* ResSourceIndex [Optional Field - BYTE] */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - /* Found a valid ResourceSourceIndex */ - - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address32.ResourceLength++; - ResSourceIndex = TRUE; - } - break; - - case 11: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - /* Found a valid ResourceSource */ - - Descriptor->Address32.ResourceLength = (UINT16) - (Descriptor->Address32.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ - - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } - -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, - InitializerOp, NULL); - } -#endif - break; - - case 12: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - case 13: /* Type */ - - RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 4, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 4); - break; - - case 14: /* Translation Type */ - - RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + - OptionIndex + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoDwordMemoryDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "DwordMemory" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoDwordMemoryDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT8 *OptionalFields; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; - UINT32 i; - BOOLEAN ResSourceIndex = FALSE; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; - Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); - Descriptor->Address32.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS32) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); - break; - - case 1: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); - break; - - case 2: /* MinType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); - break; - - case 3: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); - break; - - case 4: /* Memory Type */ - - RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 1); - break; - - case 5: /* Read/Write Type */ - - RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 1); - RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0); - break; - - case 6: /* Address Granularity */ - - Descriptor->Address32.Granularity = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); - break; - - case 7: /* Min Address */ - - Descriptor->Address32.Minimum = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); - break; - - case 8: /* Max Address */ - - Descriptor->Address32.Maximum = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); - break; - - case 9: /* Translation Offset */ - - Descriptor->Address32.TranslationOffset = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); - break; - - case 10: /* Address Length */ - - Descriptor->Address32.AddressLength = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); - break; - - case 11: /* ResSourceIndex [Optional Field - BYTE] */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address32.ResourceLength++; - ResSourceIndex = TRUE; - } - break; - - case 12: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - Descriptor->Address32.ResourceLength = (UINT16) - (Descriptor->Address32.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ - - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } - -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, - InitializerOp, NULL); - } -#endif - break; - - case 13: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - - case 14: /* Address Range */ - - RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 3); - break; - - case 15: /* Type */ - - RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + - OptionIndex + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoDwordSpaceDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "DwordSpace" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoDwordSpaceDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT8 *OptionalFields; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; - UINT32 i; - BOOLEAN ResSourceIndex = FALSE; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); - Descriptor->Address32.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS32) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Type */ - - Descriptor->Address32.ResourceType = - (UINT8) InitializerOp->Asl.Value.Integer; - break; - - case 1: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); - break; - - case 2: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); - break; - - case 3: /* MinType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); - break; - - case 4: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); - break; - - case 5: /* Type-Specific flags */ - - Descriptor->Address32.SpecificFlags = - (UINT8) InitializerOp->Asl.Value.Integer; - break; - - case 6: /* Address Granularity */ - - Descriptor->Address32.Granularity = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); - break; - - case 7: /* Min Address */ - - Descriptor->Address32.Minimum = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); - break; - - case 8: /* Max Address */ - - Descriptor->Address32.Maximum = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); - break; - - case 9: /* Translation Offset */ - - Descriptor->Address32.TranslationOffset = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); - break; - - case 10: /* Address Length */ - - Descriptor->Address32.AddressLength = - (UINT32) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); - break; - - case 11: /* ResSourceIndex [Optional Field - BYTE] */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address32.ResourceLength++; - ResSourceIndex = TRUE; - } - break; - - case 12: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - Descriptor->Address32.ResourceLength = (UINT16) - (Descriptor->Address32.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ - - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } - -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, - InitializerOp, NULL); - } -#endif - break; - - case 13: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, - InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + - OptionIndex + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoExtendedIoDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "ExtendedIO" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoExtendedIoDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT16 StringLength = 0; - UINT32 i; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; - Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; - Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; - - Descriptor->ExtAddress64.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); - break; - - case 1: /* MinType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); - break; - - case 2: /* MaxType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); - break; - - case 3: /* DecodeType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); - break; - - case 4: /* Range Type */ - - RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 3); - RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0); - break; - - case 5: /* Address Granularity */ - - Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); - break; - - case 6: /* Address Min */ - - Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); - break; - - case 7: /* Address Max */ - - Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); - break; - - case 8: /* Translation Offset */ - - Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); - break; - - case 9: /* Address Length */ - - Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); - break; - - case 10: /* Type-Specific Attributes */ - - Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); - break; - - case 11: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - case 12: /* Type */ - - RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 4, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 4); - break; - - case 13: /* Translation Type */ - - RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoExtendedMemoryDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "ExtendedMemory" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoExtendedMemoryDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT16 StringLength = 0; - UINT32 i; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; - Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; - Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; - - Descriptor->ExtAddress64.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); - break; - - case 1: /* DecodeType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); - break; - - case 2: /* MinType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); - break; - - case 3: /* MaxType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); - break; - - case 4: /* Memory Type */ - - RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 1); - break; - - case 5: /* Read/Write Type */ - - RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 1); - RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0); - break; - - case 6: /* Address Granularity */ - - Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); - break; - - case 7: /* Min Address */ - - Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); - break; - - case 8: /* Max Address */ - - Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); - break; - - case 9: /* Translation Offset */ - - Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); - break; - - case 10: /* Address Length */ - - Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); - break; - - case 11: /* Type-Specific Attributes */ - - Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); - break; - - case 12: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - - case 13: /* Address Range */ - - RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 3); - break; - - case 14: /* Type */ - - RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoExtendedSpaceDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "ExtendedSpace" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoExtendedSpaceDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT16 StringLength = 0; - UINT32 i; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; - Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; - - Descriptor->ExtAddress64.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Type */ - - Descriptor->ExtAddress64.ResourceType = - (UINT8) InitializerOp->Asl.Value.Integer; - break; - - case 1: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); - break; - - case 2: /* DecodeType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); - break; - - case 3: /* MinType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); - break; - - case 4: /* MaxType */ - - RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); - break; - - case 5: /* Type-Specific flags */ - - Descriptor->ExtAddress64.SpecificFlags = - (UINT8) InitializerOp->Asl.Value.Integer; - break; - - case 6: /* Address Granularity */ - - Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); - break; - - case 7: /* Min Address */ - - Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); - break; - - case 8: /* Max Address */ - - Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); - break; - - case 9: /* Translation Offset */ - - Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); - break; - - case 10: /* Address Length */ - - Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); - break; - - case 11: /* Type-Specific Attributes */ - - Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, - CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); - break; - - case 12: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoQwordIoDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "QwordIO" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoQwordIoDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT8 *OptionalFields; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; - UINT32 i; - BOOLEAN ResSourceIndex = FALSE; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; - Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); - Descriptor->Address64.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS64) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); - break; - - case 1: /* MinType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); - break; - - case 2: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); - break; - - case 3: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); - break; - - case 4: /* Range Type */ - - RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 3); - RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0); - break; - - case 5: /* Address Granularity */ - - Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); - break; - - case 6: /* Address Min */ - - Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); - break; - - case 7: /* Address Max */ - - Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); - break; - - case 8: /* Translation Offset */ - - Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); - break; - - case 9: /* Address Length */ - - Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); - break; - - case 10: /* ResSourceIndex [Optional Field - BYTE] */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address64.ResourceLength++; - ResSourceIndex = TRUE; - } - break; - - case 11: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - Descriptor->Address64.ResourceLength = (UINT16) - (Descriptor->Address64.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ - - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } - -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, - InitializerOp, NULL); - } -#endif - break; - - case 12: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - case 13: /* Type */ - - RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 4, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 4); - break; - - case 14: /* Translation Type */ - - RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + - OptionIndex + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoQwordMemoryDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "QwordMemory" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoQwordMemoryDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT8 *OptionalFields; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; - UINT32 i; - BOOLEAN ResSourceIndex = FALSE; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; - Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); - Descriptor->Address64.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS64) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); - break; - - case 1: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); - break; - - case 2: /* MinType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); - break; - - case 3: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); - break; - - case 4: /* Memory Type */ - - RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 1); - break; - - case 5: /* Read/Write Type */ - - RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 1); - RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0); - break; - - case 6: /* Address Granularity */ - - Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); - break; - - case 7: /* Min Address */ - - Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); - break; - - case 8: /* Max Address */ - - Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); - break; - - case 9: /* Translation Offset */ - - Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); - break; - - case 10: /* Address Length */ - - Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); - break; - - case 11: /* ResSourceIndex [Optional Field - BYTE] */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address64.ResourceLength++; - ResSourceIndex = TRUE; - } - break; - - case 12: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - Descriptor->Address64.ResourceLength = (UINT16) - (Descriptor->Address64.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ - - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } - -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, - InitializerOp, NULL); - } -#endif - break; - - case 13: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - - case 14: /* Address Range */ - - RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 3); - break; - - case 15: /* Type */ - - RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + - OptionIndex + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoQwordSpaceDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "QwordSpace" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoQwordSpaceDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT8 *OptionalFields; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; - UINT32 i; - BOOLEAN ResSourceIndex = FALSE; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); - Descriptor->Address64.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS64) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Type */ - - Descriptor->Address64.ResourceType = - (UINT8) InitializerOp->Asl.Value.Integer; - break; - - case 1: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); - break; - - case 2: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); - break; - - case 3: /* MinType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); - break; - - case 4: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); - break; - - case 5: /* Type-Specific flags */ - - Descriptor->Address64.SpecificFlags = - (UINT8) InitializerOp->Asl.Value.Integer; - break; - - case 6: /* Address Granularity */ - - Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); - break; - - case 7: /* Min Address */ - - Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); - break; - - case 8: /* Max Address */ - - Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); - break; - - case 9: /* Translation Offset */ - - Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); - break; - - case 10: /* Address Length */ - - Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); - break; - - case 11: /* ResSourceIndex [Optional Field - BYTE] */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address64.ResourceLength++; - ResSourceIndex = TRUE; - } - break; - - case 12: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - Descriptor->Address64.ResourceLength = (UINT16) - (Descriptor->Address64.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ - - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } - -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, - InitializerOp, NULL); - } -#endif - break; - - case 13: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + - OptionIndex + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoWordIoDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "WordIO" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoWordIoDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT8 *OptionalFields; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; - UINT32 i; - BOOLEAN ResSourceIndex = FALSE; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; - Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); - Descriptor->Address16.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS16) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); - break; - - case 1: /* MinType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); - break; - - case 2: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); - break; - - case 3: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); - break; - - case 4: /* Range Type */ - - RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 0, 3); - RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 0); - break; - - case 5: /* Address Granularity */ - - Descriptor->Address16.Granularity = (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); - break; - - case 6: /* Address Min */ - - Descriptor->Address16.Minimum = (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); - break; - - case 7: /* Address Max */ - - Descriptor->Address16.Maximum = (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); - break; - - case 8: /* Translation Offset */ - - Descriptor->Address16.TranslationOffset = (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); - break; - - case 9: /* Address Length */ - - Descriptor->Address16.AddressLength = (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); - break; - - case 10: /* ResSourceIndex [Optional Field - BYTE] */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address16.ResourceLength++; - ResSourceIndex = TRUE; - } - break; - - case 11: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - Descriptor->Address16.ResourceLength = (UINT16) - (Descriptor->Address16.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ - - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } - -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, - InitializerOp, NULL); - } -#endif - break; - - case 12: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - case 13: /* Type */ - - RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 4, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 4); - break; - - case 14: /* Translation Type */ - - RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 5, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 5); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + - OptionIndex + StringLength; - return (Rnode); -} - - -/******************************************************************************* - * - * FUNCTION: RsDoWordBusNumberDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "WordBusNumber" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoWordBusNumberDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT8 *OptionalFields; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; - UINT32 i; - BOOLEAN ResSourceIndex = FALSE; - - - InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); - - Descriptor = Rnode->Buffer; - Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; - Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_BUS_NUMBER_RANGE; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); - Descriptor->Address16.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS16) - - sizeof (AML_RESOURCE_LARGE_HEADER)); - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); - break; - - case 1: /* MinType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); - break; - - case 2: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); - break; - - case 3: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); - break; - - case 4: /* Address Granularity */ - - Descriptor->Address16.Granularity = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); - break; - - case 5: /* Min Address */ - - Descriptor->Address16.Minimum = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); - break; - - case 6: /* Max Address */ - - Descriptor->Address16.Maximum = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); - break; - - case 7: /* Translation Offset */ - - Descriptor->Address16.TranslationOffset = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); - break; - - case 8: /* Address Length */ - - Descriptor->Address16.AddressLength = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); - break; - - case 9: /* ResSourceIndex [Optional Field - BYTE] */ - - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address16.ResourceLength++; - ResSourceIndex = TRUE; - } - break; - - case 10: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - Descriptor->Address16.ResourceLength = (UINT16) - (Descriptor->Address16.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ - - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } - -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, - InitializerOp, NULL); - } -#endif - break; - - case 11: /* ResourceTag */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + - OptionIndex + StringLength; - return (Rnode); -} - +/* + * This module contains miscellaneous large resource descriptors: + * + * Register + * Interrupt + * VendorLong + */ /******************************************************************************* * - * FUNCTION: RsDoWordSpaceDescriptor + * FUNCTION: RsDoGeneralRegisterDescriptor * * PARAMETERS: Op - Parent resource descriptor parse node * CurrentByteOffset - Offset into the resource template AML @@ -2265,42 +140,27 @@ RsDoWordBusNumberDescriptor ( * * RETURN: Completed resource node * - * DESCRIPTION: Construct a long "WordSpace" descriptor + * DESCRIPTION: Construct a long "Register" descriptor * ******************************************************************************/ ASL_RESOURCE_NODE * -RsDoWordSpaceDescriptor ( +RsDoGeneralRegisterDescriptor ( ACPI_PARSE_OBJECT *Op, UINT32 CurrentByteOffset) { AML_RESOURCE *Descriptor; ACPI_PARSE_OBJECT *InitializerOp; ASL_RESOURCE_NODE *Rnode; - UINT8 *OptionalFields; - UINT16 StringLength = 0; - UINT32 OptionIndex = 0; UINT32 i; - BOOLEAN ResSourceIndex = FALSE; InitializerOp = Op->Asl.Child; - StringLength = RsGetStringDataLength (InitializerOp); - - Rnode = RsAllocateResourceNode ( - sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); + Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_GENERIC_REGISTER)); Descriptor = Rnode->Buffer; - Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; - - /* - * Initial descriptor length -- may be enlarged if there are - * optional fields present - */ - OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); - Descriptor->Address16.ResourceLength = (UINT16) - (sizeof (AML_RESOURCE_ADDRESS16) - - sizeof (AML_RESOURCE_LARGE_HEADER)); + Descriptor->GenericReg.DescriptorType = ACPI_RESOURCE_NAME_GENERIC_REGISTER; + Descriptor->GenericReg.ResourceLength = 12; /* Process all child initialization nodes */ @@ -2308,133 +168,48 @@ RsDoWordSpaceDescriptor ( { switch (i) { - case 0: /* Resource Type */ - - Descriptor->Address16.ResourceType = - (UINT8) InitializerOp->Asl.Value.Integer; - break; - - case 1: /* Resource Usage */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); - break; - - case 2: /* DecodeType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); - break; - - case 3: /* MinType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); - break; - - case 4: /* MaxType */ - - RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); - RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); - break; - - case 5: /* Type-Specific flags */ - - Descriptor->Address16.SpecificFlags = - (UINT8) InitializerOp->Asl.Value.Integer; - break; - - case 6: /* Address Granularity */ - - Descriptor->Address16.Granularity = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); - break; - - case 7: /* Min Address */ - - Descriptor->Address16.Minimum = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); - break; - - case 8: /* Max Address */ + case 0: /* Address space */ - Descriptor->Address16.Maximum = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); - break; + Descriptor->GenericReg.AddressSpaceId = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESSSPACE, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AddressSpaceId)); + break; - case 9: /* Translation Offset */ + case 1: /* Register Bit Width */ - Descriptor->Address16.TranslationOffset = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); + Descriptor->GenericReg.BitWidth = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITWIDTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitWidth)); break; - case 10: /* Address Length */ + case 2: /* Register Bit Offset */ - Descriptor->Address16.AddressLength = - (UINT16) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); + Descriptor->GenericReg.BitOffset = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITOFFSET, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitOffset)); break; - case 11: /* ResSourceIndex [Optional Field - BYTE] */ + case 3: /* Register Address */ - if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) - { - OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; - OptionIndex++; - Descriptor->Address16.ResourceLength++; - ResSourceIndex = TRUE; - } + Descriptor->GenericReg.Address = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESS, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.Address)); break; - case 12: /* ResSource [Optional Field - STRING] */ - - if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && - (InitializerOp->Asl.Value.String)) - { - if (StringLength) - { - Descriptor->Address16.ResourceLength = (UINT16) - (Descriptor->Address16.ResourceLength + StringLength); - - strcpy ((char *) - &OptionalFields[OptionIndex], - InitializerOp->Asl.Value.String); - - /* ResourceSourceIndex must also be valid */ + case 4: /* Access Size (ACPI 3.0) */ - if (!ResSourceIndex) - { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, - InitializerOp, NULL); - } - } - } + Descriptor->GenericReg.AccessSize = (UINT8) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_ACCESSSIZE, + CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AccessSize)); -#if 0 - /* - * Not a valid ResourceSource, ResourceSourceIndex must also - * be invalid - */ - else if (ResSourceIndex) + if (Descriptor->GenericReg.AccessSize > AML_FIELD_ACCESS_QWORD) { - AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + AslError (ASL_ERROR, ASL_MSG_INVALID_ACCESS_SIZE, InitializerOp, NULL); } -#endif break; - case 13: /* ResourceTag */ + case 5: /* ResourceTag (ACPI 3.0b) */ UtAttachNamepathToOwner (Op, InitializerOp); break; @@ -2447,9 +222,6 @@ RsDoWordSpaceDescriptor ( InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); } - - Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + - OptionIndex + StringLength; return (Rnode); } @@ -2760,95 +532,3 @@ RsDoVendorLargeDescriptor ( return (Rnode); } - - -/******************************************************************************* - * - * FUNCTION: RsDoGeneralRegisterDescriptor - * - * PARAMETERS: Op - Parent resource descriptor parse node - * CurrentByteOffset - Offset into the resource template AML - * buffer (to track references to the desc) - * - * RETURN: Completed resource node - * - * DESCRIPTION: Construct a long "Register" descriptor - * - ******************************************************************************/ - -ASL_RESOURCE_NODE * -RsDoGeneralRegisterDescriptor ( - ACPI_PARSE_OBJECT *Op, - UINT32 CurrentByteOffset) -{ - AML_RESOURCE *Descriptor; - ACPI_PARSE_OBJECT *InitializerOp; - ASL_RESOURCE_NODE *Rnode; - UINT32 i; - - - InitializerOp = Op->Asl.Child; - Rnode = RsAllocateResourceNode (sizeof (AML_RESOURCE_GENERIC_REGISTER)); - - Descriptor = Rnode->Buffer; - Descriptor->GenericReg.DescriptorType = ACPI_RESOURCE_NAME_GENERIC_REGISTER; - Descriptor->GenericReg.ResourceLength = 12; - - /* Process all child initialization nodes */ - - for (i = 0; InitializerOp; i++) - { - switch (i) - { - case 0: /* Address space */ - - Descriptor->GenericReg.AddressSpaceId = (UINT8) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESSSPACE, - CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AddressSpaceId)); - break; - - case 1: /* Register Bit Width */ - - Descriptor->GenericReg.BitWidth = (UINT8) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITWIDTH, - CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitWidth)); - break; - - case 2: /* Register Bit Offset */ - - Descriptor->GenericReg.BitOffset = (UINT8) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_REGISTERBITOFFSET, - CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.BitOffset)); - break; - - case 3: /* Register Address */ - - Descriptor->GenericReg.Address = InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_ADDRESS, - CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.Address)); - break; - - case 4: /* Access Size (ACPI 3.0) */ - - Descriptor->GenericReg.AccessSize = (UINT8) InitializerOp->Asl.Value.Integer; - RsCreateByteField (InitializerOp, ACPI_RESTAG_ACCESSSIZE, - CurrentByteOffset + ASL_RESDESC_OFFSET (GenericReg.AccessSize)); - break; - - case 5: /* ResourceTag (ACPI 3.0b) */ - - UtAttachNamepathToOwner (Op, InitializerOp); - break; - - default: - - AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); - break; - } - - InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); - } - return (Rnode); -} - - diff --git a/compiler/aslrestype2d.c b/compiler/aslrestype2d.c new file mode 100644 index 0000000..7725bf9 --- /dev/null +++ b/compiler/aslrestype2d.c @@ -0,0 +1,814 @@ + +/****************************************************************************** + * + * Module Name: aslrestype2d - Large DWord address resource descriptors + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + *****************************************************************************/ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2d") + +/* + * This module contains the Dword (32-bit) address space descriptors: + * + * DwordIO + * DwordMemory + * DwordSpace + */ + +/******************************************************************************* + * + * FUNCTION: RsDoDwordIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "DwordIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoDwordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT8 *OptionalFields; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; + Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); + Descriptor->Address32.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS32) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); + break; + + case 4: /* Range Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 3); + RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0); + break; + + case 5: /* Address Granularity */ + + Descriptor->Address32.Granularity = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); + GranOp = InitializerOp; + break; + + case 6: /* Address Min */ + + Descriptor->Address32.Minimum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); + MinOp = InitializerOp; + break; + + case 7: /* Address Max */ + + Descriptor->Address32.Maximum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); + MaxOp = InitializerOp; + break; + + case 8: /* Translation Offset */ + + Descriptor->Address32.TranslationOffset = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); + break; + + case 9: /* Address Length */ + + Descriptor->Address32.AddressLength = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); + LengthOp = InitializerOp; + break; + + case 10: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + /* Found a valid ResourceSourceIndex */ + + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address32.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 11: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + /* Found a valid ResourceSource */ + + Descriptor->Address32.ResourceLength = (UINT16) + (Descriptor->Address32.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 13: /* Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 4); + break; + + case 14: /* Translation Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address32.Minimum, + Descriptor->Address32.Maximum, + Descriptor->Address32.AddressLength, + Descriptor->Address32.Granularity, + Descriptor->Address32.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoDwordMemoryDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "DwordMemory" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoDwordMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; + Descriptor->Address32.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); + Descriptor->Address32.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS32) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); + break; + + case 1: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); + break; + + case 2: /* MinType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); + break; + + case 3: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); + break; + + case 4: /* Memory Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 1); + break; + + case 5: /* Read/Write Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 0); + break; + + case 6: /* Address Granularity */ + + Descriptor->Address32.Granularity = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address32.Minimum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address32.Maximum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address32.TranslationOffset = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address32.AddressLength = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address32.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address32.ResourceLength = (UINT16) + (Descriptor->Address32.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + + case 14: /* Address Range */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 3); + break; + + case 15: /* Type */ + + RsSetFlagBits (&Descriptor->Address32.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address32.Minimum, + Descriptor->Address32.Maximum, + Descriptor->Address32.AddressLength, + Descriptor->Address32.Granularity, + Descriptor->Address32.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoDwordSpaceDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "DwordSpace" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoDwordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS32) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address32.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS32; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS32); + Descriptor->Address32.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS32) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Type */ + + Descriptor->Address32.ResourceType = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 1: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 0, 1); + break; + + case 2: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 1); + break; + + case 3: /* MinType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 2); + break; + + case 4: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address32.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Flags), 3); + break; + + case 5: /* Type-Specific flags */ + + Descriptor->Address32.SpecificFlags = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 6: /* Address Granularity */ + + Descriptor->Address32.Granularity = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address32.Minimum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address32.Maximum = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address32.TranslationOffset = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address32.AddressLength = + (UINT32) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address32.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address32.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address32.ResourceLength = (UINT16) + (Descriptor->Address32.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, + InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address32.Minimum, + Descriptor->Address32.Maximum, + Descriptor->Address32.AddressLength, + Descriptor->Address32.Granularity, + Descriptor->Address32.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS32) + + OptionIndex + StringLength; + return (Rnode); +} diff --git a/compiler/aslrestype2e.c b/compiler/aslrestype2e.c new file mode 100644 index 0000000..46f56ce --- /dev/null +++ b/compiler/aslrestype2e.c @@ -0,0 +1,646 @@ + +/****************************************************************************** + * + * Module Name: aslrestype2e - Large Extended address resource descriptors + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + *****************************************************************************/ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2e") + +/* + * This module contains the Extended (64-bit) address space descriptors: + * + * ExtendedIO + * ExtendedMemory + * ExtendedSpace + */ + +/******************************************************************************* + * + * FUNCTION: RsDoExtendedIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "ExtendedIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoExtendedIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; + Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; + Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; + + Descriptor->ExtAddress64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); + break; + + case 4: /* Range Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 3); + RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0); + break; + + case 5: /* Address Granularity */ + + Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); + GranOp = InitializerOp; + break; + + case 6: /* Address Min */ + + Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); + MinOp = InitializerOp; + break; + + case 7: /* Address Max */ + + Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); + MaxOp = InitializerOp; + break; + + case 8: /* Translation Offset */ + + Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); + break; + + case 9: /* Address Length */ + + Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 10: /* Type-Specific Attributes */ + + Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); + break; + + case 11: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 12: /* Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 4); + break; + + case 13: /* Translation Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->ExtAddress64.Minimum, + Descriptor->ExtAddress64.Maximum, + Descriptor->ExtAddress64.AddressLength, + Descriptor->ExtAddress64.Granularity, + Descriptor->ExtAddress64.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoExtendedMemoryDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "ExtendedMemory" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoExtendedMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; + Descriptor->ExtAddress64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; + Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; + + Descriptor->ExtAddress64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); + break; + + case 1: /* DecodeType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); + break; + + case 2: /* MinType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); + break; + + case 3: /* MaxType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); + break; + + case 4: /* Memory Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 1); + break; + + case 5: /* Read/Write Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 0); + break; + + case 6: /* Address Granularity */ + + Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* Type-Specific Attributes */ + + Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + + case 13: /* Address Range */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 3); + break; + + case 14: /* Type */ + + RsSetFlagBits (&Descriptor->ExtAddress64.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->ExtAddress64.Minimum, + Descriptor->ExtAddress64.Maximum, + Descriptor->ExtAddress64.AddressLength, + Descriptor->ExtAddress64.Granularity, + Descriptor->ExtAddress64.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoExtendedSpaceDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "ExtendedSpace" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoExtendedSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT16 StringLength = 0; + UINT32 i; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->ExtAddress64.DescriptorType = ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64; + Descriptor->ExtAddress64.RevisionID = AML_RESOURCE_EXTENDED_ADDRESS_REVISION; + + Descriptor->ExtAddress64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Type */ + + Descriptor->ExtAddress64.ResourceType = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 1: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 0, 1); + break; + + case 2: /* DecodeType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 1); + break; + + case 3: /* MinType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 2); + break; + + case 4: /* MaxType */ + + RsSetFlagBits (&Descriptor->ExtAddress64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Flags), 3); + break; + + case 5: /* Type-Specific flags */ + + Descriptor->ExtAddress64.SpecificFlags = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 6: /* Address Granularity */ + + Descriptor->ExtAddress64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->ExtAddress64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->ExtAddress64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->ExtAddress64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->ExtAddress64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* Type-Specific Attributes */ + + Descriptor->ExtAddress64.TypeSpecific = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TYPESPECIFICATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (ExtAddress64.TypeSpecific)); + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->ExtAddress64.Minimum, + Descriptor->ExtAddress64.Maximum, + Descriptor->ExtAddress64.AddressLength, + Descriptor->ExtAddress64.Granularity, + Descriptor->ExtAddress64.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_EXTENDED_ADDRESS64) + StringLength; + return (Rnode); +} diff --git a/compiler/aslrestype2q.c b/compiler/aslrestype2q.c new file mode 100644 index 0000000..591ac25 --- /dev/null +++ b/compiler/aslrestype2q.c @@ -0,0 +1,793 @@ + +/****************************************************************************** + * + * Module Name: aslrestype2q - Large QWord address resource descriptors + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + *****************************************************************************/ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2q") + +/* + * This module contains the QWord (64-bit) address space descriptors: + * + * QWordIO + * QWordMemory + * QWordSpace + */ + +/******************************************************************************* + * + * FUNCTION: RsDoQwordIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "QwordIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoQwordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; + Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); + Descriptor->Address64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); + break; + + case 4: /* Range Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 3); + RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0); + break; + + case 5: /* Address Granularity */ + + Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); + GranOp = InitializerOp; + break; + + case 6: /* Address Min */ + + Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); + MinOp = InitializerOp; + break; + + case 7: /* Address Max */ + + Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); + MaxOp = InitializerOp; + break; + + case 8: /* Translation Offset */ + + Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); + break; + + case 9: /* Address Length */ + + Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 10: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address64.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 11: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address64.ResourceLength = (UINT16) + (Descriptor->Address64.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 13: /* Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 4); + break; + + case 14: /* Translation Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address64.Minimum, + Descriptor->Address64.Maximum, + Descriptor->Address64.AddressLength, + Descriptor->Address64.Granularity, + Descriptor->Address64.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoQwordMemoryDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "QwordMemory" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoQwordMemoryDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; + Descriptor->Address64.ResourceType = ACPI_ADDRESS_TYPE_MEMORY_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); + Descriptor->Address64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); + break; + + case 1: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); + break; + + case 2: /* MinType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); + break; + + case 3: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); + break; + + case 4: /* Memory Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 1); + break; + + case 5: /* Read/Write Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 0, 1); + RsCreateBitField (InitializerOp, ACPI_RESTAG_READWRITETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 0); + break; + + case 6: /* Address Granularity */ + + Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address64.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address64.ResourceLength = (UINT16) + (Descriptor->Address64.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + + case 14: /* Address Range */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MEMATTRIBUTES, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 3); + break; + + case 15: /* Type */ + + RsSetFlagBits (&Descriptor->Address64.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address64.Minimum, + Descriptor->Address64.Maximum, + Descriptor->Address64.AddressLength, + Descriptor->Address64.Granularity, + Descriptor->Address64.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoQwordSpaceDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "QwordSpace" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoQwordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS64) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address64.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS64; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS64); + Descriptor->Address64.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS64) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Type */ + + Descriptor->Address64.ResourceType = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 1: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 0, 1); + break; + + case 2: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 1); + break; + + case 3: /* MinType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 2); + break; + + case 4: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address64.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Flags), 3); + break; + + case 5: /* Type-Specific flags */ + + Descriptor->Address64.SpecificFlags = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 6: /* Address Granularity */ + + Descriptor->Address64.Granularity = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address64.Minimum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address64.Maximum = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address64.TranslationOffset = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address64.AddressLength = InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address64.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address64.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address64.ResourceLength = (UINT16) + (Descriptor->Address64.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address64.Minimum, + Descriptor->Address64.Maximum, + Descriptor->Address64.AddressLength, + Descriptor->Address64.Granularity, + Descriptor->Address64.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS64) + + OptionIndex + StringLength; + return (Rnode); +} diff --git a/compiler/aslrestype2w.c b/compiler/aslrestype2w.c new file mode 100644 index 0000000..45f1858 --- /dev/null +++ b/compiler/aslrestype2w.c @@ -0,0 +1,774 @@ + +/****************************************************************************** + * + * Module Name: aslrestype2w - Large Word address resource descriptors + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + *****************************************************************************/ + + +#include "aslcompiler.h" +#include "aslcompiler.y.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("aslrestype2w") + +/* + * This module contains the Word (16-bit) address space descriptors: + * + * WordIO + * WordMemory + * WordSpace + */ + +/******************************************************************************* + * + * FUNCTION: RsDoWordIoDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "WordIO" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoWordIoDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; + Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_IO_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); + Descriptor->Address16.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS16) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); + break; + + case 4: /* Range Type */ + + RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 0, 3); + RsCreateBitField (InitializerOp, ACPI_RESTAG_RANGETYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 0); + break; + + case 5: /* Address Granularity */ + + Descriptor->Address16.Granularity = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); + GranOp = InitializerOp; + break; + + case 6: /* Address Min */ + + Descriptor->Address16.Minimum = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); + MinOp = InitializerOp; + break; + + case 7: /* Address Max */ + + Descriptor->Address16.Maximum = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); + MaxOp = InitializerOp; + break; + + case 8: /* Translation Offset */ + + Descriptor->Address16.TranslationOffset = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); + break; + + case 9: /* Address Length */ + + Descriptor->Address16.AddressLength = (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); + LengthOp = InitializerOp; + break; + + case 10: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address16.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 11: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address16.ResourceLength = (UINT16) + (Descriptor->Address16.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 12: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + case 13: /* Type */ + + RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 4, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 4); + break; + + case 14: /* Translation Type */ + + RsSetFlagBits (&Descriptor->Address16.SpecificFlags, InitializerOp, 5, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_TRANSTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.SpecificFlags), 5); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address16.Minimum, + Descriptor->Address16.Maximum, + Descriptor->Address16.AddressLength, + Descriptor->Address16.Granularity, + Descriptor->Address16.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoWordBusNumberDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "WordBusNumber" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoWordBusNumberDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; + Descriptor->Address16.ResourceType = ACPI_ADDRESS_TYPE_BUS_NUMBER_RANGE; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); + Descriptor->Address16.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS16) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); + break; + + case 1: /* MinType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); + break; + + case 2: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); + break; + + case 3: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); + break; + + case 4: /* Address Granularity */ + + Descriptor->Address16.Granularity = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); + GranOp = InitializerOp; + break; + + case 5: /* Min Address */ + + Descriptor->Address16.Minimum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); + MinOp = InitializerOp; + break; + + case 6: /* Max Address */ + + Descriptor->Address16.Maximum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); + MaxOp = InitializerOp; + break; + + case 7: /* Translation Offset */ + + Descriptor->Address16.TranslationOffset = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); + break; + + case 8: /* Address Length */ + + Descriptor->Address16.AddressLength = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); + LengthOp = InitializerOp; + break; + + case 9: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address16.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 10: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address16.ResourceLength = (UINT16) + (Descriptor->Address16.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 11: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address16.Minimum, + Descriptor->Address16.Maximum, + Descriptor->Address16.AddressLength, + Descriptor->Address16.Granularity, + Descriptor->Address16.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + + OptionIndex + StringLength; + return (Rnode); +} + + +/******************************************************************************* + * + * FUNCTION: RsDoWordSpaceDescriptor + * + * PARAMETERS: Op - Parent resource descriptor parse node + * CurrentByteOffset - Offset into the resource template AML + * buffer (to track references to the desc) + * + * RETURN: Completed resource node + * + * DESCRIPTION: Construct a long "WordSpace" descriptor + * + ******************************************************************************/ + +ASL_RESOURCE_NODE * +RsDoWordSpaceDescriptor ( + ACPI_PARSE_OBJECT *Op, + UINT32 CurrentByteOffset) +{ + AML_RESOURCE *Descriptor; + ACPI_PARSE_OBJECT *InitializerOp; + ACPI_PARSE_OBJECT *MinOp = NULL; + ACPI_PARSE_OBJECT *MaxOp = NULL; + ACPI_PARSE_OBJECT *LengthOp = NULL; + ACPI_PARSE_OBJECT *GranOp = NULL; + ASL_RESOURCE_NODE *Rnode; + UINT8 *OptionalFields; + UINT16 StringLength = 0; + UINT32 OptionIndex = 0; + UINT32 i; + BOOLEAN ResSourceIndex = FALSE; + + + InitializerOp = Op->Asl.Child; + StringLength = RsGetStringDataLength (InitializerOp); + + Rnode = RsAllocateResourceNode ( + sizeof (AML_RESOURCE_ADDRESS16) + 1 + StringLength); + + Descriptor = Rnode->Buffer; + Descriptor->Address16.DescriptorType = ACPI_RESOURCE_NAME_ADDRESS16; + + /* + * Initial descriptor length -- may be enlarged if there are + * optional fields present + */ + OptionalFields = ((UINT8 *) Descriptor) + sizeof (AML_RESOURCE_ADDRESS16); + Descriptor->Address16.ResourceLength = (UINT16) + (sizeof (AML_RESOURCE_ADDRESS16) - + sizeof (AML_RESOURCE_LARGE_HEADER)); + + /* Process all child initialization nodes */ + + for (i = 0; InitializerOp; i++) + { + switch (i) + { + case 0: /* Resource Type */ + + Descriptor->Address16.ResourceType = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 1: /* Resource Usage */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 0, 1); + break; + + case 2: /* DecodeType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 1, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_DECODE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 1); + break; + + case 3: /* MinType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 2, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MINTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 2); + break; + + case 4: /* MaxType */ + + RsSetFlagBits (&Descriptor->Address16.Flags, InitializerOp, 3, 0); + RsCreateBitField (InitializerOp, ACPI_RESTAG_MAXTYPE, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Flags), 3); + break; + + case 5: /* Type-Specific flags */ + + Descriptor->Address16.SpecificFlags = + (UINT8) InitializerOp->Asl.Value.Integer; + break; + + case 6: /* Address Granularity */ + + Descriptor->Address16.Granularity = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_GRANULARITY, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Granularity)); + GranOp = InitializerOp; + break; + + case 7: /* Min Address */ + + Descriptor->Address16.Minimum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MINADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Minimum)); + MinOp = InitializerOp; + break; + + case 8: /* Max Address */ + + Descriptor->Address16.Maximum = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_MAXADDR, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.Maximum)); + MaxOp = InitializerOp; + break; + + case 9: /* Translation Offset */ + + Descriptor->Address16.TranslationOffset = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_TRANSLATION, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.TranslationOffset)); + break; + + case 10: /* Address Length */ + + Descriptor->Address16.AddressLength = + (UINT16) InitializerOp->Asl.Value.Integer; + RsCreateByteField (InitializerOp, ACPI_RESTAG_LENGTH, + CurrentByteOffset + ASL_RESDESC_OFFSET (Address16.AddressLength)); + LengthOp = InitializerOp; + break; + + case 11: /* ResSourceIndex [Optional Field - BYTE] */ + + if (InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) + { + OptionalFields[0] = (UINT8) InitializerOp->Asl.Value.Integer; + OptionIndex++; + Descriptor->Address16.ResourceLength++; + ResSourceIndex = TRUE; + } + break; + + case 12: /* ResSource [Optional Field - STRING] */ + + if ((InitializerOp->Asl.ParseOpcode != PARSEOP_DEFAULT_ARG) && + (InitializerOp->Asl.Value.String)) + { + if (StringLength) + { + Descriptor->Address16.ResourceLength = (UINT16) + (Descriptor->Address16.ResourceLength + StringLength); + + strcpy ((char *) + &OptionalFields[OptionIndex], + InitializerOp->Asl.Value.String); + + /* ResourceSourceIndex must also be valid */ + + if (!ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_INDEX, + InitializerOp, NULL); + } + } + } + +#if 0 + /* + * Not a valid ResourceSource, ResourceSourceIndex must also + * be invalid + */ + else if (ResSourceIndex) + { + AslError (ASL_ERROR, ASL_MSG_RESOURCE_SOURCE, + InitializerOp, NULL); + } +#endif + break; + + case 13: /* ResourceTag */ + + UtAttachNamepathToOwner (Op, InitializerOp); + break; + + default: + + AslError (ASL_ERROR, ASL_MSG_RESOURCE_LIST, InitializerOp, NULL); + break; + } + + InitializerOp = RsCompleteNodeAndGetNext (InitializerOp); + } + + /* Validate the Min/Max/Len/Gran values */ + + RsLargeAddressCheck ( + Descriptor->Address16.Minimum, + Descriptor->Address16.Maximum, + Descriptor->Address16.AddressLength, + Descriptor->Address16.Granularity, + Descriptor->Address16.Flags, + MinOp, MaxOp, LengthOp, GranOp); + + Rnode->BufferLength = sizeof (AML_RESOURCE_ADDRESS16) + + OptionIndex + StringLength; + return (Rnode); +} diff --git a/compiler/asltypes.h b/compiler/asltypes.h index 30b8fdf..8157634 100644 --- a/compiler/asltypes.h +++ b/compiler/asltypes.h @@ -420,7 +420,16 @@ typedef enum ASL_MSG_SERIALIZED, ASL_MSG_COMPILER_RESERVED, ASL_MSG_NAMED_OBJECT_IN_WHILE, - ASL_MSG_LOCAL_OUTSIDE_METHOD + ASL_MSG_LOCAL_OUTSIDE_METHOD, + ASL_MSG_ALIGNMENT, + ASL_MSG_ISA_ADDRESS, + ASL_MSG_INVALID_MIN_MAX, + ASL_MSG_INVALID_LENGTH, + ASL_MSG_INVALID_LENGTH_FIXED, + ASL_MSG_INVALID_GRANULARITY, + ASL_MSG_INVALID_GRAN_FIXED, + ASL_MSG_INVALID_ACCESS_SIZE, + ASL_MSG_INVALID_ADDR_FLAGS } ASL_MESSAGE_IDS; @@ -540,7 +549,16 @@ char *AslMessages [] = { /* ASL_MSG_SERIALIZED */ "Control Method marked Serialized", /* ASL_MSG_COMPILER_RESERVED */ "Use of compiler reserved name", /* ASL_MSG_NAMED_OBJECT_IN_WHILE */ "Creating a named object in a While loop", -/* ASL_MSG_LOCAL_OUTSIDE_METHOD */ "Local or Arg used outside a control method" +/* ASL_MSG_LOCAL_OUTSIDE_METHOD */ "Local or Arg used outside a control method", +/* ASL_MSG_ALIGNMENT */ "Must be a multiple of alignment/granularity value", +/* ASL_MSG_ISA_ADDRESS */ "Maximum 10-bit ISA address (0x3FF)", +/* ASL_MSG_INVALID_MIN_MAX */ "Address Min is greater than Address Max", +/* ASL_MSG_INVALID_LENGTH */ "Length is larger than Min/Max window", +/* ASL_MSG_INVALID_LENGTH_FIXED */ "Length is not equal to fixed Min/Max window", +/* ASL_MSG_INVALID_GRANULARITY */ "Granularity must be zero or a power of two minus one", +/* ASL_MSG_INVALID_GRAN_FIXED */ "Granularity must be zero for fixed Min/Max", +/* ASL_MSG_INVALID_ACCESS_SIZE */ "Invalid AccessSize (Maximum is 4 - QWord access)", +/* ASL_MSG_INVALID_ADDR_FLAGS */ "Invalid combination of Length and Min/Max fixed flags" }; diff --git a/debugger/dbcmds.c b/debugger/dbcmds.c index 50a8b2e..f8c6496 100644 --- a/debugger/dbcmds.c +++ b/debugger/dbcmds.c @@ -675,7 +675,7 @@ AcpiDbDisplayTableInfo ( /* Walk the entire root table list */ - for (i = 0; i < AcpiGbl_RootTableList.Count; i++) + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { TableDesc = &AcpiGbl_RootTableList.Tables[i]; AcpiOsPrintf ("%d ", i); diff --git a/debugger/dbdisply.c b/debugger/dbdisply.c index ec4715b..a610d80 100644 --- a/debugger/dbdisply.c +++ b/debugger/dbdisply.c @@ -816,6 +816,7 @@ AcpiDbDisplayGpes ( ACPI_GPE_XRUPT_INFO *GpeXruptInfo; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + char *GpeType; UINT32 GpeIndex; UINT32 Block = 0; UINT32 i; @@ -844,8 +845,17 @@ AcpiDbDisplayGpes ( AcpiOsPrintf ("Could not convert name to pathname\n"); } - AcpiOsPrintf ("\nBlock %d - Info %p DeviceNode %p [%s]\n", - Block, GpeBlock, GpeBlock->Node, Buffer); + if (GpeBlock->Node == AcpiGbl_FadtGpeDevice) + { + GpeType = "FADT-defined GPE block"; + } + else + { + GpeType = "GPE Block Device"; + } + + AcpiOsPrintf ("\nBlock %d - Info %p DeviceNode %p [%s] - %s\n", + Block, GpeBlock, GpeBlock->Node, Buffer, GpeType); AcpiOsPrintf (" Registers: %u (%u GPEs)\n", GpeBlock->RegisterCount, GpeBlock->GpeCount); diff --git a/events/evgpe.c b/events/evgpe.c index d3569b1..604f23d 100644 --- a/events/evgpe.c +++ b/events/evgpe.c @@ -370,7 +370,7 @@ AcpiEvGetGpeEventInfo ( ACPI_FUNCTION_ENTRY (); - /* A NULL GpeBlock means use the FADT-defined GPE block(s) */ + /* A NULL GpeDevice means use the FADT-defined GPE block(s) */ if (!GpeDevice) { diff --git a/events/evgpeblk.c b/events/evgpeblk.c index b109673..7214117 100644 --- a/events/evgpeblk.c +++ b/events/evgpeblk.c @@ -124,28 +124,6 @@ /* Local prototypes */ static ACPI_STATUS -AcpiEvMatchGpeMethod ( - ACPI_HANDLE ObjHandle, - UINT32 Level, - void *ObjDesc, - void **ReturnValue); - -static ACPI_STATUS -AcpiEvMatchPrwAndGpe ( - ACPI_HANDLE ObjHandle, - UINT32 Level, - void *Info, - void **ReturnValue); - -static ACPI_GPE_XRUPT_INFO * -AcpiEvGetGpeXruptBlock ( - UINT32 InterruptNumber); - -static ACPI_STATUS -AcpiEvDeleteGpeXrupt ( - ACPI_GPE_XRUPT_INFO *GpeXrupt); - -static ACPI_STATUS AcpiEvInstallGpeBlock ( ACPI_GPE_BLOCK_INFO *GpeBlock, UINT32 InterruptNumber); @@ -157,581 +135,6 @@ AcpiEvCreateGpeInfoBlocks ( /******************************************************************************* * - * FUNCTION: AcpiEvValidGpeEvent - * - * PARAMETERS: GpeEventInfo - Info for this GPE - * - * RETURN: TRUE if the GpeEvent is valid - * - * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL. - * Should be called only when the GPE lists are semaphore locked - * and not subject to change. - * - ******************************************************************************/ - -BOOLEAN -AcpiEvValidGpeEvent ( - ACPI_GPE_EVENT_INFO *GpeEventInfo) -{ - ACPI_GPE_XRUPT_INFO *GpeXruptBlock; - ACPI_GPE_BLOCK_INFO *GpeBlock; - - - ACPI_FUNCTION_ENTRY (); - - - /* No need for spin lock since we are not changing any list elements */ - - /* Walk the GPE interrupt levels */ - - GpeXruptBlock = AcpiGbl_GpeXruptListHead; - while (GpeXruptBlock) - { - GpeBlock = GpeXruptBlock->GpeBlockListHead; - - /* Walk the GPE blocks on this interrupt level */ - - while (GpeBlock) - { - if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) && - (&GpeBlock->EventInfo[GpeBlock->GpeCount] > GpeEventInfo)) - { - return (TRUE); - } - - GpeBlock = GpeBlock->Next; - } - - GpeXruptBlock = GpeXruptBlock->Next; - } - - return (FALSE); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvWalkGpeList - * - * PARAMETERS: GpeWalkCallback - Routine called for each GPE block - * Context - Value passed to callback - * - * RETURN: Status - * - * DESCRIPTION: Walk the GPE lists. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEvWalkGpeList ( - ACPI_GPE_CALLBACK GpeWalkCallback, - void *Context) -{ - ACPI_GPE_BLOCK_INFO *GpeBlock; - ACPI_GPE_XRUPT_INFO *GpeXruptInfo; - ACPI_STATUS Status = AE_OK; - ACPI_CPU_FLAGS Flags; - - - ACPI_FUNCTION_TRACE (EvWalkGpeList); - - - Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); - - /* Walk the interrupt level descriptor list */ - - GpeXruptInfo = AcpiGbl_GpeXruptListHead; - while (GpeXruptInfo) - { - /* Walk all Gpe Blocks attached to this interrupt level */ - - GpeBlock = GpeXruptInfo->GpeBlockListHead; - while (GpeBlock) - { - /* One callback per GPE block */ - - Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context); - if (ACPI_FAILURE (Status)) - { - if (Status == AE_CTRL_END) /* Callback abort */ - { - Status = AE_OK; - } - goto UnlockAndExit; - } - - GpeBlock = GpeBlock->Next; - } - - GpeXruptInfo = GpeXruptInfo->Next; - } - -UnlockAndExit: - AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); - return_ACPI_STATUS (Status); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvDeleteGpeHandlers - * - * PARAMETERS: GpeXruptInfo - GPE Interrupt info - * GpeBlock - Gpe Block info - * - * RETURN: Status - * - * DESCRIPTION: Delete all Handler objects found in the GPE data structs. - * Used only prior to termination. - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEvDeleteGpeHandlers ( - ACPI_GPE_XRUPT_INFO *GpeXruptInfo, - ACPI_GPE_BLOCK_INFO *GpeBlock, - void *Context) -{ - ACPI_GPE_EVENT_INFO *GpeEventInfo; - UINT32 i; - UINT32 j; - - - ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers); - - - /* Examine each GPE Register within the block */ - - for (i = 0; i < GpeBlock->RegisterCount; i++) - { - /* Now look at the individual GPEs in this byte register */ - - for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) - { - GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * - ACPI_GPE_REGISTER_WIDTH) + j]; - - if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_HANDLER) - { - ACPI_FREE (GpeEventInfo->Dispatch.Handler); - GpeEventInfo->Dispatch.Handler = NULL; - GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; - } - } - } - - return_ACPI_STATUS (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvMatchGpeMethod - * - * PARAMETERS: Callback from WalkNamespace - * - * RETURN: Status - * - * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a - * control method under the _GPE portion of the namespace. - * Extract the name and GPE type from the object, saving this - * information for quick lookup during GPE dispatch - * - * The name of each GPE control method is of the form: - * "_Lxx" or "_Exx", where: - * L - means that the GPE is level triggered - * E - means that the GPE is edge triggered - * xx - is the GPE number [in HEX] - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiEvMatchGpeMethod ( - ACPI_HANDLE ObjHandle, - UINT32 Level, - void *ObjDesc, - void **ReturnValue) -{ - ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); - ACPI_GPE_BLOCK_INFO *GpeBlock = (void *) ObjDesc; - ACPI_GPE_EVENT_INFO *GpeEventInfo; - UINT32 GpeNumber; - char Name[ACPI_NAME_SIZE + 1]; - UINT8 Type; - - - ACPI_FUNCTION_TRACE (EvMatchGpeMethod); - - - /* - * Match and decode the _Lxx and _Exx GPE method names - * - * 1) Extract the method name and null terminate it - */ - ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer); - Name[ACPI_NAME_SIZE] = 0; - - /* 2) Name must begin with an underscore */ - - if (Name[0] != '_') - { - return_ACPI_STATUS (AE_OK); /* Ignore this method */ - } - - /* - * 3) Edge/Level determination is based on the 2nd character - * of the method name - * - * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is - * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. - */ - switch (Name[1]) - { - case 'L': - Type = ACPI_GPE_LEVEL_TRIGGERED; - break; - - case 'E': - Type = ACPI_GPE_EDGE_TRIGGERED; - break; - - default: - /* Unknown method type, just ignore it */ - - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, - "Ignoring unknown GPE method type: %s " - "(name not of form _Lxx or _Exx)", Name)); - return_ACPI_STATUS (AE_OK); - } - - /* 4) The last two characters of the name are the hex GPE Number */ - - GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); - if (GpeNumber == ACPI_UINT32_MAX) - { - /* Conversion failed; invalid method, just ignore it */ - - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, - "Could not extract GPE number from name: %s " - "(name is not of form _Lxx or _Exx)", Name)); - return_ACPI_STATUS (AE_OK); - } - - /* Ensure that we have a valid GPE number for this GPE block */ - - GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); - if (!GpeEventInfo) - { - /* - * This GpeNumber is not valid for this GPE block, just ignore it. - * However, it may be valid for a different GPE block, since GPE0 - * and GPE1 methods both appear under \_GPE. - */ - return_ACPI_STATUS (AE_OK); - } - - /* - * Add the GPE information from above to the GpeEventInfo block for - * use during dispatch of this GPE. - */ - GpeEventInfo->Flags = (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); - GpeEventInfo->Dispatch.MethodNode = MethodNode; - - ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, - "Registered GPE method %s as GPE number 0x%.2X\n", - Name, GpeNumber)); - return_ACPI_STATUS (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvMatchPrwAndGpe - * - * PARAMETERS: Callback from WalkNamespace - * - * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is - * not aborted on a single _PRW failure. - * - * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a - * Device. Run the _PRW method. If present, extract the GPE - * number and mark the GPE as a CAN_WAKE GPE. - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiEvMatchPrwAndGpe ( - ACPI_HANDLE ObjHandle, - UINT32 Level, - void *Info, - void **ReturnValue) -{ - ACPI_GPE_WALK_INFO *GpeInfo = (void *) Info; - ACPI_NAMESPACE_NODE *GpeDevice; - ACPI_GPE_BLOCK_INFO *GpeBlock; - ACPI_NAMESPACE_NODE *TargetGpeDevice; - ACPI_GPE_EVENT_INFO *GpeEventInfo; - ACPI_OPERAND_OBJECT *PkgDesc; - ACPI_OPERAND_OBJECT *ObjDesc; - UINT32 GpeNumber; - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe); - - - /* Check for a _PRW method under this device */ - - Status = AcpiUtEvaluateObject (ObjHandle, METHOD_NAME__PRW, - ACPI_BTYPE_PACKAGE, &PkgDesc); - if (ACPI_FAILURE (Status)) - { - /* Ignore all errors from _PRW, we don't want to abort the walk */ - - return_ACPI_STATUS (AE_OK); - } - - /* The returned _PRW package must have at least two elements */ - - if (PkgDesc->Package.Count < 2) - { - goto Cleanup; - } - - /* Extract pointers from the input context */ - - GpeDevice = GpeInfo->GpeDevice; - GpeBlock = GpeInfo->GpeBlock; - - /* - * The _PRW object must return a package, we are only interested in the - * first element - */ - ObjDesc = PkgDesc->Package.Elements[0]; - - if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) - { - /* Use FADT-defined GPE device (from definition of _PRW) */ - - TargetGpeDevice = AcpiGbl_FadtGpeDevice; - - /* Integer is the GPE number in the FADT described GPE blocks */ - - GpeNumber = (UINT32) ObjDesc->Integer.Value; - } - else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) - { - /* Package contains a GPE reference and GPE number within a GPE block */ - - if ((ObjDesc->Package.Count < 2) || - ((ObjDesc->Package.Elements[0])->Common.Type != - ACPI_TYPE_LOCAL_REFERENCE) || - ((ObjDesc->Package.Elements[1])->Common.Type != - ACPI_TYPE_INTEGER)) - { - goto Cleanup; - } - - /* Get GPE block reference and decode */ - - TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node; - GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value; - } - else - { - /* Unknown type, just ignore it */ - - goto Cleanup; - } - - /* - * Is this GPE within this block? - * - * TRUE if and only if these conditions are true: - * 1) The GPE devices match. - * 2) The GPE index(number) is within the range of the Gpe Block - * associated with the GPE device. - */ - if (GpeDevice != TargetGpeDevice) - { - goto Cleanup; - } - - GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); - if (GpeEventInfo) - { - /* This GPE can wake the system */ - - GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; - } - -Cleanup: - AcpiUtRemoveReference (PkgDesc); - return_ACPI_STATUS (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvGetGpeXruptBlock - * - * PARAMETERS: InterruptNumber - Interrupt for a GPE block - * - * RETURN: A GPE interrupt block - * - * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt - * block per unique interrupt level used for GPEs. Should be - * called only when the GPE lists are semaphore locked and not - * subject to change. - * - ******************************************************************************/ - -static ACPI_GPE_XRUPT_INFO * -AcpiEvGetGpeXruptBlock ( - UINT32 InterruptNumber) -{ - ACPI_GPE_XRUPT_INFO *NextGpeXrupt; - ACPI_GPE_XRUPT_INFO *GpeXrupt; - ACPI_STATUS Status; - ACPI_CPU_FLAGS Flags; - - - ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock); - - - /* No need for lock since we are not changing any list elements here */ - - NextGpeXrupt = AcpiGbl_GpeXruptListHead; - while (NextGpeXrupt) - { - if (NextGpeXrupt->InterruptNumber == InterruptNumber) - { - return_PTR (NextGpeXrupt); - } - - NextGpeXrupt = NextGpeXrupt->Next; - } - - /* Not found, must allocate a new xrupt descriptor */ - - GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO)); - if (!GpeXrupt) - { - return_PTR (NULL); - } - - GpeXrupt->InterruptNumber = InterruptNumber; - - /* Install new interrupt descriptor with spin lock */ - - Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); - if (AcpiGbl_GpeXruptListHead) - { - NextGpeXrupt = AcpiGbl_GpeXruptListHead; - while (NextGpeXrupt->Next) - { - NextGpeXrupt = NextGpeXrupt->Next; - } - - NextGpeXrupt->Next = GpeXrupt; - GpeXrupt->Previous = NextGpeXrupt; - } - else - { - AcpiGbl_GpeXruptListHead = GpeXrupt; - } - AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); - - /* Install new interrupt handler if not SCI_INT */ - - if (InterruptNumber != AcpiGbl_FADT.SciInterrupt) - { - Status = AcpiOsInstallInterruptHandler (InterruptNumber, - AcpiEvGpeXruptHandler, GpeXrupt); - if (ACPI_FAILURE (Status)) - { - ACPI_ERROR ((AE_INFO, - "Could not install GPE interrupt handler at level 0x%X", - InterruptNumber)); - return_PTR (NULL); - } - } - - return_PTR (GpeXrupt); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvDeleteGpeXrupt - * - * PARAMETERS: GpeXrupt - A GPE interrupt info block - * - * RETURN: Status - * - * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated - * interrupt handler if not the SCI interrupt. - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiEvDeleteGpeXrupt ( - ACPI_GPE_XRUPT_INFO *GpeXrupt) -{ - ACPI_STATUS Status; - ACPI_CPU_FLAGS Flags; - - - ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt); - - - /* We never want to remove the SCI interrupt handler */ - - if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt) - { - GpeXrupt->GpeBlockListHead = NULL; - return_ACPI_STATUS (AE_OK); - } - - /* Disable this interrupt */ - - Status = AcpiOsRemoveInterruptHandler ( - GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Unlink the interrupt block with lock */ - - Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); - if (GpeXrupt->Previous) - { - GpeXrupt->Previous->Next = GpeXrupt->Next; - } - else - { - /* No previous, update list head */ - - AcpiGbl_GpeXruptListHead = GpeXrupt->Next; - } - - if (GpeXrupt->Next) - { - GpeXrupt->Next->Previous = GpeXrupt->Previous; - } - AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); - - /* Free the block */ - - ACPI_FREE (GpeXrupt); - return_ACPI_STATUS (AE_OK); -} - - -/******************************************************************************* - * * FUNCTION: AcpiEvInstallGpeBlock * * PARAMETERS: GpeBlock - New GPE block @@ -1041,6 +444,7 @@ AcpiEvCreateGpeBlock ( { ACPI_STATUS Status; ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_WALK_INFO WalkInfo; ACPI_FUNCTION_TRACE (EvCreateGpeBlock); @@ -1089,11 +493,16 @@ AcpiEvCreateGpeBlock ( return_ACPI_STATUS (Status); } - /* Find all GPE methods (_Lxx, _Exx) for this block */ + /* Find all GPE methods (_Lxx or_Exx) for this block */ + + WalkInfo.GpeBlock = GpeBlock; + WalkInfo.GpeDevice = GpeDevice; + WalkInfo.EnableThisGpe = FALSE; + WalkInfo.ExecuteByOwnerId = FALSE; Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, - AcpiEvMatchGpeMethod, NULL, GpeBlock, NULL); + AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL); /* Return the new block */ @@ -1139,7 +548,7 @@ AcpiEvInitializeGpeBlock ( { ACPI_STATUS Status; ACPI_GPE_EVENT_INFO *GpeEventInfo; - ACPI_GPE_WALK_INFO GpeInfo; + ACPI_GPE_WALK_INFO WalkInfo; UINT32 WakeGpeCount; UINT32 GpeEnabledCount; UINT32 GpeIndex; @@ -1170,12 +579,13 @@ AcpiEvInitializeGpeBlock ( * definition a wake GPE and will not be enabled while the machine * is running. */ - GpeInfo.GpeBlock = GpeBlock; - GpeInfo.GpeDevice = GpeDevice; + WalkInfo.GpeBlock = GpeBlock; + WalkInfo.GpeDevice = GpeDevice; + WalkInfo.ExecuteByOwnerId = FALSE; Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, - AcpiEvMatchPrwAndGpe, NULL, &GpeInfo, NULL); + AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While executing _PRW methods")); @@ -1238,165 +648,13 @@ AcpiEvInitializeGpeBlock ( } } - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, - "Found %u Wake, Enabled %u Runtime GPEs in this block\n", - WakeGpeCount, GpeEnabledCount)); - - return_ACPI_STATUS (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvGpeInitialize - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initialize the GPE data structures - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEvGpeInitialize ( - void) -{ - UINT32 RegisterCount0 = 0; - UINT32 RegisterCount1 = 0; - UINT32 GpeNumberMax = 0; - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE (EvGpeInitialize); - - - Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* - * Initialize the GPE Block(s) defined in the FADT - * - * Why the GPE register block lengths are divided by 2: From the ACPI - * Spec, section "General-Purpose Event Registers", we have: - * - * "Each register block contains two registers of equal length - * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the - * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN - * The length of the GPE1_STS and GPE1_EN registers is equal to - * half the GPE1_LEN. If a generic register block is not supported - * then its respective block pointer and block length values in the - * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need - * to be the same size." - */ - - /* - * Determine the maximum GPE number for this machine. - * - * Note: both GPE0 and GPE1 are optional, and either can exist without - * the other. - * - * If EITHER the register length OR the block address are zero, then that - * particular block is not supported. - */ - if (AcpiGbl_FADT.Gpe0BlockLength && - AcpiGbl_FADT.XGpe0Block.Address) - { - /* GPE block 0 exists (has both length and address > 0) */ - - RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2); - - GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1; - - /* Install GPE Block 0 */ - - Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, - &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0, - AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]); - - if (ACPI_FAILURE (Status)) - { - ACPI_EXCEPTION ((AE_INFO, Status, - "Could not create GPE Block 0")); - } - } - - if (AcpiGbl_FADT.Gpe1BlockLength && - AcpiGbl_FADT.XGpe1Block.Address) - { - /* GPE block 1 exists (has both length and address > 0) */ - - RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2); - - /* Check for GPE0/GPE1 overlap (if both banks exist) */ - - if ((RegisterCount0) && - (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base)) - { - ACPI_ERROR ((AE_INFO, - "GPE0 block (GPE 0 to %u) overlaps the GPE1 block " - "(GPE %u to %u) - Ignoring GPE1", - GpeNumberMax, AcpiGbl_FADT.Gpe1Base, - AcpiGbl_FADT.Gpe1Base + - ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1))); - - /* Ignore GPE1 block by setting the register count to zero */ - - RegisterCount1 = 0; - } - else - { - /* Install GPE Block 1 */ - - Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, - &AcpiGbl_FADT.XGpe1Block, RegisterCount1, - AcpiGbl_FADT.Gpe1Base, - AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]); - - if (ACPI_FAILURE (Status)) - { - ACPI_EXCEPTION ((AE_INFO, Status, - "Could not create GPE Block 1")); - } - - /* - * GPE0 and GPE1 do not have to be contiguous in the GPE number - * space. However, GPE0 always starts at GPE number zero. - */ - GpeNumberMax = AcpiGbl_FADT.Gpe1Base + - ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1); - } - } - - /* Exit if there are no GPE registers */ - - if ((RegisterCount0 + RegisterCount1) == 0) + if (GpeEnabledCount || WakeGpeCount) { - /* GPEs are not required by ACPI, this is OK */ - ACPI_DEBUG_PRINT ((ACPI_DB_INIT, - "There are no GPE blocks defined in the FADT\n")); - Status = AE_OK; - goto Cleanup; + "Enabled %u Runtime GPEs, added %u Wake GPEs in this block\n", + GpeEnabledCount, WakeGpeCount)); } - /* Check for Max GPE number out-of-range */ - - if (GpeNumberMax > ACPI_GPE_MAX) - { - ACPI_ERROR ((AE_INFO, - "Maximum GPE number from FADT is too large: 0x%X", - GpeNumberMax)); - Status = AE_BAD_VALUE; - goto Cleanup; - } - -Cleanup: - (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_OK); } - diff --git a/events/evgpeinit.c b/events/evgpeinit.c new file mode 100644 index 0000000..1720250 --- /dev/null +++ b/events/evgpeinit.c @@ -0,0 +1,763 @@ +/****************************************************************************** + * + * Module Name: evgpeinit - System GPE initialization and update + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + *****************************************************************************/ + + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evgpeinit") + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGpeInitialize + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvGpeInitialize ( + void) +{ + UINT32 RegisterCount0 = 0; + UINT32 RegisterCount1 = 0; + UINT32 GpeNumberMax = 0; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvGpeInitialize); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Initialize the GPE Block(s) defined in the FADT + * + * Why the GPE register block lengths are divided by 2: From the ACPI + * Spec, section "General-Purpose Event Registers", we have: + * + * "Each register block contains two registers of equal length + * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the + * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN + * The length of the GPE1_STS and GPE1_EN registers is equal to + * half the GPE1_LEN. If a generic register block is not supported + * then its respective block pointer and block length values in the + * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need + * to be the same size." + */ + + /* + * Determine the maximum GPE number for this machine. + * + * Note: both GPE0 and GPE1 are optional, and either can exist without + * the other. + * + * If EITHER the register length OR the block address are zero, then that + * particular block is not supported. + */ + if (AcpiGbl_FADT.Gpe0BlockLength && + AcpiGbl_FADT.XGpe0Block.Address) + { + /* GPE block 0 exists (has both length and address > 0) */ + + RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2); + + GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1; + + /* Install GPE Block 0 */ + + Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, + &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0, + AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]); + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not create GPE Block 0")); + } + } + + if (AcpiGbl_FADT.Gpe1BlockLength && + AcpiGbl_FADT.XGpe1Block.Address) + { + /* GPE block 1 exists (has both length and address > 0) */ + + RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2); + + /* Check for GPE0/GPE1 overlap (if both banks exist) */ + + if ((RegisterCount0) && + (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base)) + { + ACPI_ERROR ((AE_INFO, + "GPE0 block (GPE 0 to %u) overlaps the GPE1 block " + "(GPE %u to %u) - Ignoring GPE1", + GpeNumberMax, AcpiGbl_FADT.Gpe1Base, + AcpiGbl_FADT.Gpe1Base + + ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1))); + + /* Ignore GPE1 block by setting the register count to zero */ + + RegisterCount1 = 0; + } + else + { + /* Install GPE Block 1 */ + + Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, + &AcpiGbl_FADT.XGpe1Block, RegisterCount1, + AcpiGbl_FADT.Gpe1Base, + AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]); + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not create GPE Block 1")); + } + + /* + * GPE0 and GPE1 do not have to be contiguous in the GPE number + * space. However, GPE0 always starts at GPE number zero. + */ + GpeNumberMax = AcpiGbl_FADT.Gpe1Base + + ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1); + } + } + + /* Exit if there are no GPE registers */ + + if ((RegisterCount0 + RegisterCount1) == 0) + { + /* GPEs are not required by ACPI, this is OK */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INIT, + "There are no GPE blocks defined in the FADT\n")); + Status = AE_OK; + goto Cleanup; + } + + /* Check for Max GPE number out-of-range */ + + if (GpeNumberMax > ACPI_GPE_MAX) + { + ACPI_ERROR ((AE_INFO, + "Maximum GPE number from FADT is too large: 0x%X", + GpeNumberMax)); + Status = AE_BAD_VALUE; + goto Cleanup; + } + +Cleanup: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvUpdateGpes + * + * PARAMETERS: TableOwnerId - ID of the newly-loaded ACPI table + * + * RETURN: None + * + * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a + * result of a Load() or LoadTable() operation. If new GPE + * methods have been installed, register the new methods and + * enable and runtime GPEs that are associated with them. Also, + * run any newly loaded _PRW methods in order to discover any + * new CAN_WAKE GPEs. + * + ******************************************************************************/ + +void +AcpiEvUpdateGpes ( + ACPI_OWNER_ID TableOwnerId) +{ + ACPI_GPE_XRUPT_INFO *GpeXruptInfo; + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_WALK_INFO WalkInfo; + ACPI_STATUS Status = AE_OK; + UINT32 NewWakeGpeCount = 0; + + + /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */ + + WalkInfo.OwnerId = TableOwnerId; + WalkInfo.ExecuteByOwnerId = TRUE; + WalkInfo.Count = 0; + + if (AcpiGbl_LeaveWakeGpesDisabled) + { + /* + * 1) Run any newly-loaded _PRW methods to find any GPEs that + * can now be marked as CAN_WAKE GPEs. Note: We must run the + * _PRW methods before we process the _Lxx/_Exx methods because + * we will enable all runtime GPEs associated with the new + * _Lxx/_Exx methods at the time we process those methods. + * + * Unlock interpreter so that we can run the _PRW methods. + */ + WalkInfo.GpeBlock = NULL; + WalkInfo.GpeDevice = NULL; + + AcpiExExitInterpreter (); + + Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, + AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While executing _PRW methods")); + } + + AcpiExEnterInterpreter (); + NewWakeGpeCount = WalkInfo.Count; + } + + /* + * 2) Find any _Lxx/_Exx GPE methods that have just been loaded. + * + * Any GPEs that correspond to new _Lxx/_Exx methods and are not + * marked as CAN_WAKE are immediately enabled. + * + * Examine the namespace underneath each GpeDevice within the + * GpeBlock lists. + */ + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return; + } + + WalkInfo.Count = 0; + WalkInfo.EnableThisGpe = TRUE; + + /* Walk the interrupt level descriptor list */ + + GpeXruptInfo = AcpiGbl_GpeXruptListHead; + while (GpeXruptInfo) + { + /* Walk all Gpe Blocks attached to this interrupt level */ + + GpeBlock = GpeXruptInfo->GpeBlockListHead; + while (GpeBlock) + { + WalkInfo.GpeBlock = GpeBlock; + WalkInfo.GpeDevice = GpeBlock->Node; + + Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, + WalkInfo.GpeDevice, ACPI_UINT32_MAX, + ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod, + NULL, &WalkInfo, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While decoding _Lxx/_Exx methods")); + } + + GpeBlock = GpeBlock->Next; + } + + GpeXruptInfo = GpeXruptInfo->Next; + } + + if (WalkInfo.Count || NewWakeGpeCount) + { + ACPI_INFO ((AE_INFO, + "Enabled %u new runtime GPEs, added %u new wakeup GPEs", + WalkInfo.Count, NewWakeGpeCount)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvMatchGpeMethod + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status + * + * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a + * control method under the _GPE portion of the namespace. + * Extract the name and GPE type from the object, saving this + * information for quick lookup during GPE dispatch. Allows a + * per-OwnerId evaluation if ExecuteByOwnerId is TRUE in the + * WalkInfo parameter block. + * + * The name of each GPE control method is of the form: + * "_Lxx" or "_Exx", where: + * L - means that the GPE is level triggered + * E - means that the GPE is edge triggered + * xx - is the GPE number [in HEX] + * + * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods + * with that owner. + * If WalkInfo->EnableThisGpe is TRUE, the GPE that is referred to by a GPE + * method is immediately enabled (Used for Load/LoadTable operators) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvMatchGpeMethod ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); + ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_NAMESPACE_NODE *GpeDevice; + ACPI_STATUS Status; + UINT32 GpeNumber; + char Name[ACPI_NAME_SIZE + 1]; + UINT8 Type; + + + ACPI_FUNCTION_TRACE (EvMatchGpeMethod); + + + /* Check if requested OwnerId matches this OwnerId */ + + if ((WalkInfo->ExecuteByOwnerId) && + (MethodNode->OwnerId != WalkInfo->OwnerId)) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * Match and decode the _Lxx and _Exx GPE method names + * + * 1) Extract the method name and null terminate it + */ + ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer); + Name[ACPI_NAME_SIZE] = 0; + + /* 2) Name must begin with an underscore */ + + if (Name[0] != '_') + { + return_ACPI_STATUS (AE_OK); /* Ignore this method */ + } + + /* + * 3) Edge/Level determination is based on the 2nd character + * of the method name + * + * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is + * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. + */ + switch (Name[1]) + { + case 'L': + Type = ACPI_GPE_LEVEL_TRIGGERED; + break; + + case 'E': + Type = ACPI_GPE_EDGE_TRIGGERED; + break; + + default: + /* Unknown method type, just ignore it */ + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, + "Ignoring unknown GPE method type: %s " + "(name not of form _Lxx or _Exx)", Name)); + return_ACPI_STATUS (AE_OK); + } + + /* 4) The last two characters of the name are the hex GPE Number */ + + GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); + if (GpeNumber == ACPI_UINT32_MAX) + { + /* Conversion failed; invalid method, just ignore it */ + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, + "Could not extract GPE number from name: %s " + "(name is not of form _Lxx or _Exx)", Name)); + return_ACPI_STATUS (AE_OK); + } + + /* Ensure that we have a valid GPE number for this GPE block */ + + GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock); + if (!GpeEventInfo) + { + /* + * This GpeNumber is not valid for this GPE block, just ignore it. + * However, it may be valid for a different GPE block, since GPE0 + * and GPE1 methods both appear under \_GPE. + */ + return_ACPI_STATUS (AE_OK); + } + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_HANDLER) + { + /* If there is already a handler, ignore this GPE method */ + + return_ACPI_STATUS (AE_OK); + } + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_METHOD) + { + /* + * If there is already a method, ignore this method. But check + * for a type mismatch (if both the _Lxx AND _Exx exist) + */ + if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) + { + ACPI_ERROR ((AE_INFO, + "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods", + GpeNumber, GpeNumber, GpeNumber)); + } + return_ACPI_STATUS (AE_OK); + } + + /* + * Add the GPE information from above to the GpeEventInfo block for + * use during dispatch of this GPE. + */ + GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); + GpeEventInfo->Dispatch.MethodNode = MethodNode; + + /* + * Enable this GPE if requested. This only happens when during the + * execution of a Load or LoadTable operator. We have found a new + * GPE method and want to immediately enable the GPE if it is a + * runtime GPE. + */ + if (WalkInfo->EnableThisGpe) + { + /* Ignore GPEs that can wake the system */ + + if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) || + !AcpiGbl_LeaveWakeGpesDisabled) + { + WalkInfo->Count++; + GpeDevice = WalkInfo->GpeDevice; + + if (GpeDevice == AcpiGbl_FadtGpeDevice) + { + GpeDevice = NULL; + } + + Status = AcpiEnableGpe (GpeDevice, GpeNumber, + ACPI_GPE_TYPE_RUNTIME); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not enable GPE 0x%02X", GpeNumber)); + } + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, + "Registered GPE method %s as GPE number 0x%.2X\n", + Name, GpeNumber)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvMatchPrwAndGpe + * + * PARAMETERS: Callback from WalkNamespace + * + * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is + * not aborted on a single _PRW failure. + * + * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a + * Device. Run the _PRW method. If present, extract the GPE + * number and mark the GPE as a CAN_WAKE GPE. Allows a + * per-OwnerId execution if ExecuteByOwnerId is TRUE in the + * WalkInfo parameter block. + * + * If WalkInfo->ExecuteByOwnerId is TRUE, we only execute _PRWs with that + * owner. + * If WalkInfo->GpeDevice is NULL, we execute every _PRW found. Otherwise, + * we only execute _PRWs that refer to the input GpeDevice. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvMatchPrwAndGpe ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); + ACPI_NAMESPACE_NODE *GpeDevice; + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_NAMESPACE_NODE *TargetGpeDevice; + ACPI_NAMESPACE_NODE *PrwNode; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_OPERAND_OBJECT *PkgDesc; + ACPI_OPERAND_OBJECT *ObjDesc; + UINT32 GpeNumber; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe); + + + /* Check for a _PRW method under this device */ + + Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW, + ACPI_NS_NO_UPSEARCH, &PrwNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (AE_OK); + } + + /* Check if requested OwnerId matches this OwnerId */ + + if ((WalkInfo->ExecuteByOwnerId) && + (PrwNode->OwnerId != WalkInfo->OwnerId)) + { + return_ACPI_STATUS (AE_OK); + } + + /* Execute the _PRW */ + + Status = AcpiUtEvaluateObject (PrwNode, NULL, + ACPI_BTYPE_PACKAGE, &PkgDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (AE_OK); + } + + /* The returned _PRW package must have at least two elements */ + + if (PkgDesc->Package.Count < 2) + { + goto Cleanup; + } + + /* Extract pointers from the input context */ + + GpeDevice = WalkInfo->GpeDevice; + GpeBlock = WalkInfo->GpeBlock; + + /* + * The _PRW object must return a package, we are only interested + * in the first element + */ + ObjDesc = PkgDesc->Package.Elements[0]; + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + /* Use FADT-defined GPE device (from definition of _PRW) */ + + TargetGpeDevice = NULL; + if (GpeDevice) + { + TargetGpeDevice = AcpiGbl_FadtGpeDevice; + } + + /* Integer is the GPE number in the FADT described GPE blocks */ + + GpeNumber = (UINT32) ObjDesc->Integer.Value; + } + else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) + { + /* Package contains a GPE reference and GPE number within a GPE block */ + + if ((ObjDesc->Package.Count < 2) || + ((ObjDesc->Package.Elements[0])->Common.Type != + ACPI_TYPE_LOCAL_REFERENCE) || + ((ObjDesc->Package.Elements[1])->Common.Type != + ACPI_TYPE_INTEGER)) + { + goto Cleanup; + } + + /* Get GPE block reference and decode */ + + TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node; + GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value; + } + else + { + /* Unknown type, just ignore it */ + + goto Cleanup; + } + + /* Get the GpeEventInfo for this GPE */ + + if (GpeDevice) + { + /* + * Is this GPE within this block? + * + * TRUE if and only if these conditions are true: + * 1) The GPE devices match. + * 2) The GPE index(number) is within the range of the Gpe Block + * associated with the GPE device. + */ + if (GpeDevice != TargetGpeDevice) + { + goto Cleanup; + } + + GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); + } + else + { + /* GpeDevice is NULL, just match the TargetDevice and GpeNumber */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber); + } + + if (GpeEventInfo) + { + if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) + { + /* This GPE can wake the system */ + + GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; + WalkInfo->Count++; + } + } + +Cleanup: + AcpiUtRemoveReference (PkgDesc); + return_ACPI_STATUS (AE_OK); +} + diff --git a/events/evgpeutil.c b/events/evgpeutil.c new file mode 100644 index 0000000..2ac0ad4 --- /dev/null +++ b/events/evgpeutil.c @@ -0,0 +1,452 @@ +/****************************************************************************** + * + * Module Name: evgpeutil - GPE utilities + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + *****************************************************************************/ + + + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evgpeutil") + + +/******************************************************************************* + * + * FUNCTION: AcpiEvWalkGpeList + * + * PARAMETERS: GpeWalkCallback - Routine called for each GPE block + * Context - Value passed to callback + * + * RETURN: Status + * + * DESCRIPTION: Walk the GPE lists. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvWalkGpeList ( + ACPI_GPE_CALLBACK GpeWalkCallback, + void *Context) +{ + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_XRUPT_INFO *GpeXruptInfo; + ACPI_STATUS Status = AE_OK; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (EvWalkGpeList); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Walk the interrupt level descriptor list */ + + GpeXruptInfo = AcpiGbl_GpeXruptListHead; + while (GpeXruptInfo) + { + /* Walk all Gpe Blocks attached to this interrupt level */ + + GpeBlock = GpeXruptInfo->GpeBlockListHead; + while (GpeBlock) + { + /* One callback per GPE block */ + + Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_CTRL_END) /* Callback abort */ + { + Status = AE_OK; + } + goto UnlockAndExit; + } + + GpeBlock = GpeBlock->Next; + } + + GpeXruptInfo = GpeXruptInfo->Next; + } + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvValidGpeEvent + * + * PARAMETERS: GpeEventInfo - Info for this GPE + * + * RETURN: TRUE if the GpeEvent is valid + * + * DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL. + * Should be called only when the GPE lists are semaphore locked + * and not subject to change. + * + ******************************************************************************/ + +BOOLEAN +AcpiEvValidGpeEvent ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_GPE_XRUPT_INFO *GpeXruptBlock; + ACPI_GPE_BLOCK_INFO *GpeBlock; + + + ACPI_FUNCTION_ENTRY (); + + + /* No need for spin lock since we are not changing any list elements */ + + /* Walk the GPE interrupt levels */ + + GpeXruptBlock = AcpiGbl_GpeXruptListHead; + while (GpeXruptBlock) + { + GpeBlock = GpeXruptBlock->GpeBlockListHead; + + /* Walk the GPE blocks on this interrupt level */ + + while (GpeBlock) + { + if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) && + (&GpeBlock->EventInfo[GpeBlock->GpeCount] > GpeEventInfo)) + { + return (TRUE); + } + + GpeBlock = GpeBlock->Next; + } + + GpeXruptBlock = GpeXruptBlock->Next; + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvGetGpeXruptBlock + * + * PARAMETERS: InterruptNumber - Interrupt for a GPE block + * + * RETURN: A GPE interrupt block + * + * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt + * block per unique interrupt level used for GPEs. Should be + * called only when the GPE lists are semaphore locked and not + * subject to change. + * + ******************************************************************************/ + +ACPI_GPE_XRUPT_INFO * +AcpiEvGetGpeXruptBlock ( + UINT32 InterruptNumber) +{ + ACPI_GPE_XRUPT_INFO *NextGpeXrupt; + ACPI_GPE_XRUPT_INFO *GpeXrupt; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock); + + + /* No need for lock since we are not changing any list elements here */ + + NextGpeXrupt = AcpiGbl_GpeXruptListHead; + while (NextGpeXrupt) + { + if (NextGpeXrupt->InterruptNumber == InterruptNumber) + { + return_PTR (NextGpeXrupt); + } + + NextGpeXrupt = NextGpeXrupt->Next; + } + + /* Not found, must allocate a new xrupt descriptor */ + + GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO)); + if (!GpeXrupt) + { + return_PTR (NULL); + } + + GpeXrupt->InterruptNumber = InterruptNumber; + + /* Install new interrupt descriptor with spin lock */ + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + if (AcpiGbl_GpeXruptListHead) + { + NextGpeXrupt = AcpiGbl_GpeXruptListHead; + while (NextGpeXrupt->Next) + { + NextGpeXrupt = NextGpeXrupt->Next; + } + + NextGpeXrupt->Next = GpeXrupt; + GpeXrupt->Previous = NextGpeXrupt; + } + else + { + AcpiGbl_GpeXruptListHead = GpeXrupt; + } + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + /* Install new interrupt handler if not SCI_INT */ + + if (InterruptNumber != AcpiGbl_FADT.SciInterrupt) + { + Status = AcpiOsInstallInterruptHandler (InterruptNumber, + AcpiEvGpeXruptHandler, GpeXrupt); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not install GPE interrupt handler at level 0x%X", + InterruptNumber)); + return_PTR (NULL); + } + } + + return_PTR (GpeXrupt); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvDeleteGpeXrupt + * + * PARAMETERS: GpeXrupt - A GPE interrupt info block + * + * RETURN: Status + * + * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated + * interrupt handler if not the SCI interrupt. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvDeleteGpeXrupt ( + ACPI_GPE_XRUPT_INFO *GpeXrupt) +{ + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt); + + + /* We never want to remove the SCI interrupt handler */ + + if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt) + { + GpeXrupt->GpeBlockListHead = NULL; + return_ACPI_STATUS (AE_OK); + } + + /* Disable this interrupt */ + + Status = AcpiOsRemoveInterruptHandler ( + GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Unlink the interrupt block with lock */ + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + if (GpeXrupt->Previous) + { + GpeXrupt->Previous->Next = GpeXrupt->Next; + } + else + { + /* No previous, update list head */ + + AcpiGbl_GpeXruptListHead = GpeXrupt->Next; + } + + if (GpeXrupt->Next) + { + GpeXrupt->Next->Previous = GpeXrupt->Previous; + } + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + /* Free the block */ + + ACPI_FREE (GpeXrupt); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvDeleteGpeHandlers + * + * PARAMETERS: GpeXruptInfo - GPE Interrupt info + * GpeBlock - Gpe Block info + * + * RETURN: Status + * + * DESCRIPTION: Delete all Handler objects found in the GPE data structs. + * Used only prior to termination. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvDeleteGpeHandlers ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo; + UINT32 i; + UINT32 j; + + + ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers); + + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) + { + GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * + ACPI_GPE_REGISTER_WIDTH) + j]; + + if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_HANDLER) + { + ACPI_FREE (GpeEventInfo->Dispatch.Handler); + GpeEventInfo->Dispatch.Handler = NULL; + GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; + } + } + } + + return_ACPI_STATUS (AE_OK); +} + diff --git a/executer/exconfig.c b/executer/exconfig.c index 034afb6..ab2be8a 100644 --- a/executer/exconfig.c +++ b/executer/exconfig.c @@ -164,8 +164,9 @@ AcpiExAddTable ( ACPI_NAMESPACE_NODE *ParentNode, ACPI_OPERAND_OBJECT **DdbHandle) { - ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + ACPI_OWNER_ID OwnerId; ACPI_FUNCTION_TRACE (ExAddTable); @@ -205,7 +206,15 @@ AcpiExAddTable ( AcpiNsExecModuleCodeList (); AcpiExEnterInterpreter (); - return_ACPI_STATUS (Status); + /* Update GPEs for any new _PRW or _Lxx/_Exx methods. Ignore errors */ + + Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); + if (ACPI_SUCCESS (Status)) + { + AcpiEvUpdateGpes (OwnerId); + } + + return_ACPI_STATUS (AE_OK); } @@ -347,9 +356,8 @@ AcpiExLoadTableOp ( Status = AcpiGetTableByIndex (TableIndex, &Table); if (ACPI_SUCCESS (Status)) { - ACPI_INFO ((AE_INFO, - "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", - Table->Signature, Table->OemId, Table->OemTableId)); + ACPI_INFO ((AE_INFO, "Dynamic OEM Table Load:")); + AcpiTbPrintTableHeader (0, Table); } /* Invoke table handler if present */ @@ -644,6 +652,9 @@ AcpiExLoadOp ( return_ACPI_STATUS (Status); } + ACPI_INFO ((AE_INFO, "Dynamic OEM Table Load:")); + AcpiTbPrintTableHeader (0, TableDesc.Pointer); + /* Remove the reference by added by AcpiExStore above */ AcpiUtRemoveReference (DdbHandle); diff --git a/executer/exoparg1.c b/executer/exoparg1.c index 1bff09b..7a47bb1 100644 --- a/executer/exoparg1.c +++ b/executer/exoparg1.c @@ -268,7 +268,7 @@ AcpiExOpcode_1A_0T_0R ( case AML_SLEEP_OP: /* Sleep (MsecTime) */ - Status = AcpiExSystemDoSuspend (Operand[0]->Integer.Value); + Status = AcpiExSystemDoSleep (Operand[0]->Integer.Value); break; diff --git a/executer/exsystem.c b/executer/exsystem.c index f43ef21..8f4ccfe 100644 --- a/executer/exsystem.c +++ b/executer/exsystem.c @@ -280,19 +280,19 @@ AcpiExSystemDoStall ( /******************************************************************************* * - * FUNCTION: AcpiExSystemDoSuspend + * FUNCTION: AcpiExSystemDoSleep * - * PARAMETERS: HowLong - The amount of time to suspend, + * PARAMETERS: HowLong - The amount of time to sleep, * in milliseconds * * RETURN: None * - * DESCRIPTION: Suspend running thread for specified amount of time. + * DESCRIPTION: Sleep the running thread for specified amount of time. * ******************************************************************************/ ACPI_STATUS -AcpiExSystemDoSuspend ( +AcpiExSystemDoSleep ( UINT64 HowLong) { ACPI_FUNCTION_ENTRY (); diff --git a/include/acevents.h b/include/acevents.h index 4d945ef..4051557 100644 --- a/include/acevents.h +++ b/include/acevents.h @@ -167,8 +167,12 @@ AcpiEvQueueNotifyRequest ( /* - * evgpe - GPE handling and dispatch + * evgpe - Low-level GPE support */ +UINT32 +AcpiEvGpeDetect ( + ACPI_GPE_XRUPT_INFO *GpeXruptList); + ACPI_STATUS AcpiEvUpdateGpeEnableMasks ( ACPI_GPE_EVENT_INFO *GpeEventInfo); @@ -193,23 +197,8 @@ AcpiEvLowGetGpeInfo ( /* - * evgpeblk + * evgpeblk - Upper-level GPE block support */ -BOOLEAN -AcpiEvValidGpeEvent ( - ACPI_GPE_EVENT_INFO *GpeEventInfo); - -ACPI_STATUS -AcpiEvWalkGpeList ( - ACPI_GPE_CALLBACK GpeWalkCallback, - void *Context); - -ACPI_STATUS -AcpiEvDeleteGpeHandlers ( - ACPI_GPE_XRUPT_INFO *GpeXruptInfo, - ACPI_GPE_BLOCK_INFO *GpeBlock, - void *Context); - ACPI_STATUS AcpiEvCreateGpeBlock ( ACPI_NAMESPACE_NODE *GpeDevice, @@ -233,14 +222,57 @@ AcpiEvGpeDispatch ( ACPI_GPE_EVENT_INFO *GpeEventInfo, UINT32 GpeNumber); -UINT32 -AcpiEvGpeDetect ( - ACPI_GPE_XRUPT_INFO *GpeXruptList); - +/* + * evgpeinit - GPE initialization and update + */ ACPI_STATUS AcpiEvGpeInitialize ( void); +void +AcpiEvUpdateGpes ( + ACPI_OWNER_ID TableOwnerId); + +ACPI_STATUS +AcpiEvMatchGpeMethod ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +ACPI_STATUS +AcpiEvMatchPrwAndGpe ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +/* + * evgpeutil - GPE utilities + */ +ACPI_STATUS +AcpiEvWalkGpeList ( + ACPI_GPE_CALLBACK GpeWalkCallback, + void *Context); + +BOOLEAN +AcpiEvValidGpeEvent ( + ACPI_GPE_EVENT_INFO *GpeEventInfo); + +ACPI_GPE_XRUPT_INFO * +AcpiEvGetGpeXruptBlock ( + UINT32 InterruptNumber); + +ACPI_STATUS +AcpiEvDeleteGpeXrupt ( + ACPI_GPE_XRUPT_INFO *GpeXrupt); + +ACPI_STATUS +AcpiEvDeleteGpeHandlers ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + /* * evregion - Address Space handling diff --git a/include/acglobal.h b/include/acglobal.h index 4f0769e..e0f8871 100644 --- a/include/acglobal.h +++ b/include/acglobal.h @@ -216,11 +216,10 @@ ACPI_NAME AcpiGbl_TraceMethodName; ****************************************************************************/ /* - * AcpiGbl_RootTableList is the master list of ACPI tables found in the - * RSDT/XSDT. - * + * AcpiGbl_RootTableList is the master list of ACPI tables that were + * found in the RSDT/XSDT. */ -ACPI_EXTERN ACPI_INTERNAL_RSDT AcpiGbl_RootTableList; +ACPI_EXTERN ACPI_TABLE_LIST AcpiGbl_RootTableList; ACPI_EXTERN ACPI_TABLE_FACS *AcpiGbl_FACS; /* These addresses are calculated from the FADT Event Block addresses */ diff --git a/include/acinterp.h b/include/acinterp.h index 67142c8..e3fa940 100644 --- a/include/acinterp.h +++ b/include/acinterp.h @@ -434,7 +434,7 @@ AcpiExSystemDoNotifyOp ( ACPI_OPERAND_OBJECT *ObjDesc); ACPI_STATUS -AcpiExSystemDoSuspend( +AcpiExSystemDoSleep( UINT64 Time); ACPI_STATUS diff --git a/include/aclocal.h b/include/aclocal.h index 8818a6e..1deced0 100644 --- a/include/aclocal.h +++ b/include/aclocal.h @@ -307,16 +307,16 @@ typedef struct acpi_namespace_node #define ANOBJ_IS_REFERENCED 0x80 /* iASL only: Object was referenced */ -/* One internal RSDT for table management */ +/* Internal ACPI table management - master table list */ -typedef struct acpi_internal_rsdt +typedef struct acpi_table_list { - ACPI_TABLE_DESC *Tables; - UINT32 Count; - UINT32 Size; + ACPI_TABLE_DESC *Tables; /* Table descriptor array */ + UINT32 CurrentTableCount; /* Tables currently in the array */ + UINT32 MaxTableCount; /* Max tables array will hold */ UINT8 Flags; -} ACPI_INTERNAL_RSDT; +} ACPI_TABLE_LIST; /* Flags for above */ @@ -612,6 +612,10 @@ typedef struct acpi_gpe_walk_info { ACPI_NAMESPACE_NODE *GpeDevice; ACPI_GPE_BLOCK_INFO *GpeBlock; + UINT16 Count; + ACPI_OWNER_ID OwnerId; + BOOLEAN EnableThisGpe; + BOOLEAN ExecuteByOwnerId; } ACPI_GPE_WALK_INFO; diff --git a/include/acpiosxf.h b/include/acpiosxf.h index 0c22b63..3a9da6c 100644 --- a/include/acpiosxf.h +++ b/include/acpiosxf.h @@ -410,8 +410,8 @@ AcpiOsWritePciConfiguration ( */ void AcpiOsDerivePciId( - ACPI_HANDLE Rhandle, - ACPI_HANDLE Chandle, + ACPI_HANDLE Device, + ACPI_HANDLE Region, ACPI_PCI_ID **PciId); diff --git a/include/acpixf.h b/include/acpixf.h index 300b2c7..0e68fab 100644 --- a/include/acpixf.h +++ b/include/acpixf.h @@ -120,7 +120,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20100331 +#define ACPI_CA_VERSION 0x20100428 #include "actypes.h" #include "actbl.h" @@ -283,7 +283,7 @@ AcpiGetDevices ( ACPI_STATUS AcpiGetName ( - ACPI_HANDLE Handle, + ACPI_HANDLE Object, UINT32 NameType, ACPI_BUFFER *RetPathPtr); @@ -295,18 +295,18 @@ AcpiGetHandle ( ACPI_STATUS AcpiAttachData ( - ACPI_HANDLE ObjHandle, + ACPI_HANDLE Object, ACPI_OBJECT_HANDLER Handler, void *Data); ACPI_STATUS AcpiDetachData ( - ACPI_HANDLE ObjHandle, + ACPI_HANDLE Object, ACPI_OBJECT_HANDLER Handler); ACPI_STATUS AcpiGetData ( - ACPI_HANDLE ObjHandle, + ACPI_HANDLE Object, ACPI_OBJECT_HANDLER Handler, void **Data); @@ -338,7 +338,7 @@ AcpiEvaluateObjectTyped ( ACPI_STATUS AcpiGetObjectInfo ( - ACPI_HANDLE Handle, + ACPI_HANDLE Object, ACPI_DEVICE_INFO **ReturnBuffer); ACPI_STATUS @@ -527,36 +527,36 @@ ACPI_STATUS (*ACPI_WALK_RESOURCE_CALLBACK) ( ACPI_STATUS AcpiGetVendorResource ( - ACPI_HANDLE DeviceHandle, + ACPI_HANDLE Device, char *Name, ACPI_VENDOR_UUID *Uuid, ACPI_BUFFER *RetBuffer); ACPI_STATUS -AcpiGetCurrentResources( - ACPI_HANDLE DeviceHandle, +AcpiGetCurrentResources ( + ACPI_HANDLE Device, ACPI_BUFFER *RetBuffer); ACPI_STATUS -AcpiGetPossibleResources( - ACPI_HANDLE DeviceHandle, +AcpiGetPossibleResources ( + ACPI_HANDLE Device, ACPI_BUFFER *RetBuffer); ACPI_STATUS AcpiWalkResources ( - ACPI_HANDLE DeviceHandle, + ACPI_HANDLE Device, char *Name, ACPI_WALK_RESOURCE_CALLBACK UserFunction, void *Context); ACPI_STATUS AcpiSetCurrentResources ( - ACPI_HANDLE DeviceHandle, + ACPI_HANDLE Device, ACPI_BUFFER *InBuffer); ACPI_STATUS -AcpiGetIrqRoutingTable ( - ACPI_HANDLE BusDeviceHandle, +AcpiGetIrqRoutingTable ( + ACPI_HANDLE Device, ACPI_BUFFER *RetBuffer); ACPI_STATUS diff --git a/include/actypes.h b/include/actypes.h index 3c0626a..601e87e 100644 --- a/include/actypes.h +++ b/include/actypes.h @@ -1099,7 +1099,7 @@ ACPI_STATUS (*ACPI_ADR_SPACE_SETUP) ( typedef ACPI_STATUS (*ACPI_WALK_CALLBACK) ( - ACPI_HANDLE ObjHandle, + ACPI_HANDLE Object, UINT32 NestingLevel, void *Context, void **ReturnValue); diff --git a/include/amlresrc.h b/include/amlresrc.h index 9084e44..4cd2617 100644 --- a/include/amlresrc.h +++ b/include/amlresrc.h @@ -300,6 +300,12 @@ typedef struct aml_resource_large_header } AML_RESOURCE_LARGE_HEADER; +/* General Flags for address space resource descriptors */ + +#define ACPI_RESOURCE_FLAG_DEC 2 +#define ACPI_RESOURCE_FLAG_MIF 4 +#define ACPI_RESOURCE_FLAG_MAF 8 + typedef struct aml_resource_memory24 { AML_RESOURCE_LARGE_HEADER_COMMON diff --git a/os_specific/service_layers/osunixxf.c b/os_specific/service_layers/osunixxf.c index e62ed73..b457745 100644 --- a/os_specific/service_layers/osunixxf.c +++ b/os_specific/service_layers/osunixxf.c @@ -986,8 +986,8 @@ AcpiOsWritePciConfiguration ( /* TEMPORARY STUB FUNCTION */ void AcpiOsDerivePciId( - ACPI_HANDLE rhandle, - ACPI_HANDLE chandle, + ACPI_HANDLE Device, + ACPI_HANDLE Region, ACPI_PCI_ID **PciId) { diff --git a/os_specific/service_layers/oswinxf.c b/os_specific/service_layers/oswinxf.c index 0f11777..4c50416 100644 --- a/os_specific/service_layers/oswinxf.c +++ b/os_specific/service_layers/oswinxf.c @@ -1234,8 +1234,8 @@ AcpiOsWritePciConfiguration ( /* TEMPORARY STUB FUNCTION */ void AcpiOsDerivePciId( - ACPI_HANDLE rhandle, - ACPI_HANDLE chandle, + ACPI_HANDLE Device, + ACPI_HANDLE Region, ACPI_PCI_ID **PciId) { diff --git a/osunixxf.c b/osunixxf.c index e62ed73..b457745 100644 --- a/osunixxf.c +++ b/osunixxf.c @@ -986,8 +986,8 @@ AcpiOsWritePciConfiguration ( /* TEMPORARY STUB FUNCTION */ void AcpiOsDerivePciId( - ACPI_HANDLE rhandle, - ACPI_HANDLE chandle, + ACPI_HANDLE Device, + ACPI_HANDLE Region, ACPI_PCI_ID **PciId) { diff --git a/tables/tbfind.c b/tables/tbfind.c index e1c110f..4fd988e 100644 --- a/tables/tbfind.c +++ b/tables/tbfind.c @@ -164,7 +164,7 @@ AcpiTbFindTable ( /* Search for the table */ - for (i = 0; i < AcpiGbl_RootTableList.Count; ++i) + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { if (ACPI_MEMCMP (&(AcpiGbl_RootTableList.Tables[i].Signature), Header.Signature, ACPI_NAME_SIZE)) diff --git a/tables/tbinstal.c b/tables/tbinstal.c index 78cf164..2179b6b 100644 --- a/tables/tbinstal.c +++ b/tables/tbinstal.c @@ -227,7 +227,7 @@ AcpiTbAddTable ( /* Check if table is already registered */ - for (i = 0; i < AcpiGbl_RootTableList.Count; ++i) + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { if (!AcpiGbl_RootTableList.Tables[i].Pointer) { @@ -370,7 +370,7 @@ AcpiTbResizeRootTableList ( /* Increase the Table Array size */ Tables = ACPI_ALLOCATE_ZEROED ( - ((ACPI_SIZE) AcpiGbl_RootTableList.Size + + ((ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof (ACPI_TABLE_DESC)); if (!Tables) @@ -384,7 +384,7 @@ AcpiTbResizeRootTableList ( if (AcpiGbl_RootTableList.Tables) { ACPI_MEMCPY (Tables, AcpiGbl_RootTableList.Tables, - (ACPI_SIZE) AcpiGbl_RootTableList.Size * sizeof (ACPI_TABLE_DESC)); + (ACPI_SIZE) AcpiGbl_RootTableList.MaxTableCount * sizeof (ACPI_TABLE_DESC)); if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) { @@ -393,7 +393,7 @@ AcpiTbResizeRootTableList ( } AcpiGbl_RootTableList.Tables = Tables; - AcpiGbl_RootTableList.Size += ACPI_ROOT_TABLE_SIZE_INCREMENT; + AcpiGbl_RootTableList.MaxTableCount += ACPI_ROOT_TABLE_SIZE_INCREMENT; AcpiGbl_RootTableList.Flags |= (UINT8) ACPI_ROOT_ORIGIN_ALLOCATED; return_ACPI_STATUS (AE_OK); @@ -423,12 +423,14 @@ AcpiTbStoreTable ( UINT8 Flags, UINT32 *TableIndex) { - ACPI_STATUS Status = AE_OK; + ACPI_STATUS Status; + ACPI_TABLE_DESC *NewTable; /* Ensure that there is room for the table in the Root Table List */ - if (AcpiGbl_RootTableList.Count >= AcpiGbl_RootTableList.Size) + if (AcpiGbl_RootTableList.CurrentTableCount >= + AcpiGbl_RootTableList.MaxTableCount) { Status = AcpiTbResizeRootTableList(); if (ACPI_FAILURE (Status)) @@ -437,21 +439,21 @@ AcpiTbStoreTable ( } } + NewTable = &AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount]; + /* Initialize added table */ - AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Address = Address; - AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Pointer = Table; - AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Length = Length; - AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].OwnerId = 0; - AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Flags = Flags; + NewTable->Address = Address; + NewTable->Pointer = Table; + NewTable->Length = Length; + NewTable->OwnerId = 0; + NewTable->Flags = Flags; - ACPI_MOVE_32_TO_32 ( - &(AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Signature), - Table->Signature); + ACPI_MOVE_32_TO_32 (&NewTable->Signature, Table->Signature); - *TableIndex = AcpiGbl_RootTableList.Count; - AcpiGbl_RootTableList.Count++; - return (Status); + *TableIndex = AcpiGbl_RootTableList.CurrentTableCount; + AcpiGbl_RootTableList.CurrentTableCount++; + return (AE_OK); } @@ -523,7 +525,7 @@ AcpiTbTerminate ( /* Delete the individual tables */ - for (i = 0; i < AcpiGbl_RootTableList.Count; i++) + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[i]); } @@ -539,7 +541,7 @@ AcpiTbTerminate ( AcpiGbl_RootTableList.Tables = NULL; AcpiGbl_RootTableList.Flags = 0; - AcpiGbl_RootTableList.Count = 0; + AcpiGbl_RootTableList.CurrentTableCount = 0; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ACPI Tables freed\n")); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); @@ -575,7 +577,7 @@ AcpiTbDeleteNamespaceByOwner ( return_ACPI_STATUS (Status); } - if (TableIndex >= AcpiGbl_RootTableList.Count) + if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) { /* The table index does not exist */ @@ -634,7 +636,7 @@ AcpiTbAllocateOwnerId ( (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - if (TableIndex < AcpiGbl_RootTableList.Count) + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) { Status = AcpiUtAllocateOwnerId (&(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId)); @@ -668,7 +670,7 @@ AcpiTbReleaseOwnerId ( (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - if (TableIndex < AcpiGbl_RootTableList.Count) + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) { AcpiUtReleaseOwnerId ( &(AcpiGbl_RootTableList.Tables[TableIndex].OwnerId)); @@ -705,7 +707,7 @@ AcpiTbGetOwnerId ( (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - if (TableIndex < AcpiGbl_RootTableList.Count) + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) { *OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId; Status = AE_OK; @@ -734,7 +736,7 @@ AcpiTbIsTableLoaded ( (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - if (TableIndex < AcpiGbl_RootTableList.Count) + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) { IsLoaded = (BOOLEAN) (AcpiGbl_RootTableList.Tables[TableIndex].Flags & @@ -766,7 +768,7 @@ AcpiTbSetTableLoadedFlag ( { (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - if (TableIndex < AcpiGbl_RootTableList.Count) + if (TableIndex < AcpiGbl_RootTableList.CurrentTableCount) { if (IsLoaded) { diff --git a/tables/tbutils.c b/tables/tbutils.c index eb8bc43..100a91d 100644 --- a/tables/tbutils.c +++ b/tables/tbutils.c @@ -184,7 +184,7 @@ AcpiTbTablesLoaded ( void) { - if (AcpiGbl_RootTableList.Count >= 3) + if (AcpiGbl_RootTableList.CurrentTableCount >= 3) { return (TRUE); } @@ -765,14 +765,15 @@ AcpiTbParseRootTable ( * come from the FADT */ TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER); - AcpiGbl_RootTableList.Count = 2; + AcpiGbl_RootTableList.CurrentTableCount = 2; /* * Initialize the root table array from the RSDT/XSDT */ for (i = 0; i < TableCount; i++) { - if (AcpiGbl_RootTableList.Count >= AcpiGbl_RootTableList.Size) + if (AcpiGbl_RootTableList.CurrentTableCount >= + AcpiGbl_RootTableList.MaxTableCount) { /* There is no more room in the root table array, attempt resize */ @@ -781,18 +782,18 @@ AcpiTbParseRootTable ( { ACPI_WARNING ((AE_INFO, "Truncating %u table entries!", (unsigned) (TableCount - - (AcpiGbl_RootTableList.Count - 2)))); + (AcpiGbl_RootTableList.CurrentTableCount - 2)))); break; } } /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ - AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.Count].Address = + AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address = AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); TableEntry += TableEntrySize; - AcpiGbl_RootTableList.Count++; + AcpiGbl_RootTableList.CurrentTableCount++; } /* @@ -805,7 +806,7 @@ AcpiTbParseRootTable ( * Complete the initialization of the root table array by examining * the header of each table */ - for (i = 2; i < AcpiGbl_RootTableList.Count; i++) + for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address, NULL, i); diff --git a/tables/tbxface.c b/tables/tbxface.c index b3e09a0..ba1a026 100644 --- a/tables/tbxface.c +++ b/tables/tbxface.c @@ -150,7 +150,7 @@ AcpiAllocateRootTable ( UINT32 InitialTableCount) { - AcpiGbl_RootTableList.Size = InitialTableCount; + AcpiGbl_RootTableList.MaxTableCount = InitialTableCount; AcpiGbl_RootTableList.Flags = ACPI_ROOT_ALLOW_RESIZE; return (AcpiTbResizeRootTableList ()); @@ -216,7 +216,7 @@ AcpiInitializeTables ( (ACPI_SIZE) InitialTableCount * sizeof (ACPI_TABLE_DESC)); AcpiGbl_RootTableList.Tables = InitialTableArray; - AcpiGbl_RootTableList.Size = InitialTableCount; + AcpiGbl_RootTableList.MaxTableCount = InitialTableCount; AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_UNKNOWN; if (AllowResize) { @@ -285,7 +285,7 @@ AcpiReallocateRootTable ( * increment to create the new table size. */ CurrentSize = (ACPI_SIZE) - AcpiGbl_RootTableList.Count * sizeof (ACPI_TABLE_DESC); + AcpiGbl_RootTableList.CurrentTableCount * sizeof (ACPI_TABLE_DESC); NewSize = CurrentSize + (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof (ACPI_TABLE_DESC)); @@ -306,8 +306,8 @@ AcpiReallocateRootTable ( * size of the original table list. */ AcpiGbl_RootTableList.Tables = Tables; - AcpiGbl_RootTableList.Size = - AcpiGbl_RootTableList.Count + ACPI_ROOT_TABLE_SIZE_INCREMENT; + AcpiGbl_RootTableList.MaxTableCount = + AcpiGbl_RootTableList.CurrentTableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT; AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE; @@ -354,7 +354,7 @@ AcpiGetTableHeader ( /* Walk the root table list */ - for (i = 0, j = 0; i < AcpiGbl_RootTableList.Count; i++) + for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), Signature)) @@ -439,7 +439,7 @@ AcpiGetTable ( /* Walk the root table list */ - for (i = 0, j = 0; i < AcpiGbl_RootTableList.Count; i++) + for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), Signature)) @@ -502,7 +502,7 @@ AcpiGetTableByIndex ( /* Validate index */ - if (TableIndex >= AcpiGbl_RootTableList.Count) + if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) { (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); return_ACPI_STATUS (AE_BAD_PARAMETER); @@ -559,7 +559,7 @@ AcpiTbLoadNamespace ( * Load the namespace. The DSDT is required, but any SSDT and * PSDT tables are optional. Verify the DSDT. */ - if (!AcpiGbl_RootTableList.Count || + if (!AcpiGbl_RootTableList.CurrentTableCount || !ACPI_COMPARE_NAME ( &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), ACPI_SIG_DSDT) || @@ -613,7 +613,7 @@ AcpiTbLoadNamespace ( /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); - for (i = 0; i < AcpiGbl_RootTableList.Count; ++i) + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), ACPI_SIG_SSDT) && diff --git a/tests/misc/badcode.asl b/tests/misc/badcode.asl new file mode 100644 index 0000000..36ca0d5 --- /dev/null +++ b/tests/misc/badcode.asl @@ -0,0 +1,295 @@ +/* + * badcode.asl + * + * This file contains examples of the extended error checking and + * typechecking capabilities of the iASL compiler. Other ASL compilers + * may ignore these errors completely. Note - this is not an exhaustive + * list of errors detected by iASL, it shows many of the errors that + * are not detected by other ASL compilers. + * + * To compile, use: + * iasl badcode.asl + */ +DefinitionBlock ("badcode.aml", "DSDT", 1, "Intel", "Example", 0x00000001) +{ + Name (INT1, 0) + Name (BUF1, Buffer() {0,1,2,3}) + Event (EVT1) + + // Invalid SyncLevel in Mutex declaration + + Mutex (MTX1, 32) + + // Integer beyond the table integer size (32 bits) + + Name (BIG, 0x1234567887654321) + + // CPackage length does not match initializer list length + + Name (PKG1, Package(5) {0,1}) + + // Inadvertent use of single backslash in a string + + Name (PATH, Buffer() {"\_SB_.PCI2._CRS"}) + + // Invalid hex escape sequence + + Name (ESC1, "abcdefg\x00hijklmn") + + // Field access beyond region bounds + + OperationRegion (OPR1, SystemMemory, 0x2000, 6) + Field (OPR1, DWordAcc, NoLock, Preserve) + { + Offset (4), + FLD1, 8 + } + + // Some address spaces support only ByteAcc or BufferAcc + + OperationRegion (OPR2, EmbeddedControl, 0x4000, 8) + Field (OPR2, DWordAcc, NoLock, Preserve) + { + FLD2, 8 + } + OperationRegion (OPR3, SMBus, 0x8000, 16) + Field (OPR3, WordAcc, NoLock, Preserve) + { + FLD3, 8 + } + + // Invalid SyncLevel in method declaration + + Method (MTH1, 0, NotSerialized, 32) + { + // Invalid arguments and uninitialized locals + + Store (Arg3, Local0) + Store (Local1, Local2) + + // Parameter typechecking (MTX1 is invalid type) + + Subtract (MTX1, 4, Local3) + + // Various invalid parameters + + CreateField (BUF1, 0, Subtract (4, 4), FLD1) + + // Unchecked mutex and event timeouts + + Acquire (MTX1, 100) + Wait (EVT1, 1) + + // Result from operation is not used - statement has no effect + + Add (INT1, 8) + + // Unreachable code + + Return (0) + Store (5, INT1) + } + + Method (MTH2) + { + // Switch with no Case statements + + Switch (ToInteger (INT1)) + { + Default + { + } + } + + if (LEqual (INT1, 0)) + { + Return (INT1) + } + + // Fallthrough exit path does not return a value + } + + Method (MTH3) + { + // Method MTH2 above does not always return a value + + Store (MTH2 (), Local0) + } + + // Invalid _HID value + + Name (_HID, "*PNP0C0A") + + // Predefined Name typechecking + + Name (_PRW, 4) + Name (_FDI, Buffer () {0}) + + // Predefined Name argument count validation + // and return value validation + + Method (_OSC, 5) + { + } + + // Predefined Names that must be implemented as control methods + + Name (_L01, 1) + Name (_E02, 2) + Name (_Q03, 3) + Name (_ON, 0) + Name (_INI, 1) + Name (_PTP, 2) + + /* + * Resource Descriptor error checking + */ + Name (RSC1, ResourceTemplate () + { + // Illegal nested StartDependent macros + + StartDependentFn (0, 0) + { + StartDependentFn (0, 0) + { + } + } + + // Missing EndDependentFn macro + }) + + Name (RSC2, ResourceTemplate () + { + // AddressMin is larger than AddressMax + IO (Decode16, + 0x07D0, // Range Minimum + 0x03E8, // Range Maximum + 0x01, // Alignment + 0x20, // Length + ) + + // Length larger than Min/Max window size + Memory32 (ReadOnly, + 0x00001000, // Range Minimum + 0x00002000, // Range Maximum + 0x00000004, // Alignment + 0x00002000, // Length + ) + + // Min and Max not multiples of alignment value + Memory32 (ReadOnly, + 0x00001001, // Range Minimum + 0x00002002, // Range Maximum + 0x00000004, // Alignment + 0x00000200, // Length + ) + + // 10-bit ISA I/O address has a max of 0x3FF + FixedIO ( + 0xFFFF, // Address + 0x20, // Length + ) + + // Invalid AccessSize parameter + Register (SystemIO, + 0x08, // Bit Width + 0x00, // Bit Offset + 0x0000000000000100, // Address + 0x05 // Access Size + ) + + // Invalid ResourceType (0xB0) + QWordSpace (0xB0, ResourceConsumer, PosDecode, MinFixed, MaxFixed, 0xA5, + 0x0000, // Granularity + 0xA000, // Range Minimum + 0xBFFF, // Range Maximum + 0x0000, // Translation Offset + 0x2000, // Length + ,, ) + + // AddressMin is larger than AddressMax + WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Granularity + 0x0200, // Range Minimum + 0x0100, // Range Maximum + 0x0000, // Translation Offset + 0x0100, // Length + ,, , TypeStatic) + + // Length larger than Min/Max window size + DWordSpace (0xC3, ResourceConsumer, PosDecode, MinFixed, MaxFixed, 0xA5, + 0x00000000, // Granularity + 0x000C8000, // Range Minimum + 0x000C9000, // Range Maximum + 0x00000000, // Translation Offset + 0x00001002, // Length + ,, ) + + // Granularity must be (power-of-two -1) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxNotFixed, NonCacheable, ReadWrite, + 0x00000010, + 0x40000000, + 0xFED9FFFF, + 0x00000000, + 0xBECA0000) + + // Address Min (with zero length) not on granularity boundary + QWordIO (ResourceProducer, MinFixed, MaxNotFixed, PosDecode, EntireRange, + 0x0000000000000003, // Granularity + 0x0000000000000B02, // Range Minimum + 0x0000000000000C00, // Range Maximum + 0x0000000000000000, // Translation Offset + 0x0000000000000000, // Length + ,, , TypeStatic) + + // Address Max (with zero length) not on (granularity boundary -1) + QWordMemory (ResourceProducer, PosDecode, MinNotFixed, MaxFixed, Cacheable, ReadWrite, + 0x0000000000000001, // Granularity + 0x0000000000100000, // Range Minimum + 0x00000000002FFFFE, // Range Maximum + 0x0000000000000000, // Translation Offset + 0x0000000000000000, // Length + ,, , AddressRangeMemory, TypeStatic) + + // Invalid combination: zero length, both Min and Max are fixed + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x00000000, // Granularity + 0x000C8000, // Range Minimum + 0x000C8FFF, // Range Maximum + 0x00000000, // Translation Offset + 0x00000000, // Length + ,, ) + + // Invalid combination: non-zero length, Min Fixed, Max not fixed + DWordIO (ResourceProducer, MinFixed, MaxNotFixed, PosDecode, EntireRange, + 0x00000001, // Granularity + 0x000C8000, // Range Minimum + 0x000C8FFF, // Range Maximum + 0x00000000, // Translation Offset + 0x00000100, // Length + ,, ) + + // Invalid combination: non-zero length, Min not Fixed, Max fixed + DWordIO (ResourceProducer, MinNotFixed, MaxFixed, PosDecode, EntireRange, + 0x00000001, // Granularity + 0x000C8000, // Range Minimum + 0x000C8FFF, // Range Maximum + 0x00000000, // Translation Offset + 0x00000200, // Length + ,, ) + + // Granularity must be zero if non-zero length, min/max fixed + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000000F, // Granularity + 0x000C8000, // Range Minimum + 0x000C8FFF, // Range Maximum + 0x00000000, // Translation Offset + 0x00001000, // Length + ,, ) + + // Missing StartDependentFn macro + + EndDependentFn () + }) +} + diff --git a/tests/misc/grammar.asl b/tests/misc/grammar.asl new file mode 100644 index 0000000..8a13fd1 --- /dev/null +++ b/tests/misc/grammar.asl @@ -0,0 +1,10266 @@ +/* + * Some or all of this work - Copyright (c) 2006 - 2010, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of Intel Corporation nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// +// +// Grammar.asl - Minimally excercises most ASL constructs +// +// NOTE -- use: iasl -f -of grammar.asl to compile +// +// This 1) Ignores errors (checks compiler error handling) +// 2) Disables constant folding +// +// + +/******************************************************************************* +Compilation should look like this: + +C:\acpica\tests\misc>iasl -f -of grammar.asl + +Intel ACPI Component Architecture +ASL Optimizing Compiler version 20090422 [Apr 22 2009] +Copyright (C) 2000 - 2009 Intel Corporation +Supports ACPI Specification Revision 3.0a + +grammar.asl 187: Name (_NPK, Package (8) +Warning 1098 - ^ Unknown reserved name (_NPK) + +grammar.asl 510: NAME (ESC1, "abcdefg\x00hijklmn") +Warning 1042 - ^ Invalid Hex/Octal Escape - Non-ASCII or NULL + +grammar.asl 511: NAME (ESC2, "abcdefg\000hijklmn") +Warning 1042 - ^ Invalid Hex/Octal Escape - Non-ASCII or NULL + +grammar.asl 601: Method (RCIV, 1) +Warning 1087 - ^ Not all control paths return a value (RCIV) + +grammar.asl 608: RCIV (Subtract (Arg0, 1)) +Remark 5073 - ^ Recursive method call (RCIV) + +grammar.asl 937: Method (_ERR, 2) +Warning 1077 - ^ Reserved method has too few arguments (_ERR requires 3) + +grammar.asl 1377: Store (0x1234567887654321, QWD2) +Warning 1032 - ^ 64-bit integer in 32-bit table, truncating + +grammar.asl 1379: if (LNotEqual (Local0, 0x1234567887654321)) +Warning 1032 - 64-bit integer in 32-bit table, truncating ^ + +grammar.asl 1459: SizeOf (BUFO) +Warning 1105 - ^ Result is not used, operator has no effect + +grammar.asl 1485: Acquire (MTX2, 1) +Warning 1104 - ^ Possible operator timeout is ignored + +grammar.asl 1633: Add (Local0, Local1) +Warning 1105 - ^ Result is not used, operator has no effect + +grammar.asl 1804: Method (COND) +Warning 1087 - ^ Not all control paths return a value (COND) + +grammar.asl 6010: Name (_HID, "*PNP0A06") +Error 4001 - ^ String must be entirely alphanumeric (*PNP0A06) + +grammar.asl 6461: Name (_CRS, Buffer(26) {"\_SB_.PCI2._CRS..........."}) +Warning 1038 - Invalid or unknown escape sequence ^ + +grammar.asl 6800: And (Local0, 1, Local0) // Local0 &= 1 +Error 4050 - ^ Method local variable is not initialized (Local0) + +grammar.asl 6886: Name (_HID, "*PNP0C0A") // Control Method Battey ID +Error 4001 - ^ String must be entirely alphanumeric (*PNP0C0A) + +ASL Input: grammar.asl - 10254 lines, 322162 bytes, 4810 keywords +AML Output: grammar.aml - 43392 bytes, 669 named objects, 4141 executable opcodes + +Compilation complete. 3 Errors, 12 Warnings, 1 Remarks, 1101 Optimizations + +***************************************************************************************************/ + +DefinitionBlock ( + "grammar.aml", //Output filename + "DSDT", //Signature + 0x01, //DSDT Revision ---> 32-bit table + "Intel", //OEMID + "GRMTEST", //TABLE ID + 0x20090511 //OEM Revision + ) +{ + + External (\ABCD, UnknownObj) + + + /* Device with _STA and _INI */ + + Device (A1) + { + Method (_STA) + { + Return (0x0F) + } + + Method (_INI) + { + Return + } + } + + /* Device with no _STA, has _INI */ + + Device (A2) + { + Method (_INI) + { + Return + } + } + + /* Device with _STA, no _INI */ + + Device (A3) + { + Method (_STA) + { + Return (0x0F) + } + } + + /* Device with _STA and _INI, but not present */ + + Device (A4) + { + Method (_STA) + { + Return (Zero) + } + + Method (_INI) + { + Return + } + } + + + /* Resource descriptors */ + + Device (IRES) + { + Name (PRT0, ResourceTemplate () + { + IRQ (Edge, ActiveHigh, Exclusive) {3,4,5,6,7,9,10,11,14,15} + + StartDependentFn (1,1) + { + IRQNoFlags () {0,1,2} + } + EndDependentFn () + }) + + Method (_CRS, 0, NotSerialized) + { + Store ("_CRS:", Debug) + Store (PRT0, Debug) + Return (PRT0) + } + + Method (_SRS, 1, Serialized) + { + Store ("_SRS:", Debug) + Store (Arg0, Debug) + Return (Zero) + } + } + + Name (_NPK, Package () + { + 0x1111, + 0x2222, + 0x3333, + 0x4444 + }) + + + Device (RES) + { + Name (_PRT, Package (0x04) + { + Package (0x04) + { + 0x0002FFFF, + Zero, + Zero, + Zero + }, + + Package (0x04) + { + 0x0002FFFF, + One, + Zero, + Zero + }, + + Package (0x04) + { + 0x000AFFFF, + Zero, + Zero, + Zero + }, + + Package (0x04) + { + 0x000BFFFF, + Zero, + Zero, + Zero + } + }) + + Method (_CRS, 0, NotSerialized) + { + Name (PRT0, ResourceTemplate () + { + WordBusNumber (ResourceConsumer, MinFixed, MaxFixed, SubDecode, + 0x0000, // Address Space Granularity + 0xFFF2, // Address Range Minimum + 0xFFF3, // Address Range Maximum + 0x0032, // Address Translation Offset + 0x0002,,,) + WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, + 0x0000, // Address Space Granularity + 0x0000, // Address Range Minimum + 0x00FF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x0100,,,) + WordSpace (0xC3, ResourceConsumer, PosDecode, MinFixed, MaxFixed, 0xA5, + 0x0000, // Address Space Granularity + 0xA000, // Address Range Minimum + 0xBFFF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x2000,,,) + IO (Decode16, 0x0CF8, 0x0CFF, 0x01, 0x08) + WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Address Space Granularity + 0x0000, // Address Range Minimum + 0x0CF7, // Address Range Maximum + 0x0000, // Address Translation Offset + 0x0CF8,,, + , TypeStatic) + WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000, // Address Space Granularity + 0x0D00, // Address Range Minimum + 0xFFFF, // Address Range Maximum + 0x0000, // Address Translation Offset + 0xF300,,, + , TypeStatic) + DWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x00000000, // Address Space Granularity + 0x00000000, // Address Range Minimum + 0x00000CF7, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x00000CF8,,, + , TypeStatic) + DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x00000000, // Address Space Granularity + 0x000C8000, // Address Range Minimum + 0x000EFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x00028000,,, + , AddressRangeMemory, TypeStatic) + DWordSpace (0xC3, ResourceConsumer, PosDecode, MinFixed, MaxFixed, 0xA5, + 0x00000000, // Address Space Granularity + 0x000C8000, // Address Range Minimum + 0x000EFFFF, // Address Range Maximum + 0x00000000, // Address Translation Offset + 0x00028000,,,) + QWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000000000000000, // Address Space Granularity + 0x0000000000000000, // Address Range Minimum + 0x0000000000000CF7, // Address Range Maximum + 0x0000000000000000, // Address Translation Offset + 0x0000000000000CF8, 0x44, "This is a ResouceSource string", + , TypeStatic) + QWordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000000000000000, // Address Space Granularity + 0x0000000000000000, // Address Range Minimum + 0x0000000000000CF7, // Address Range Maximum + 0x0000000000000000, // Address Translation Offset + 0x0000000000000CF8,,, + , TypeStatic) + QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x0000000000000000, // Address Space Granularity + 0x0000000000100000, // Address Range Minimum + 0x00000000FFDFFFFF, // Address Range Maximum + 0x0000000000000000, // Address Translation Offset + 0x00000000FFD00000,,, + , AddressRangeMemory, TypeStatic) + QWordSpace (0xC3, ResourceConsumer, PosDecode, MinFixed, MaxFixed, 0xA5, + 0x0000000000000000, // Address Space Granularity + 0x0000000000000000, // Address Range Minimum + 0x0000000000000CF7, // Address Range Maximum + 0x0000000000000000, // Address Translation Offset + 0x0000000000000CF8,,,) + ExtendedIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, + 0x0000000000000000, // Address Space Granularity + 0x0000000000000000, // Address Range Minimum + 0x0000000000000CF7, // Address Range Maximum + 0x0000000000000000, // Address Translation Offset + 0x0000000000000CF8, // Address Length + 0x0000000000000000, // Type Specific Attributes + , TypeStatic) + ExtendedMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, + 0x0000000000000000, // Address Space Granularity + 0x0000000000100000, // Address Range Minimum + 0x00000000FFDFFFFF, // Address Range Maximum + 0x0000000000000000, // Address Translation Offset + 0x00000000FFD00000, // Address Length + 0x0000000000000000, // Type Specific Attributes + , AddressRangeMemory, TypeStatic) + ExtendedSpace (0xC3, ResourceProducer, PosDecode, MinFixed, MaxFixed, 0xA3, + 0x0000000000000000, // Address Space Granularity + 0x0000000000100000, // Address Range Minimum + 0x00000000FFDFFFFF, // Address Range Maximum + 0x0000000000000000, // Address Translation Offset + 0x00000000FFD00000, // Address Length + 0x0000000000000000) // Type Specific Attributes + IO (Decode16, 0x0010, 0x0020, 0x01, 0x10) + IO (Decode16, 0x0090, 0x00A0, 0x01, 0x10) + FixedIO (0x0061, 0x01) + IRQNoFlags () {2} + DMA (Compatibility, BusMaster, Transfer8_16) {4} + DMA (Compatibility, BusMaster, Transfer8) {2,5,7} + Memory32Fixed (ReadWrite, 0x00100000, 0x00000000) + Memory32Fixed (ReadOnly, 0xFFFE0000, 0x00020000) + Memory32 (ReadOnly, 0x00020000, 0xFFFE0000, 0x00000004, 0x00000200) + Memory24 (ReadOnly, 0x1111, 0x2222, 0x0004, 0x0200) + Interrupt (ResourceConsumer, Level, ActiveLow, Exclusive, 0xE, "\\_SB_.TEST") + { + 0x00000E01, + } + Interrupt (ResourceConsumer, Edge, ActiveHigh, Exclusive, 0x6, "xxxx") + { + 0x00000601, + 0x00000003, + 0x00000002, + 0x00000001, + } + Interrupt (ResourceProducer, Edge, ActiveHigh, Exclusive) + { + 0xFFFF0000, + 0x00000003, + 0x00000002, + 0x00000001, + 0x00000005, + 0x00000007, + 0x00000009, + } + VendorShort () {0x01, 0x02, 0x03} + VendorLong () + { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09 + } + Register (SystemIO, 0x08, 0x00, 0x00000000000000B2, , R000) + Register (SystemMemory, 0x08, 0x00, 0x00000000000000B2) + StartDependentFnNoPri () + { + IRQNoFlags () {0,1,2} + IRQ (Level, ActiveLow, Shared) {3,4,5,6,7,9,10,11,14,15} + } + EndDependentFn () + }) + CreateWordField (PRT0, 0x08, BMIN) + CreateByteField (PRT0, R000._ASZ, RSIZ) + Store (0x03, BMIN) + Return (PRT0) + } + + Method (_PRS, 0, NotSerialized) + { + Name (BUF0, ResourceTemplate () + { + StartDependentFn (0x01, 0x02) + { + IO (Decode16, 0x03D8, 0x03F8, 0x01, 0x08) + IRQNoFlags () {4} + } + StartDependentFn (0x02, 0x01) + { + IO (Decode16, 0x03D8, 0x03E8, 0x01, 0x08) + IRQNoFlags () {4} + } + StartDependentFn (0x00, 0x02) + { + IO (Decode16, 0x02E8, 0x02F8, 0x01, 0x08) + IRQNoFlags () {3} + } + StartDependentFn (0x00, 0x02) + { + IO (Decode16, 0x02D8, 0x02E8, 0x01, 0x08) + IRQNoFlags () {3} + } + StartDependentFn (0x02, 0x00) + { + IO (Decode16, 0x0100, 0x03F8, 0x08, 0x08) + IRQNoFlags () {1,3,4,5,6,7,8,10,11,12,13,14,15} + } + EndDependentFn () + }) + Return (BUF0) + } + + Method (_SRS, 1, Serialized) + { + Return (Zero) + } + } + + + Name(\_S0,Package(0x04){ + 0x00, + 0x00, + 0x00, + 0x00 + }) + Name(\_S3,Package(0x04){ + 0x05, + 0x05, + 0x00, + 0x00 + }) + Name(\_S4,Package(0x04){ + 0x06, + 0x06, + 0x00, + 0x00 + }) + Name(\_S5,Package(0x04){ + 0x07, + 0x07, + 0x00, + 0x00 + }) + +/* Examine this table header (DSDT) */ + +/* + DataTableRegion (HDR, "DSDT", "", "") + Field (HDR, AnyAcc, NoLock, Preserve) + { + SIG, 32, + LENG, 32, + REV, 8, + SUM, 8, + OID, 48, + OTID, 64, + OREV, 32, + CID, 32, + CREV, 32 + } + + Method (SIZE) + { + If (LLess (REV, 2)) + { + Store ("32-bit table", Debug) + } + else + { + Store ("64-bit table", Debug) + } + Return (0) + } + +*/ + Name (SIZE, 0) + + /* Custom operation region */ + + OperationRegion(MYOP,0x80,0xFD60,0x6) + Field(MYOP,ByteAcc,NoLock,Preserve) + { + MFLD,8 + } + + Method (TCOP) + { + Name (_STR, Unicode ("test")) + Store (4, MFLD) + Store (MFLD, Local0) + } + + Name (ERRS, 0x0) + + /* Warning should be issued for premature string termination */ + + NAME (ESC1, "abcdefg\x00hijklmn") + NAME (ESC2, "abcdefg\000hijklmn") + Name (ESC3, "abc\a\bdef\f\n\r\t\v\x03ffff\432") + + + Name(CRSA,ResourceTemplate() + { + WORDBusNumber(ResourceProducer,MinFixed,MaxFixed,PosDecode,0x0000,0x0019,0x001D,0x0000,0x0005) + WORDIO(ResourceProducer,MinFixed,MaxFixed,PosDecode,NonISAOnlyRanges,0x0000,0xC000,0xCFFF,0x0000,0x1000) + DWORDMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,NonCacheable,ReadWrite,0x00000000,0xD8000000,0xDBFFFFFF,0x00000000,0x04000000) + + }) + Name(CRSB,ResourceTemplate() + { + DWORDMemory(ResourceProducer,PosDecode,MinFixed,MaxFixed,NonCacheable,ReadWrite,0x00000000,0xD8000000,0xDBFFFFFF,0x00000000,0x04000000) + + }) + + Name(CRSC,ResourceTemplate() + { + VendorShort () {0x1, 0x2, 0x3} + }) + Name(CRSD,ResourceTemplate() + { + VendorLong (VNDL) {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9} + }) + + Name(CRSE,ResourceTemplate() + { + IRQNoFlags(){3,4,10,11} + IRQNoFlags(xxxt){3,4,10,11} + }) + Name(CRSR, Buffer (Add (SizeOf(CRSA),SizeOf(CRSB))){}) + Method(_CRS,0,NotSerialized) + { + Return(CRSR) + } + + + // + // Unnamed scope + // + Scope (\) + { + Name(Bxxx,0xFFFFFFFF) + } + + Name (LANS, 0x0) + + PowerResource(LANP,1,0) + { + Method(_STA){ + If(LEqual(And(LANS,0x30),0x30)){ + Return(One) + } Else { + Return(Zero) + } + } + Method(_ON){ + If(LNot(_STA())){ + Store (0x30, LANS) + } + } + Method(_OFF){ + If(_STA()){ + Store (0, LANS) + } + } + } + + + /* Can a method define another method? */ + + /********************************** + Method (TASK, 2, SERIALIZED) + { + Sleep (100) + + Method (TAS2) + { + Sleep (100) + } + + TAS2() + Return + + } + ************************************/ + + /* A recursive method */ + + Method (RCIV, 1) + { + Store (Arg0, Debug) + If (Lequal (Arg0, 0)) + { + Return () + } + RCIV (Subtract (Arg0, 1)) + } + + Method (RTOP) + { + RCIV (100) + } + + + Scope(\_PR) + { + Processor(CPU0,0x0,0xFFFFFFFF,0x0) {} + } + + Name(B1TP,0xFFFFFFFF) + + Name(B2TP,0xFFFFFFFF) + Name(ADPS,0xFFFFFFFF) + Name(B1PS,0xFFFFFFFF) + Name(B1RS,0xFFFFFFFF) + Name(B1CS,0xFFFFFFFF) + Name(B2PS,0xFFFFFFFF) + Name(B2RS,0xFFFFFFFF) + Name(B2CS,0xFFFFFFFF) + Name(B1DC,3000) + Name(B2DC,2600) + Name(B1LF,3000) + Name(B2LF,2600) + Name(BPIF,0) + Name(PBLL,0) + + Name(RBIF,Package() + { + 0x1, + 2200, + 2200, + 0x1, + 10800, + 0, + 0, + 1, + 1, + "CA54200-5003/5", + "1", + "LION", + "Fujitsu" + }) + + Method(SMWE, 4) + { + return(ONES) + } + + Method(SMRE, 4) + { + return(ONES) + } + +/* + Method(RDBT,0,Serialized){ + If(LNot(SMWE(0x09,0x15,1,1))){ + Store(0x18,Local2) + } + } +*/ + Scope(_SB) + { + + Name (SBUF, Buffer (128) {}) + + CreateBitField (SBUF, 3, BITY) + CreateByteField (SBUF, 1, BYTY) + CreateWordField (SBUF, 2, WRDZ) + CreateDwordField (SBUF, 4, DWDZ) + CreateQwordField (SBUF, 8, QWDZ) + CreateField (SBUF, 128, 12, FLDZ) + CreateField (SBUF, 148, 96, FLDY) + CreateField (SBUF, 148, 96, \_SB_.FLDW) + + Method (_INI) + { + CreateField (\_SB_.SBUF, 148, 96, FLDV) + } + + + Device(PCI0) + { + Name(_HID,EISAID("PNP0A03")) + Name(_ADR,0x0) + + Method(_CRS) + { + Name(PRT0, ResourceTemplate() { + WORDBusNumber( // Bus number resource(0) + ResourceConsumer, // bit 0 of general flags is 1 + MinFixed, // Range is notfixed + MaxFixed, // Range is not fixed + SubDecode, // SubDecode + 0x0000, // Granularity + 0xfff1, // Min + 0xfff2, // Max + 0x0032, // Translation + 0x0002,,, // Range Length + BUS0 + ) } )// PRT0 + + CreateWordField(PRT0, BUS0._MIN, BMIN) //Minimum bus number suported under this bridge. + + Store(3, BMIN) + Return(PRT0) + + } // _CRS + + Method(_SRS) + { + Return () + } + + Device(EIO) + { + OperationRegion(FJIO,SystemIO,0xFD60,0x6) + Field(FJIO,ByteAcc,NoLock,Preserve) + { + GIDX,8, + + GDTA,8, + + PIDX,8, + + PDTA,8, + + SIDX,8, + + SDTA,8 + } + IndexField(GIDX,GDTA,ByteAcc,NoLock,Preserve) + { + Offset(0x2), + ,5, + VGAS,2, + Offset(0x4), + ,4, + DCKE,1, + Offset(0x5), + ,6, + ACPW,1, + + Offset(0xA), + B1P,1, + + B2P,1, + + B1C,1, + + B2C,1, + + B1ER,1, + + B2ER,1, + + Offset(0xB), + B1CP,8, + + B2CP,8, + + BCP,8, + + B1VH,8, + + B1VL,8, + + B2VH,8, + + B2VL,8, + + B1TM,8, + + B2TM,8, + + B1CH,8, + + B1CL,8, + + B2CH,8, + + B2CL,8 + } + } + } + } + + Method(RDBT,3,Serialized){ + Store(0x1FFF,Local1) + If( Arg0 ){ + Store(0x2FFF,Local1) + } + Store(0x18,Local2) + If( Arg1 ){ + Store(0x10,Local2) + } + If(LNot(SMRE(0x09,0x15,1,RefOf(Local0)))){ + If(LNot(SMWE(0x08,0x14,1,Local1))){ + If(LNot(SMRE(0x09,0x17,Local2,RefOf(Local3)))){ + Store(Local1,Arg2) + } + } + Or(Local0,0xFFF,Local0) + SMWE(0x08,0x14,1,Local0) + } + } + Method(MKWD,2) + { + If(And(Arg1,0x80)) { + Or(0xFFFF0000,Arg0,Local0) + Or(Local0,ShiftLeft(Arg1,8),Local0) + Subtract(Zero,Local0,Local0) + } else { + Store(Arg0,Local0) + Or(Local0,ShiftLeft(Arg1,8),Local0) + } + Return(Local0) + } + + Device(CMB1) + { + Name(_HID,EISAID("PNP0C0A")) + Name(_UID,0x1) + Alias(\_SB.PCI0.EIO.B1P,\_SB_.PCI0.XXXX) + Alias(\_SB.PCI0.EIO.B1P,B1P) + Alias(\_SB.PCI0.EIO.B1C,B1C) + Alias(\_SB.PCI0.EIO.B1CH,B1CH) + Alias(\_SB.PCI0.EIO.B1CL,B1CL) + Alias(\_SB.PCI0.EIO.B1VH,B1VH) + Alias(\_SB.PCI0.EIO.B1VL,B1VL) + Alias(\_SB.PCI0.EIO.B1CP,B1CP) + + Method(_INI) + { + Store(B1P, B1PS) + Store(B1CP,B1RS) + Store(B1C, B1CS) + } + + Method(_BIF){ + RDBT(Zero,Zero,RefOf(B1DC)) + RDBT(Zero,One,RefOf(B1LF)) + Store(B1DC,Index(RBIF,1)) + Store(B1LF,Index(RBIF,2)) + Store("CA54200-5003/5",Index(RBIF,9)) + Store("1",Index(RBIF,10)) + Return(RBIF) + } + + Method(_BST) { + + _INI() + + Store(Zero,Local0) + + if (LAnd(B1P,LNot(B1C))){ + Or(Local0,1,Local0) + } + + if (LAnd(B1P,B1C)) { + Or(Local0,2,Local0) + } + + if (LLessEqual(B1CP,1)) { + Or(Local0,4,Local0) + } + + Store(MKWD(B1CL,B1CH),Local1) + + Store(Divide(Add(Multiply(B1CP,B1LF),99),100),Local2) + + Store(MKWD(B1VL,B1VH),Local3) + + Name(STAT,Package(4){}) + Store(Local0,Index(STAT,0)) + Store(Local1,Index(STAT,1)) + Store(Local2,Index(STAT,2)) + Store(Local3,Index(STAT,3)) + + If(LNot(BPIF)){ +// \_SB.PCI0.EIO.EC0.IECT() +// \_SB.PCI0.EIO.EC0.SECT() + Store(One,BPIF) + } + return(STAT) + } + + } + + Device (DEV1) + { + } + + Scope(\_TZ) + { + ThermalZone(TZ1) + { + Name(_PSL,Package() + { + \_PR.CPU0 + }) + } + } + + Method (TZ2, 0, SERIALIZED) + { + Name(_PSL,Package() + { + \_PR.CPU0 + }) + + Return (_PSL) + } + + ThermalZone (THM1) + { + } + + Method (NOTI) + { + Notify (\DEV1, 0) + Notify (\THM1, 0) + Notify (\_PR.CPU0, 0) + } + + Method (_ERR, 2) + { + Increment (ERRS) + Store ("Run-time exception:", Debug) + Store (Arg0, Debug) + Store (Arg1, Debug) + + Return (0) // Map error to AE_OK + } + + Method (DIV0) + { + Store (1, Local0) + Store (0, Local1) + Divide (Local0, Local1, Local3) + + Store ("DIV0 - noabort", Debug) + } + + Method (ERR_, 1) + { + if (LEqual (Arg0, 0)) + { + Store ("+*+*+*+* MTHD_ERROR: Results not equal!", Debug) + } + if (LEqual (Arg0, 1)) + { + Store ("+*+*+*+* MTHD_ERROR: Numeric result is incorrect!", Debug) + } + if (LEqual (Arg0, 2)) + { + Store ("+*+*+*+* MTHD_ERROR: Operand was clobbered!", Debug) + } + + Notify (DEV1, Arg0) + Increment (ERRS) + } + + Method (R226, 2) + { + } + Method (R225, 2) + { + R226 (Arg0, Arg1) + } + Method (R224, 2) + { + R225 (Arg1, Arg0) + } + Method (R223, 2) + { + R224 (Arg0, Arg1) + } + Method (R222, 2) + { + R223 (Arg1, Arg0) + } + Method (R111) + { + Store (0x01010101, Local0) + R222 (0xABAB, Local0) + Store (Local0, Local1) + } + + Method (MAIN) + { + +// SIZE() + Store (NUM1(), Local0) + \CMB1._BST() + RDBT(1,2,3) + OBJ1(1) + OBJ2(2) + CHEK() + RETZ() + BITZ() + LOGS() + REFS() + COND() + TZ2() + + // + // iPCO tests added + // + Store (\IFEL.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\NOSV.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\IDXF.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\_SB_.NSTL.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\RTBF.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\_SB_.RTLV.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\_SB_.RETP.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\WHLR.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\ANDO.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\BRKP.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\ADSU.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\INDC.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\LOPS.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\FDSO.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\MLDV.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\NBIT.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\SHFT.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\XORD.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\CRBF.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\IDX4.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\EVNT.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\SZLV.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\_SB_.BYTF.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\DWDF.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\DVAX.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\IDX6.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\IDX5.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\_SB_.IDX0.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\_SB_.IDX3.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\IDX7.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\MTCH.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\WHLB.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\_SB_.IDX2.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\SIZO.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + Store (\_SB_.SMIS.TEST(), Local0) + if (LGreater (Local0, 0)) + { + ERR_ (1) + Return(Local0) + } + + if (LGreater (ERRS, 0)) + { + Store ("****** There were errors during the execution of the test ******", Debug) + } + + // + // Last Test + // + + Return(0) // Success + } + + + Method (OBJ1, 1, SERIALIZED) + { + + Store (3, Local0) + Name(BUFR, Buffer (Local0) {}) + Name(BUF1, Buffer (4) {1,2,3,4}) + Name(BUF2, Buffer (4) {}) + + Store (BUF1, BUF2) + Mutex (MTX1, 4) + + Alias (MTX1, MTX2) + } + + + Mutex (MTXT, 0) + Mutex (MTXX, 0) + + /* + * Field Creation + */ + + Method (FLDS) + { + Store ("++++++++ Creating BufferFields", Debug) + Name (BUF2, Buffer (128) {}) + + CreateBitField (BUF2, 3, BIT2) + CreateByteField (BUF2, 1, BYT2) + CreateWordField (BUF2, 2, WRD2) + CreateDwordField (BUF2, 4, DWD2) + CreateQwordField (BUF2, 8, QWD2) + CreateField (BUF2, 128, 12, FLD2) + CreateField (BUF2, 148, 96, FLD3) + + Store (0x1, BIT2) + Store (BIT2, Local0) + if (LNotEqual (Local0, 0x1)) + { + ERR_ (1) + } + else + { + Store (DerefOf (Index (BUF2, 0)), Local0) + if (LNotEqual (Local0, 0x08)) + { + ERR_ (1) + } + else + { + Store ("++++++++ Bit BufferField I/O PASS", Debug) + } + } + + Store (0x1A, BYT2) + Store (BYT2, Local0) + if (LNotEqual (Local0, 0x1A)) + { + ERR_ (1) + } + else + { + Store ("++++++++ Byte BufferField I/O PASS", Debug) + } + + Store (0x1234, WRD2) + Store (WRD2, Local0) + if (LNotEqual (Local0, 0x1234)) + { + ERR_ (1) + } + else + { + Store ("++++++++ Word BufferField I/O PASS", Debug) + } + + Store (0x123, FLD2) + Store (FLD2, Local0) + if (LNotEqual (Local0, 0x123)) + { + ERR_ (1) + } + else + { + Store ("++++++++ 12-bit BufferField I/O PASS", Debug) + } + + Store (0x12345678, DWD2) + Store (DWD2, Local0) + if (LNotEqual (Local0, 0x12345678)) + { + ERR_ (1) + } + else + { + Store ("++++++++ Dword BufferField I/O PASS", Debug) + } + + Store (0x1234567887654321, QWD2) + Store (QWD2, Local0) + if (LNotEqual (Local0, 0x1234567887654321)) + { + ERR_ (1) + } + else + { + Store ("++++++++ Qword BufferField I/O PASS", Debug) + } + } + + + /* Field execution */ + + Method (FLDX) + { + Field (\_SB_.MEM.SMEM, AnyAcc, NoLock, Preserve) + { // Field: SMEM overlay using 32-bit field elements + SMD0, 32, // 32-bits + SMD1, 32, // 32-bits + SMD2, 32, // 32-bits + SMD3, 32 // 32-bits + } // Field: SMEM overlay using 32-bit field elements + Field (\_SB_.MEM.SMEM, AnyAcc, NoLock, Preserve) + { // Field: SMEM overlay using greater than 32-bit field elements + SME0, 69, // larger than an integer (32 or 64) + SME1, 97 // larger than an integer + } // Field: SMEM overlay using greater than 32-bit field elements + } + + + Method (MTX_, ) + { + /* Test "Force release" of mutex on method exit */ + + Acquire (MTXT, 0xFFFF) + Acquire (MTXX, 0xFFFF) + + Store ("++++++++ Acquiring Mutex MTX2", Debug) + Acquire (_GL_, 0xFFFF) + + + Store ("++++++++ Releasing Mutex MTX2", Debug) + Release (_GL_) + } + + + Method (OBJ2, 1) + { + Store ("++++++++ Creating Buffer BUFO", Debug) + Name (BUFO, Buffer (32) {}) + + Store ("++++++++ Creating OpRegion OPR2", Debug) + OperationRegion (OPR2, SystemMemory, Arg0, 256) + + Store ("++++++++ Creating Field(s) in OpRegion OPR2", Debug) + Field (OPR2, ByteAcc, NoLock, Preserve) + { + IDX2, 8, + DAT2, 8, + BNK2, 4 + } + + Store ("++++++++ Creating BankField BNK2 in OpRegion OPR2", Debug) + // + // mcw 3/20/00 - changed FET0, 4, FET1, 3 to FET0, 1, FET1, 1 + // + BankField (OPR2, BNK2, 0, ByteAcc, NoLock, Preserve) + { + FET0, 4, + FET1, 3 + } + + Store ("++++++++ Creating IndexField", Debug) + IndexField (IDX2, DAT2, ByteAcc, NoLock, Preserve) + { + FET2, 4, + FET3, 3 + } + + Store ("++++++++ SizeOf (BUFO)", Debug) + SizeOf (BUFO) + + Store ("++++++++ Store (SizeOf (BUFO), Local0)", Debug) + Store (SizeOf (BUFO), Local0) + + Store ("++++++++ Concatenate (\"abd\", \"def\", Local0)", Debug) + Concatenate ("abd", "def", Local0) + Store (Local0, Debug) + + Store ("++++++++ Concatenate (\"abd\", 0x7B, Local0)", Debug) + Concatenate ("abd", 0x7B, Local0) + Store (Local0, Debug) + + Store ("++++++++ Creating Event EVT2", Debug) + Event (EVT2) + + Store ("++++++++ Creating Mutex MTX2", Debug) + Mutex (MTX2, 0) + + Store ("++++++++ Creating Alias MTXA to MTX2", Debug) + Alias (MTX2, MTXA) + + Store ("++++++++ Acquiring Mutex MTX2", Debug) + Acquire (MTX2, 0xFFFF) + + Store ("++++++++ Acquiring Mutex MTX2 (2nd acquire)", Debug) + Acquire (MTX2, 1) + + Store ("++++++++ Releasing Mutex MTX2", Debug) + Release (MTX2) + + // Type 1 opcodes + + Store ("++++++++ Signalling Event EVT2", Debug) + Signal (EVT2) + + Store ("++++++++ Resetting Event EVT2", Debug) + Reset (EVT2) + + Store ("++++++++ Signalling Event EVT2", Debug) + Signal (EVT2) + + Store ("++++++++ Waiting Event EVT2", Debug) + Wait (EVT2, 0xFFFF) + + Store ("++++++++ Sleep", Debug) + Sleep (100) + + Store ("++++++++ Stall", Debug) + Stall (254) + + Store ("++++++++ NoOperation", Debug) + Noop + + // Type 2 Opcodes + + Store ("++++++++ Return from Method OBJ2", Debug) + return (4) + } + + + Method (NUM1, 0) + { + /* ADD */ + + Store ("++++++++ Add (0x12345678, 0x11111111, Local0)", Debug) + Add (0x12345678, 0x11111111, Local0) + + Store ("++++++++ Store (Add (0x12345678, 0x11111111), Local1)", Debug) + Store (Add (0x12345678, 0x11111111), Local1) + + Store ("++++++++ Checking result from ADD", Debug) + if (LNotEqual (Local0, Local1)) + { + ERR_ (0) + } + + + /* SUBTRACT */ + + Store ("++++++++ Subtract (0x87654321, 0x11111111, Local4)", Debug) + Subtract (0x87654321, 0x11111111, Local4) + + Store ("++++++++ Store (Subtract (0x87654321, 0x11111111), Local5)", Debug) + Store (Subtract (0x87654321, 0x11111111), Local5) + + Store ("++++++++ Checking result from SUBTRACT", Debug) + if (LNotEqual (Local4, Local5)) + { + ERR_ (0) + } + + + /* MULTIPLY */ + + Store ("++++++++ Multiply (33, 10, Local6)", Debug) + Multiply (33, 10, Local6) + + Store ("++++++++ Store (Multiply (33, 10), Local7)", Debug) + Store (Multiply (33, 10), Local7) + + + Store ("++++++++ Checking result from MULTIPLY", Debug) + if (LNotEqual (Local6, Local7)) + { + ERR_ (0) + } + + + /* DIVIDE */ + + Store ("++++++++ Divide (100, 9, Local1, Local2)", Debug) + Divide (100, 9, Local1, Local2) + + Store ("++++++++ Store (Divide (100, 9), Local3)", Debug) + Store (Divide (100, 9), Local3) + + Store ("++++++++ Checking (quotient) result from DIVIDE", Debug) + if (LNotEqual (Local2, Local3)) + { + ERR_ (0) + } + + + /* INCREMENT */ + + Store ("++++++++ Increment (Local0)", Debug) + Store (1, Local0) + Store (2, Local1) + Increment (Local0) + + Store ("++++++++ Checking result from INCREMENT", Debug) + if (LNotEqual (Local0, Local1)) + { + ERR_ (0) + } + + + /* DECREMENT */ + + Store ("++++++++ Decrement (Local0)", Debug) + Store (2, Local0) + Store (1, Local1) + Decrement (Local0) + + Store ("++++++++ Checking result from DECREMENT", Debug) + if (LNotEqual (Local0, Local1)) + { + ERR_ (0) + } + + + /* TOBCD */ + /* FROMBCD */ + + Store ("++++++++ ToBCD (0x1234, Local5)", Debug) + ToBCD (0x1234, Local5) + + Store ("++++++++ FromBCD (Local5, Local6)", Debug) + FromBCD (Local5, Local6) + + Store ("++++++++ Return (Local6)", Debug) + Return (Local6) + } + + + Method (CHEK) + { + + Store (3, Local0) + Store (3, Debug) + Store (Local0, Debug) + Store (7, Local1) + + Add (Local0, Local1) + if (LNotEqual (Local0, 3)) + { + ERR_ (2) + } + if (LNotEqual (Local1, 7)) + { + ERR_ (2) + } + + + Add (Local0, Local1, Local2) + if (LNotEqual (Local0, 3)) + { + ERR_ (2) + } + if (LNotEqual (Local1, 7)) + { + ERR_ (2) + } + } + + + Method (RET1) + { + Store (3, Local0) + Return (Local0) + } + + Method (RET2) + { + Return (RET1()) + } + + Method (RETZ) + { + RET2 () + } + + + Method (BITZ) + { + Store ("++++++++ FindSetLeftBit (0x00100100, Local0)", Debug) + FindSetLeftBit (0x00100100, Local0) + if (LNotEqual (Local0, 21)) + { + ERR_ (1) + } + + Store ("++++++++ FindSetRightBit (0x00100100, Local1)", Debug) + FindSetRightBit (0x00100100, Local1) + if (LNotEqual (Local1, 9)) + { + ERR_ (1) + } + + Store ("++++++++ And (0xF0F0F0F0, 0x11111111, Local2)", Debug) + And (0xF0F0F0F0, 0x11111111, Local2) + if (LNotEqual (Local2, 0x10101010)) + { + ERR_ (1) + } + + Store ("++++++++ NAnd (0xF0F0F0F0, 0x11111111, Local3)", Debug) + NAnd (0xF0F0F0F0, 0x11111111, Local3) + if (LNotEqual (Local3, 0xEFEFEFEF)) + { + ERR_ (1) + } + + Store ("++++++++ Or (0x11111111, 0x22222222, Local4)", Debug) + Or (0x11111111, 0x22222222, Local4) + if (LNotEqual (Local4, 0x33333333)) + { + ERR_ (1) + } + + Store ("++++++++ NOr (0x11111111, 0x22222222, Local5)", Debug) + NOr (0x11111111, 0x22222222, Local5) + if (LNotEqual (Local5, 0xCCCCCCCC)) + { + ERR_ (1) + } + + Store ("++++++++ XOr (0x11113333, 0x22222222, Local6)", Debug) + XOr (0x11113333, 0x22222222, Local6) + if (LNotEqual (Local6, 0x33331111)) + { + ERR_ (1) + } + + Store ("++++++++ ShiftLeft (0x11112222, 2, Local7)", Debug) + ShiftLeft (0x11112222, 2, Local7) + if (LNotEqual (Local7, 0x44448888)) + { + ERR_ (1) + } + + Store ("++++++++ ShiftRight (Local7, 2, Local7)", Debug) + ShiftRight (Local7, 2, Local7) + if (LNotEqual (Local7, 0x11112222)) + { + ERR_ (1) + } + + + Store ("++++++++ Not (Local0, Local1)", Debug) + Store (0x22224444, Local0) + Not (Local0, Local1) + if (LNotEqual (Local0, 0x22224444)) + { + ERR_ (2) + } + + if (LNotEqual (Local1, 0xDDDDBBBB)) + { + ERR_ (1) + } + + Return (Local7) + } + + + Method (LOGS) + { + + Store ("++++++++ Store (LAnd (0xFFFFFFFF, 0x11111111), Local0)", Debug) + Store (LAnd (0xFFFFFFFF, 0x11111111), Local0) + + Store ("++++++++ Store (LEqual (0xFFFFFFFF, 0x11111111), Local)", Debug) + Store (LEqual (0xFFFFFFFF, 0x11111111), Local1) + + Store ("++++++++ Store (LGreater (0xFFFFFFFF, 0x11111111), Local2)", Debug) + Store (LGreater (0xFFFFFFFF, 0x11111111), Local2) + + Store ("++++++++ Store (LGreaterEqual (0xFFFFFFFF, 0x11111111), Local3)", Debug) + Store (LGreaterEqual (0xFFFFFFFF, 0x11111111), Local3) + + Store ("++++++++ Store (LLess (0xFFFFFFFF, 0x11111111), Local4)", Debug) + Store (LLess (0xFFFFFFFF, 0x11111111), Local4) + + Store ("++++++++ Store (LLessEqual (0xFFFFFFFF, 0x11111111), Local5)", Debug) + Store (LLessEqual (0xFFFFFFFF, 0x11111111), Local5) + + Store ("++++++++ Store (LNot (0x31313131), Local6)", Debug) + Store (0x00001111, Local6) + Store (LNot (Local6), Local7) + if (LNotEqual (Local6, 0x00001111)) + { + ERR_ (2) + } + + if (LNotEqual (Local7, 0x0)) + { + ERR_ (1) + } + + + Store ("++++++++ Store (LNotEqual (0xFFFFFFFF, 0x11111111), Local7)", Debug) + Store (LNotEqual (0xFFFFFFFF, 0x11111111), Local7) + + Store ("++++++++ Lor (0x0, 0x1)", Debug) + if (Lor (0x0, 0x1)) + { + Store ("+_+_+_+_+ Lor (0x0, 0x1) returned TRUE", Debug) + } + + return (Local7) + } + + + Method (COND) + { + Store ("++++++++ Store (0x4, Local0)", Debug) + Store (0x4, Local0) + + Store ("++++++++ While (Local0)", Debug) + While (Local0) + { + Store ("++++++++ Decrement (Local0)", Debug) + Decrement (Local0) + } + + + Store ("++++++++ Store (0x3, Local6)", Debug) + Store (0x3, Local6) + + Store ("++++++++ While (Subtract (Local6, 1))", Debug) + While (Subtract (Local6, 1)) + { + Store ("++++++++ Decrement (Local6)", Debug) + Decrement (Local6) + } + + + Store ("++++++++ [LVL1] If (LGreater (0x2, 0x1))", Debug) + If (LGreater (0x2, 0x1)) + { + Store ("++++++++ [LVL2] If (LEqual (0x11111111, 0x22222222))", Debug) + If (LEqual (0x11111111, 0x22222222)) + { + Store ("++++++++ ERROR: If (LEqual (0x11111111, 0x22222222)) returned TRUE", Debug) + } + + else + { + Store ("++++++++ [LVL3] If (LNot (0x0))", Debug) + If (LNot (0x0)) + { + Store ("++++++++ [LVL4] If (LAnd (0xEEEEEEEE, 0x2))", Debug) + If (LAnd (0xEEEEEEEE, 0x2)) + { + Store ("++++++++ [LVL5] If (LLess (0x44444444, 0x3))", Debug) + If (LLess (0x44444444, 0x3)) + { + Store ("++++++++ ERROR: If (LLess (0x44444444, 0x3)) returned TRUE", Debug) + } + + else + { + Store ("++++++++ Exiting from nested IF/ELSE statements", Debug) + } + } + } + } + } + + + Store ("++++++++ [LVL1] If (LGreater (0x2, 0x1))", Debug) + If (LGreater (0x2, 0x1)) + { + Store ("++++++++ [LVL2] If (LEqual (0x11111111, 0x22222222))", Debug) + If (LEqual (0x11111111, 0x22222222)) + { + Store ("++++++++ ERROR: If (LEqual (0x11111111, 0x22222222)) returned TRUE", Debug) + } + + else + { + Store ("++++++++ [LVL3] If (LNot (0x0))", Debug) + If (LNot (0x0)) + { + Store ("++++++++ [LVL4] If (LAnd (0xEEEEEEEE, 0x2))", Debug) + If (LAnd (0xEEEEEEEE, 0x2)) + { + Store ("++++++++ [LVL5] If (LLess (0x44444444, 0x3))", Debug) + If (LLess (0x44444444, 0x3)) + { + Store ("++++++++ ERROR: If (LLess (0x44444444, 0x3)) returned TRUE", Debug) + } + + else + { + Store ("++++++++ Returning from nested IF/ELSE statements", Debug) + Return (Local6) + } + } + } + } + } + + } + + + Method (REFS) + { + Name (BBUF, Buffer() {0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7}) + + Name (NEST, Package () + { + Package () + { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 + }, + Package () + { + 0x11, 0x12, 0x12, 0x14, 0x15, 0x16 + } + }) + + /* Parser thinks this is a method invocation!! */ + + Store (RefOf (MAIN), Local5) + + // For this to work, ABCD must NOT exist. + + Store (CondRefOf (ABCD, Local0), Local1) + if (LNotEqual (Local1, 0)) + { + ERR_ (2) + } + + Store (CondRefOf (BBUF, Local0), Local1) + if (LNotEqual (Local1, Ones)) + { + ERR_ (2) + } + + Store (DeRefOf (Index (BBUF, 3)), Local6) + if (LNotEqual (Local6, 0xB3)) + { + ERR_ (2) + } + + Store (DeRefOf (Index (DeRefOf (Index (NEST, 1)), 3)), Local0) + if (LNotEqual (Local0, 0x14)) + { + ERR_ (2) + } + + + Store (0x11223344, Local0) + Store (RefOf (Local0), Local1) + + Store (DerefOf (Local1), Local2) + If (LNotEqual (Local2, 0x11223344)) + { + ERR_ (2) + } + + + /* Parser thinks this is a method invocation!! */ + + // RefOf (MAIN) + + + // RefOf (R___) + // RefOf (BBUF) + + // Store (RefOf (Local0), Local1) + + // CondRefOf (BBUF, Local2) + // CondRefOf (R___, Local3) + + // Store (DerefOf (Local1), Local4) + + // Return (Local4) + } + + + Method (INDX, 0) + { + Name(STAT,Package(4){}) + Store(0x44443333,Index(STAT,0)) + } + +//================================================================= +//================================================================= +//===================== iPCO TESTS ================================ +//================================================================= +//================================================================= +// +// +// test IfElseOp.asl +// +// test for IfOp and ElseOp, including validation of object stack cleanup +// + Device (IFEL) + { + Name (DWRD, 1) + Name (RSLT, 0) + + // IFNR control method executes IfOp branch with NO nested Return + // and no Else branch + Method (IFNR) + { + Store (DWRD, RSLT) + If (LEqual (DWRD, 1)) + { + Store (0, RSLT) + } + } // IFNR + + // NINR control method does not execute If branch and has no Else branch + Method (NINR) + { + Store (0, RSLT) + If (LNotEqual (DWRD, 1)) + { + Store (DWRD, RSLT) + } + } // NINR + + // IENR control method executes IfOp branch with NO nested Return + Method (IENR) + { + If (LEqual (DWRD, 1)) + { + Store (0, RSLT) + } + Else + { + Store (DWRD, RSLT) + } + } // IENR + + // ELNR control method executes ElseOp branch with NO nested Return + Method (ELNR) + { + If (LNotEqual (DWRD, 1)) + { + Store (DWRD, RSLT) + } + Else + { + Store (0, RSLT) + } + } // ELNR + + // IFRT control method executes IfOp branch with nested Return with + // no Else branch + Method (IFRT) + + { + If (LEqual (DWRD, 1)) + { + Return (0) + } + Return (DWRD) + } // IFRT + + // IERT control method executes IfOp branch with nested Return with + // Else branch + Method (IERT) + { + If (LEqual (DWRD, 1)) + { + Return (0) + } + Else + { + Return (DWRD) + } + } // IERT + + // ELRT control method executes ElseOp branch with nested Return + Method (ELRT) + { + If (LNotEqual (DWRD, 1)) + { + Return (DWRD) + } + Else + { + Return (0) + } + } // ELRT + + Method (TEST) + { + Store ("++++++++ IfElseOp Test", Debug) + + // IfOp with NO return value + IFNR() + If (LNotEqual (RSLT, 0)) + { + Return (RSLT) + } + + // IfOp with NO return value + NINR() + If (LNotEqual (RSLT, 0)) + { + Return (RSLT) + } + + // IfOp with NO return value + IENR() + If (LNotEqual (RSLT, 0)) + { + Return (RSLT) + } + + // ElseOp with NO return value + ELNR() + If (LNotEqual (RSLT, 0)) + { + Return (RSLT) + } + + // IfOp with return value + Store (IFRT, RSLT) + If (LNotEqual (RSLT, 0)) + { + Return (RSLT) + } + + // IfOp with return value + Store (IERT, RSLT) + If (LNotEqual (RSLT, 0)) + { + Return (RSLT) + } + + // ElseOp with return value + Store (ELRT, RSLT) + If (LNotEqual (RSLT, 0)) + { + Return (RSLT) + } + + Return (0) + } // TEST + } // IFEL + +// +// test NoSave.asl +// +// +// Internal test cases to validate IfOp (Operator (,,)) where Operator +// target is ZeroOp to throw away the results. +// Includes internal test cases for logical operators with no destination +// operands. +// + Device (NOSV) + { + Method (TEST) + { + Store ("++++++++ NoSave Test", Debug) + + Name (WRD, 0x1234) + + // + // Begin test of nested operators without saving results + // + + // Test If (And ()) with no save of And result + If (And (3, 1, )) + { + Store (1, WRD) // pass -- just do something + } + else + { + Return (1) // fail + } + + // Test If (And ()) with no save of And result + If (And (4, 1, )) + { + Return (2) // fail + } + else + { + Store (2, WRD) // pass -- just do something + } + + + // Test If (NAnd ()) with no save of NAnd result + If (NAnd (3, 1, )) + { + Store (3, WRD) // pass -- just do something + } + else + { + Return (3) // fail + } + + // Test If (NAnd ()) with no save of NAnd result + If (NAnd (0xFFFFFFFF, 0xFFFFFFFF, )) + { + Return (4) // fail + } + else + { + Store (4, WRD) // pass -- just do something + } + + + // Test If (NOr ()) with no save of NOr result + If (NOr (0, 1, )) + { + Store (5, WRD) // pass -- just do something + } + else + { + Return (5) // fail + } + + // Test If (NOr ()) with no save of NOr result + If (NOr (0xFFFFFFFE, 1, )) + { + Return (6) // fail + } + else + { + Store (6, WRD) // pass -- just do something + } + + + // Test If (Not ()) with no save of Not result + If (Not (1, )) + { + Store (7, WRD) // pass -- just do something + } + else + { + Return (7) // fail + } + + // Test If (Not ()) with no save of Not result + If (Not (0xFFFFFFFF, )) + { + Return (8) // fail + } + else + { + Store (8, WRD) // pass -- just do something + } + + + // Test If (Or ()) with no save of Or result + If (Or (3, 1, )) + { + Store (9, WRD) // pass -- just do something + } + else + { + Return (9) // fail + } + + // Test If (Or ()) with no save of Or result + If (Or (0, 0, )) + { + Return (10) // fail + } + else + { + Store (10, WRD) // pass -- just do something + } + + + // Test If (XOr ()) with no save of XOr result + If (XOr (3, 1, )) + { + Store (11, WRD) // pass -- just do something + } + else + { + Return (11) // fail + } + + // Test If (XOr ()) with no save of XOr result + If (XOr (3, 3, )) + { + Return (12) // fail + } + else + { + Store (12, WRD) // pass -- just do something + } + + + // + // Begin test of logical operators with no destination operands + // + + // Test If (LAnd ()) with no save of LAnd result + If (LAnd (3, 3)) + { + Store (21, WRD) // pass -- just do something + } + else + { + Return (21) // fail + } + + // Test If (LAnd ()) with no save of LAnd result + If (LAnd (3, 0)) + { + Return (22) // fail + } + else + { + Store (22, WRD) // pass -- just do something + } + + // Test If (LAnd ()) with no save of LAnd result + If (LAnd (0, 3)) + { + Return (23) // fail + } + else + { + Store (23, WRD) // pass -- just do something + } + + // Test If (LAnd ()) with no save of LAnd result + If (LAnd (0, 0)) + { + Return (24) // fail + } + else + { + Store (24, WRD) // pass -- just do something + } + + + // Test If (LEqual ()) with no save of LEqual result + If (LEqual (3, 3)) + { + Store (31, WRD) // pass -- just do something + } + else + { + Return (31) // fail + } + + // Test If (LEqual ()) with no save of LEqual result + If (LEqual (1, 3)) + { + Return (32) // fail + } + else + { + Store (32, WRD) // pass -- just do something + } + + + // Test If (LGreater ()) with no save of LGreater result + If (LGreater (3, 1)) + { + Store (41, WRD) // pass -- just do something + } + else + { + Return (41) // fail + } + + // Test If (LGreater ()) with no save of LGreater result + If (LGreater (4, 4)) + { + Return (42) // fail + } + else + { + Store (42, WRD) // pass -- just do something + } + + // Test If (LGreater ()) with no save of LGreater result + If (LGreater (1, 4)) + { + Return (43) // fail + } + else + { + Store (43, WRD) // pass -- just do something + } + + // Test If (LGreaterEqual ()) with no save of LGreaterEqual result + If (LGreaterEqual (3, 1)) + { + Store (44, WRD) // pass -- just do something + } + else + { + Return (44) // fail + } + + // Test If (LGreaterEqual ()) with no save of LGreaterEqual result + If (LGreaterEqual (3, 3)) + { + Store (45, WRD) // pass -- just do something + } + else + { + Return (45) // fail + } + + // Test If (LGreaterEqual ()) with no save of LGreaterEqual result + If (LGreaterEqual (3, 4)) + { + Return (46) // fail + } + else + { + Store (46, WRD) // pass -- just do something + } + + + // Test If (LLess ()) with no save of LLess result + If (LLess (1, 3)) + { + Store (51, WRD) // pass -- just do something + } + else + { + Return (51) // fail + } + + // Test If (LLess ()) with no save of LLess result + If (LLess (2, 2)) + { + Return (52) // fail + } + else + { + Store (52, WRD) // pass -- just do something + } + + // Test If (LLess ()) with no save of LLess result + If (LLess (4, 2)) + { + Return (53) // fail + } + else + { + Store (53, WRD) // pass -- just do something + } + + + // Test If (LLessEqual ()) with no save of LLessEqual result + If (LLessEqual (1, 3)) + { + Store (54, WRD) // pass -- just do something + } + else + { + Return (54) // fail + } + + // Test If (LLessEqual ()) with no save of LLessEqual result + If (LLessEqual (2, 2)) + { + Store (55, WRD) // pass -- just do something + } + else + { + Return (55) // fail + } + + // Test If (LLessEqual ()) with no save of LLessEqual result + If (LLessEqual (4, 2)) + { + Return (56) // fail + } + else + { + Store (56, WRD) // pass -- just do something + } + + + // Test If (LNot ()) with no save of LNot result + If (LNot (0)) + { + Store (61, WRD) // pass -- just do something + } + else + { + Return (61) // fail + } + + // Test If (LNot ()) with no save of LNot result + If (LNot (1)) + { + Return (62) // fail + } + else + { + Store (62, WRD) // pass -- just do something + } + + + // Test If (LNotEqual ()) with no save of LNotEqual result + If (LNotEqual (3, 3)) + { + Return (63) // fail + } + else + { + Store (63, WRD) // pass -- just do something + } + + // Test If (LNotEqual ()) with no save of LNotEqual result + If (LNotEqual (1, 3)) + { + Store (64, WRD) // pass -- just do something + } + else + { + Return (64) // fail + } + + + // Test If (LOr ()) with no save of LOr result + If (LOr (3, 1)) + { + Store (71, WRD) // pass -- just do something + } + else + { + Return (71) // fail + } + + // Test If (LOr ()) with no save of LOr result + If (LOr (0, 1)) + { + Store (72, WRD) // pass -- just do something + } + else + { + Return (72) // fail + } + + // Test If (LOr ()) with no save of LOr result + If (LOr (3, 0)) + { + Store (73, WRD) // pass -- just do something + } + else + { + Return (73) // fail + } + + // Test If (LOr ()) with no save of LOr result + If (LOr (0, 0)) + { + Return (74) // fail + } + else + { + Store (74, WRD) // pass -- just do something + } + + Return (0) + } // TEST + } // NOSV + + +// +// test IndxFld.asl +// +// IndexFld test +// This is just a subset of the many RegionOp/Index Field test cases. +// Tests index field element AccessAs macro. +// + Device (IDXF) + { // Test device name + + OperationRegion (SIO, SystemIO, 0x100, 2) + Field (SIO, ByteAcc, NoLock, Preserve) + { + INDX, 8, + DATA, 8 + } + IndexField (INDX, DATA, AnyAcc, NoLock, WriteAsOnes) + { + AccessAs (ByteAcc, 0), + IFE0, 8, + IFE1, 8, + IFE2, 8, + IFE3, 8, + IFE4, 8, + IFE5, 8, + IFE6, 8, + IFE7, 8, + IFE8, 8, + IFE9, 8, + } + + Method (TEST) + { + Store ("++++++++ IndxFld Test", Debug) + + Store (IFE0, Local0) + Store (IFE1, Local1) + Store (IFE2, Local2) + + Return (0) + } // TEST + } // IDXF + +// +// test NestdLor.asl +// + Scope (\_SB) // System Bus + { // _SB system bus + + Name (ZER0, 0) + Name (ZER1, 0) + Name (ZER2, 0) + Name (ONE0, 1) + + Device (NSTL) + { + Method (TEST) + { + Store ("++++++++ NestdLor Test", Debug) + + If (Lor (ZER0, Lor (ZER1, Lor (ZER2, ONE0)))) + { // Indicate Pass + Store (0x00, Local0) + } + + Else + { // Indicate Fail + Store (0x01, Local0) + } + + Return (Local0) + } // End Method TEST + } // Device NSTL + } // _SB system bus + +// +// test RetBuf.asl +// +// Test ReturnOp(Buffer) +// This is required to support Control Method Batteries on +// Dell Latitude Laptops (e.g., CP1-A) +// + Device (RTBF) + { + Method (SUBR, 1) + { + Return (Arg0) + } + + Method (RBUF) + { // RBUF: Return Buffer from local variable + Name (ABUF, Buffer() {"ARBITRARY_BUFFER"}) + + // store local buffer ABUF into Local0 + Store (ABUF, Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Buffer + If (LNotEqual (Local1, 3)) // Buffer type is 3 + { + Return (1) // failure + } + + // store value returned by control method SUBR into Local0 + Store (SUBR (ABUF), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Buffer + If (LNotEqual (Local1, 3)) // Buffer type is 3 + { + Return (2) // failure + } + + // allocate buffer using Local1 as buffer size (run-time evaluation) + Store (5, Local1) + Name (BUFR, Buffer(Local1) {}) + + // store value returned by control method SUBR into Local0 + Store (SUBR (BUFR), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Buffer + If (LNotEqual (Local1, 3)) // Buffer type is 3 + { + Return (3) // failure + } + + // store BUFR Buffer into Local0 + Store (BUFR, Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Buffer + If (LNotEqual (Local1, 3)) // Buffer type is 3 + { + Return (4) // failure + } + + + // return Local0 Buffer + Return (Local0) + } // RBUF + + Method (TEST) + { + Store ("++++++++ RetBuf Test", Debug) + + // store RBUF Buffer return value into Local0 + Store (RBUF, Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Buffer + If (LNotEqual (Local1, 3)) // Buffer type is 3 + { + Return (10) // failure + } + Else + { + Return (0) // success + } + } // TEST + } // RTBF + +// +// test RetLVal.asl +// +// Test ReturnOp(Lvalue) +// This is required to support _PSR on IBM ThinkPad 560D and +// _DCK on Toshiba Tecra 8000. +// + + Device (GPE2) + { + Method (_L03) + { + Store ("Method GPE2._L03 invoked", Debug) + Return () + } + + Method (_E05) + { + Store ("Method GPE2._E05 invoked", Debug) + Return () + } + } + + Device (PRW2) + { + Name (_PRW, Package(2) {Package(2){\GPE2, 0x05}, 3}) + } + + + Scope (\_GPE) + { + Name (ACST, 0xFF) + + Method (_L08) + { + Store ("Method _GPE._L08 invoked", Debug) + Return () + } + + Method (_E09) + { + Store ("Method _GPE._E09 invoked", Debug) + Return () + } + + Method (_E11) + { + Store ("Method _GPE._E11 invoked", Debug) + Notify (\PRW1, 2) + } + + Method (_L22) + { + Store ("Method _GPE._L22 invoked", Debug) + Return () + } + + Method (_L33) + { + Store ("Method _GPE._L33 invoked", Debug) + Return () + } + + Method (_E64) + { + Store ("Method _GPE._E64 invoked", Debug) + Return () + } + + } // _GPE + + Device (PRW1) + { + Name (_PRW, Package(2) {0x11, 3}) + } + + Device (PWRB) + { + Name (_HID, EISAID("PNP0C0C")) + Name (_PRW, Package(2) {0x33, 3}) + } + + + Scope (\_SB) // System Bus + { // _SB system bus + + Device (ACAD) + { // ACAD: AC adapter device + Name (_HID, "ACPI0003") // AC adapter device + + Name (_PCL, Package () {\_SB}) + + OperationRegion (AREG, SystemIO, 0x0372, 2) + Field (AREG, ByteAcc, NoLock, Preserve) + { + AIDX, 8, + ADAT, 8 + } + IndexField (AIDX, ADAT, ByteAcc, NoLock, Preserve) + { + , 1, // skips + ACIN, 1, + , 2, // skips + CHAG, 1, + , 3, // skips + , 7, // skips + ABAT, 1, + } // IndexField + + Method (_PSR) + { + Store (\_GPE.ACST, Local0) + Store (ACIN, Local1) + If (LNotEqual (\_GPE.ACST, Local1)) + { + Store (Local1, \_GPE.ACST) + // This Notify is commented because it causes a + // method error when running on a system without the + // specific device. + // Notify (\_SB_.ACAD, 0) + } + Return (Local0) + } // _PSR + + Method (_STA) + { + Return (0x0F) + } + + Method (_INI) + { + Store (ACIN, \_GPE.ACST) + } + } // ACAD: AC adapter device + + // test implicit return from control method + Method (DIS_, 1) + { + Store (Arg0, Local0) + } + + Device (RTLV) + { + // test implicit return inside nested if with explicit return of Lvalue + Method (_DCK, 1) + // Arg0: 1 == dock, 0 == undock + { + If (Arg0) + { // dock + Store (0x87, Local0) + + If (Local0) + { + DIS_ (0x23) + Return (1) + } + + Return (0) + } // dock + Else + { // undock + Store (Arg0, Local0) + + If (Local0) + { + DIS_ (0x23) + Return (1) + } + + Return (0) + } // undock + } // _DCK control method + + Method (TEST) + { + Store ("++++++++ RetLVal Test", Debug) + + // store _PSR return value into Local0 + Store (\_SB_.ACAD._PSR, Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number/Integer type is 1 + { + Return (1) // failure + } + + // test implicit return inside nested if with explicit return of Lvalue + Store (_DCK (1), Local2) + + // save Local2 object type value into Local3 + Store (ObjectType (Local2), Local3) + + // validate Local2 is a Number + If (LNotEqual (Local3, 1)) // Number/Integer type is 1 + { + Return (2) // failure + } + + If (LNotEqual (Local2, 1)) + { + Return (3) // failure + } + + Return (0) // success + } // TEST + } // RTLV + } // _SB system bus + +// +// test RetPkg.asl +// +// Test ReturnOp(Package) +// This is required to support _PRT on Dell Optiplex Workstations (e.g. GX1) +// + + Scope (\_SB) // System Bus + { // _SB system bus + Device(LNKA) + { + Name (_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name (_UID, 1) + } + Device(LNKB) + { + Name (_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name (_UID, 2) + } + Device(LNKC) + { + Name (_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name (_UID, 3) + } + Device(LNKD) + { + Name (_HID, EISAID("PNP0C0F")) // PCI interrupt link + Name (_UID, 4) + } + + Device (PCI1) + { // PCI1: Root PCI Bus + Name (_HID, "PNP0A03") // Need _HID for root device (String format) + Name (_ADR,0x00000000) + Name (_CRS,0) + + Name (_PRT, Package () + { + Package () {0x0004ffff, 0, LNKA, 0}, // Slot 1, INTA + Package () {0x0004ffff, 1, LNKB, 0}, // Slot 1, INTB + Package () {0x0004ffff, 2, LNKC, 0}, // Slot 1, INTC + Package () {0x0004ffff, 3, LNKD, 0}, // Slot 1, INTD + Package () {0x0005ffff, 0, \_SB_.LNKB, 0}, // Slot 2, INTA + Package () {0x0005ffff, 1, \_SB_.LNKC, 0}, // Slot 2, INTB + Package () {0x0005ffff, 2, \_SB_.LNKD, 0}, // Slot 2, INTC + Package () {0x0006ffff, 3, \_SB_.LNKA, 0}, // Slot 2, INTD + Package () {0x0006ffff, 0, LNKC, 0}, // Slot 3, INTA + Package () {0x0006ffff, 1, LNKD, 0}, // Slot 3, INTB + Package () {0x0006ffff, 2, LNKA, 0}, // Slot 3, INTC + Package () {0x0006ffff, 3, LNKB, 0}, // Slot 3, INTD + }) + + Device (PX40) + { // Map f0 space, Start PX40 + Name (_ADR,0x00070000) // Address+function. + } + } // PCI0: Root PCI Bus + + Device (RETP) + { + Method (RPKG) + { // RPKG: Return Package from local variable + + // store _PRT package into Local0 + Store (\_SB_.PCI1._PRT, Local0) + + // return Local0 Package + Return (Local0) + } // RPKG + + Method (TEST) + { + Store ("++++++++ RetPkg Test", Debug) + + // store RPKG package return value into Local0 + Store (RPKG, Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Package + If (LNotEqual (Local1, 4)) // Package type is 4 + { Return (1) } // failure + Else + { Return (0) } // success + } // TEST + } // RETP + } // _SB_ + +// +// test WhileRet.asl +// +// WhileRet.asl tests a ReturnOp nested in a IfOp nested in a WhileOp. +// + Device (WHLR) + { + Name (LCNT, 0) + Method (WIR) + { // WIR: control method that returns inside of IfOp inside of WhileOp + While (LLess (LCNT, 4)) + { + If (LEqual (LCNT, 2)) + { + Return (0) + } + + Increment (LCNT) + } + + Return (LCNT) + } // WIR: control method that returns inside of IfOp inside of WhileOp + + Method (TEST) + { + Store ("++++++++ WhileRet Test", Debug) + + Store (WIR, Local0) + + Return (Local0) + } // TEST + } // WHLR + +// +// test AndOrOp.asl +// +//This code tests the bitwise AndOp and OrOp Operator terms +// +//Syntax of Andop term +//And - Bitwise And +//AndTerm := And( +// Source1, //TermArg=>Integer +// Source2, //TermArg=>Integer +// Result //Nothing | SuperName +//) => Integer +//Source1 and Source2 are evaluated as integer data types, +// a bit-wise AND is performed, and the result is optionally +//stored into Result. +// +// +//Syntax of OrOp +//Or - Bit-wise Or +//OrTerm := Or( +// Source1, //TermArg=>Integer +// Source2 //TermArg=>Integer +// Result //Nothing | SuperName +//) => Integer +//Source1 and Source2 are evaluated as integer data types, +// a bit-wide OR is performed, and the result is optionally +//stored in Result +// + Device (ANDO) + { + OperationRegion (TMEM, SystemMemory, 0xC4, 0x02) + Field (TMEM, ByteAcc, NoLock, Preserve) + { + , 3, + TOUD, 13 + } + + //Create System Memory Operation Region and field overlays + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + SMDW, 32, // 32-bit DWORD + SMWD, 16, // 16-bit WORD + SMBY, 8, // 8-bit BYTE + }// Field(RAM) + + + //And with Byte Data + Name (BYT1, 0xff) + Name (BYT2, 0xff) + Name (BRSL, 0x00) + + //And with Word Data + Name (WRD1, 0xffff) + Name (WRD2, 0xffff) + Name (WRSL, 0x0000) + + //And with DWord Data + Name (DWD1, 0xffffffff) + Name (DWD2, 0xffffffff) + Name (DRSL, 0x00000000) + + Method (ANDP) + { + //Check with 1 And 1 on byte data + And(BYT1, BYT2, BRSL) + if(LNotEqual(BRSL,0xff)) + {Return(1)} + + //Check with 1 And 1 on Word data + And(WRD1, WRD2, WRSL) + if(LNotEqual(WRSL,0xffff)) + { + Return (1) // failure + } + + //Check with 1 And 1 Dword + And(DWD1, DWD2, DRSL) + if(LNotEqual(DRSL,0xffffffff)) + { + Return (1) // failure + } + + //Check with 0 And 0 on byte data + Store(0x00,BYT1) + Store(0x00,BYT2) + Store(0x00,BRSL) + And(BYT1, BYT2, BRSL) + if(LNotEqual(BRSL,0x00)) + { + Return (1) // failure + } + + //Check with 0 And 0 on Word data + Store (0x0000,WRD1) + Store (0x0000,WRD2) + Store (0x0000,WRSL) + And(WRD1, WRD2, WRSL) + if(LNotEqual(WRSL,0x0000)) + { + Return (1) // failure + } + + //Check with 0 And 0 Dword + Store (0x00000000,DWD1) + Store (0x00000000,DWD2) + Store (0x00000000,DRSL) + And(DWD1, DWD2, DRSL) + if(LNotEqual(DRSL,0x00000000)) + { + Return (1) // failure + } + + + //Check with 1 And 0 on byte data + Store(0x55,BYT1) + Store(0xAA,BYT2) + Store(0x00,BRSL) + And(BYT1, BYT2, BRSL) + if(LNotEqual(BRSL,0x00)) + { + Return (1) // failure + } + + //Check with 1 And 0 on Word data + Store (0x5555,WRD1) + Store (0xAAAA,WRD2) + Store (0x0000,WRSL) + And(WRD1, WRD2, WRSL) + if(LNotEqual(WRSL,0x0000)) + { + Return (1) // failure + } + + //Check with 1 And 0 on Dword + Store (0x55555555,DWD1) + Store (0xAAAAAAAA,DWD2) + Store (0x00000000,DRSL) + And(DWD1, DWD2, DRSL) + if(LNotEqual(DRSL,0x00000000)) + { + Return (1) // failure + } + + Store (0x1FFF, TOUD) + Store (TOUD, Local0) + if(LNotEqual(Local0,0x1FFF)) + { + Return (1) // failure + } + + //TBD- Do We need to check for system memory data also for each test case ?? + + Return(0) + + }//ANDP + + Method (OROP) + { + + //Check with 1 Ored with 1 on byte data + Store(0xff,BYT1) + Store(0xff,BYT2) + Store(0x00,BRSL) + Or(BYT1, BYT2, BRSL) + if(LNotEqual(BRSL,0xff)) + { + Return (1) // failure + } + + + //Check with 1 Ored with 1 on Word data + Store(0xffff,WRD1) + Store(0xffff,WRD2) + Store(0x0000,WRSL) + Or(WRD1, WRD2, WRSL) + if(LNotEqual(WRSL,0xffff)) + { + Return (1) // failure + } + + //Check with 1 Ored with 1 on Dword data + Store(0xffffffff,DWD1) + Store(0xffffffff,DWD2) + Store(0x00000000,DRSL) + Or(DWD1, DWD2, DRSL) + if(LNotEqual(DRSL,0xffffffff)) + { + Return (1) // failure + } + + //Check with 0 Ored with 0 on byte data + Store(0x00,BYT1) + Store(0x00,BYT2) + Store(0x00,BRSL) + Or(BYT1, BYT2, BRSL) + if(LNotEqual(BRSL,0x00)) + { + Return (1) // failure + } + + //Check with 0 Ored with 0 on Word data + Store (0x0000,WRD1) + Store (0x0000,WRD2) + Store (0x0000,WRSL) + Or(WRD1, WRD2, WRSL) + if(LNotEqual(WRSL,0x0000)) + { + Return (1) // failure + } + + //Check with 0 Ored with 0 Dword data + Store (0x00000000,DWD1) + Store (0x00000000,DWD2) + Store (0x00000000,DRSL) + Or(DWD1, DWD2, DRSL) + if(LNotEqual(DRSL,0x00000000)) + { + Return (1) // failure + } + + + //Check with 1 Ored with 0 on byte data + Store(0x55,BYT1) + Store(0xAA,BYT2) + Store(0x00,BRSL) + Or(BYT1, BYT2, BRSL) + if(LNotEqual(BRSL,0xff)) + { + Return (1) // failure + } + + //Check with 1 Ored with 0 on Word data + Store (0x5555,WRD1) + Store (0xAAAA,WRD2) + Store (0x0000,WRSL) + Or(WRD1, WRD2, WRSL) + if(LNotEqual(WRSL,0xffff)) + { + Return (1) // failure + } + + //Check with 1 Ored with 0 on Dword data + Store (0x55555555,DWD1) + Store (0xAAAAAAAA,DWD2) + Store (0x00000000,DRSL) + Or(DWD1, DWD2, DRSL) + if(LNotEqual(DRSL,0xffffffff)) + { + Return (1) // failure + } + + //TBD - Do We need to check for system memory data also for each test case ?? + + Return(0) + + }//OROP + + Method(TEST) + { + Store ("++++++++ AndOrOp Test", Debug) + + Name(RSLT,1) + //Call Andop method + Store(ANDP,RSLT) + if(LEqual(RSLT,1)) + { + Return (RSLT) + } + + //Call OrOp Method + Store(OROP,RSLT) + if(LEqual(RSLT,1)) + { + Return(RSLT) + } + + // + // Return original conditions to allow iterative execution + // + Store(0xff,BYT1) + Store(0xff,BYT2) + Store(0x00,BRSL) + Store (0xffff,WRD1) + Store (0xffff,WRD2) + Store (0x0000,WRSL) + Store (0xffffffff,DWD1) + Store (0xffffffff,DWD2) + Store (0x00000000,DRSL) + + Return(0) + } //TEST + } //ANDO + +// +// test BreakPnt.asl +// +// This code tests the BreakPoint opcode term. The syntax of BreakPoint Term is +// BreakPointTerm := BreakPoint +// Used for debugging, the Breakpoint opcode stops the execution and enters the AML debugger. +// In the non-debug version of the interpreter, BreakPoint is equivalent to Noop. +// + Device (BRKP) + { + Name(CNT0,0) + + Method (BK1) + { + BreakPoint + Return(0) + } + + Method (TEST) + { + Store ("++++++++ BreakPnt Test", Debug) + + Store(0,CNT0) + + //Check BreakPoint statement + While(LLess(CNT0,10)) + { + Increment(CNT0) + } + + //Check the BreakPoint statement + If(LEqual(CNT0,10)) + { + // BreakPoint + Return(0) + } + + //failed + Return(1) + } + } + +// +// test AddSubOp.asl +// + Device (ADSU) + { + // create System Memory Operation Region and field overlays + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + SMDW, 32, // 32-bit DWORD + SMWD, 16, // 16-bit WORD + SMBY, 8, // 8-bit BYTE + } // Field(RAM) + + Method (TEST) + { + Store ("++++++++ AddSubOp Test", Debug) + + Name (DWRD, 0x12345678) + Name (WRD, 0x1234) + Name (BYT, 0x12) + + // Test AddOp with DWORD data + Store (0x12345678, DWRD) + Add (DWRD, 7, DWRD) + If (LNotEqual (DWRD, 0x1234567F)) + { Return (DWRD) } + + // Test AddOp with WORD data + Add (WRD, 5, WRD) + If (LNotEqual (WRD, 0x1239)) + { Return (WRD) } + + // Test AddOp with BYTE data + Add (BYT, 3, BYT) + If (LNotEqual (BYT, 0x15)) + { Return (BYT) } + + // Test SubtractOp with DWORD data + Subtract (DWRD, 7, DWRD) + If (LNotEqual (DWRD, 0x12345678)) + { Return (DWRD) } + + // Test SubtractOp with WORD data + Subtract (WRD, 3, WRD) + If (LNotEqual (WRD, 0x1236)) + { Return (WRD) } + + // Test SubtractOp with BYTE data + Subtract (BYT, 3, BYT) + If (LNotEqual (BYT, 0x12)) + { Return (BYT) } + + + // test AddOp with DWORD SystemMemory OpRegion + Store (0x01234567, SMDW) + Add (SMDW, 8, SMDW) + If (LNotEqual (SMDW, 0x0123456F)) + { Return (SMDW) } + + // test SubtractOp with DWORD SystemMemory OpRegion + Subtract (SMDW, 7, SMDW) + If (LNotEqual (SMDW, 0x01234568)) + { Return (SMDW) } + + + // test AddOp with WORD SystemMemory OpRegion + Store (0x0123, SMWD) + Add (SMWD, 6, SMWD) + If (LNotEqual (SMWD, 0x0129)) + { Return (SMWD) } + + // test SubtractOp with WORD SystemMemory OpRegion + Subtract (SMWD, 5, SMWD) + If (LNotEqual (SMWD, 0x0124)) + { Return (SMWD) } + + + // test AddOp with BYTE SystemMemory OpRegion + Store (0x01, SMBY) + Add (SMBY, 4, SMBY) + If (LNotEqual (SMBY, 0x05)) + { Return (SMBY) } + + // test SubtractOp with BYTE SystemMemory OpRegion + Subtract (SMBY, 3, SMBY) + If (LNotEqual (SMBY, 0x02)) + { Return (SMBY) } + + Return (0) + } // TEST + } // ADSU + +// +// test IncDecOp.asl +// + Device (INDC) + { + // create System Memory Operation Region and field overlays + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + SMDW, 32, // 32-bit DWORD + SMWD, 16, // 16-bit WORD + SMBY, 8, // 8-bit BYTE + } // Field(RAM) + + Method (TEST) + { + Store ("++++++++ IncDecOp Test", Debug) + + Name (DWRD, 0x12345678) + Name (WRD, 0x1234) + Name (BYT, 0x12) + + // Test IncrementOp with DWORD data + Store (0x12345678, DWRD) + Increment (DWRD) + If (LNotEqual (DWRD, 0x12345679)) + { Return (DWRD) } + + // Test IncrementOp with WORD data + Increment (WRD) + If (LNotEqual (WRD, 0x1235)) + { Return (WRD) } + + // Test IncrementOp with BYTE data + Increment (BYT) + If (LNotEqual (BYT, 0x13)) + { Return (BYT) } + + // Test DecrementOp with DWORD data + Decrement (DWRD) + If (LNotEqual (DWRD, 0x12345678)) + { Return (DWRD) } + + // Test DecrementOp with WORD data + Decrement (WRD) + If (LNotEqual (WRD, 0x1234)) + { Return (WRD) } + + // Test DecrementOp with BYTE data + Decrement (BYT) + If (LNotEqual (BYT, 0x12)) + { Return (BYT) } + + + // test IncrementOp with DWORD SystemMemory OpRegion + Store (0x01234567, SMDW) + Increment (SMDW) + If (LNotEqual (SMDW, 0x01234568)) + { Return (SMDW) } + + // test DecrementOp with DWORD SystemMemory OpRegion + Decrement (SMDW) + If (LNotEqual (SMDW, 0x01234567)) + { Return (SMDW) } + + + // test IncrementOp with WORD SystemMemory OpRegion + Store (0x0123, SMWD) + Increment (SMWD) + If (LNotEqual (SMWD, 0x0124)) + { Return (SMWD) } + + // test DecrementOp with WORD SystemMemory OpRegion + Decrement (SMWD) + If (LNotEqual (SMWD, 0x0123)) + { Return (SMWD) } + + + // test IncrementOp with BYTE SystemMemory OpRegion + Store (0x01, SMBY) + Increment (SMBY) + If (LNotEqual (SMBY, 0x02)) + { Return (SMBY) } + + // test DecrementOp with BYTE SystemMemory OpRegion + Decrement (SMBY) + If (LNotEqual (SMBY, 0x01)) + { Return (SMBY) } + + Return (0) + } // TEST + } // INDC + +// +// test LOps.asl +// +//This source tests all the logical operators. Logical operators in ASL are as follows. +//LAnd, LEqual, LGreater, LLess, LNot, LNotEqual, LOr. +// Success will return 0 and failure will return a non zero number. Check the source code for +// non zero number to find where the test failed + + Device (LOPS) + { + //Create System Memory Operation Region and field overlays + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + SMDW, 32, // 32-bit DWORD + SMWD, 16, // 16-bit WORD + SMBY, 8, // 8-bit BYTE + }// Field(RAM) + + //And with Byte Data + Name (BYT1, 0xff) + Name (BYT2, 0xff) + Name (BRSL, 0x00) + + //And with Word Data + Name (WRD1, 0xffff) + Name (WRD2, 0xffff) + Name (WRSL, 0x0000) + + //And with DWord Data + Name (DWD1, 0xffffffff) + Name (DWD2, 0xffffffff) + Name (DRSL, 0x00000000) + + Name(RSLT,1) + + Method (ANDL,2) // Test Logical And + { + //test with the arguments passed + if(LEqual(Arg0,Arg1)) + { Store(LAnd(Arg0,Arg1),RSLT) + if(LNotEqual(Ones,RSLT)) + {Return(11)} + } + + //test with he locals + Store(Arg0,Local0) + Store(Arg1,Local1) + + if(LEqual(Local0,Local1)) + { + Store(LAnd(Local0,Local1),RSLT) + if(LNotEqual(Ones,RSLT)) + {Return(12)} + } + + //test with BYTE data + if(LEqual(BYT1,BYT2)) + { Store(LAnd(BYT1,BYT2),BRSL) + if(LNotEqual(Ones,BRSL)) + {Return(13)} + } + + //test with WORD data + if(LEqual(WRD1,WRD2)) + { Store(LAnd(WRD1,WRD2),WRSL) + if(LNotEqual(Ones,WRSL)) + {Return(14)} + } + + //test with DWORD data + if(LEqual(DWD1,DWD2)) + { Store(LAnd(DWD1,DWD2),DRSL) + if(LNotEqual(Ones,DRSL)) + {Return(15)} + } + + //Test for system memory data for each test case. + + Store(0xff,BYT1) + Store(0xff,SMBY) + Store(0x00,BRSL) + + //test with BYTE system memory data + if(LEqual(BYT1,SMBY)) + { Store(LAnd(BYT1,SMBY),BRSL) + if(LNotEqual(Ones,BRSL)) + {Return(16)} + } + + Store (0xffff,WRD1) + Store(0xffff,SMWD) + Store(0x0000,WRSL) + //test with WORD system memory data + if(LEqual(WRD1,SMWD)) + { Store(LAnd(WRD1,SMWD),WRSL) + if(LNotEqual(Ones,WRSL)) + {Return(17)} + } + + Store(0x000000,DRSL) + Store (0xffffff,DWD1) + Store(0xffffff,SMDW) + + //test with DWORD system memory data + if(LEqual(DWD1,SMDW)) + { Store(LAnd(DWD1,SMDW),DRSL) + if(LNotEqual(Ones,DRSL)) + {Return(18)} + } + + Return(0) + + }//ANDL + + //Test the LOr Operator + + Method (ORL_,2) + {//ORL_ + + //test with the arguments passed + if(LEqual(Arg0,Arg1)) + { + Store(LOr(Arg0,Arg1),RSLT) + if(LNotEqual(Ones,RSLT)) + { + Return(21) + } + } + + //test with he locals + Store(Arg0,Local0) + Store(Arg1,Local1) + + if(LEqual(Local0,Local1)) + { + Store(LOr(Local0,Local1),RSLT) + if(LNotEqual(Ones,RSLT)) + {Return(22)} + } + + //Check with 1 LOred with 0 on byte data + Store(0xff,BYT1) + Store(0x00,BYT2) + Store(0x00,BRSL) + + if(LNotEqual(BYT1, BYT2)) + { + Store(LOr(BYT1, BYT2), BRSL) + if(LNotEqual(Ones,BRSL)) + {Return(23)} + } + + //Check with 1 LOred with 0 on WORD data + Store(0xffff,WRD1) + Store(0x0000,WRD2) + Store(0x0000,WRSL) + + if(LNotEqual(WRD1, WRD2)) + { + Store(LOr(WRD1, WRD2), WRSL) + if(LNotEqual(Ones,WRSL)) + {Return(24)} + } + + //Check with 1 LOred with 0 on DWORD data + Store(0xffffffff,DWD1) + Store(0x00000000,DWD2) + Store(0x00000000,DRSL) + + if(LNotEqual(DWD1, DWD2)) + { + Store(LOr(DWD1, DWD2), DRSL) + if(LNotEqual(Ones,DRSL)) + {Return(25)} + } + + Store(0x00,BYT1) + Store(0xff,SMBY) + Store(0x00,BRSL) + + //test with BYTE system memory data + if(LEqual(BYT1,SMBY)) + { Store(LOr(BYT1,SMBY),BRSL) + if(LNotEqual(Ones,BRSL)) + {Return(26)} + } + + Store (0x0000,WRD1) + Store(0xffff,SMWD) + Store(0x0000,WRSL) + + //test with WORD system memory data + if(LEqual(WRD1,SMWD)) + { Store(LOr(WRD1,SMWD),WRSL) + if(LNotEqual(Ones,WRSL)) + {Return(27)} + } + + + Store(0x00000000,DWD1) + Store(0xffffffff,SMDW) + Store(0x00000000,DRSL) + + //test with DWORD system memory data + if(LEqual(DWD1,SMDW)) + { Store(LAnd(DWD1,SMDW),DRSL) + if(LNotEqual(Ones,DRSL)) + {Return(28)} + } + Return(0) + + }//ORL_ + + //This method tests LGreater and LNot operator + Method(LSGR,2) + {//LSGR + + //Test on arguements passed + + //in test data, Arg1 > Arg0 + if(LEqual(Ones,LNot(LGreater(Arg1,Arg0)))) + {Return(31)} + + //test LLessEqual + if(LEqual(Ones,LNot(LGreaterEqual(Arg1,Arg0)))) + {Return(32)} + + if(LEqual(Ones,LLess(Arg1,Arg0))) + {Return(33)} + + //test LLessEqual + if(LEqual(Ones,LLessEqual(Arg1,Arg0))) + {Return(34)} + + Store(Arg0,Local0) + Store(Arg1,Local1) + + //test with the locals + if(LNot(LGreater(Local1,Local0))) + {Return(35)} + + //test on Byte data + Store(0x12,BYT1) + Store(0x21,BYT2) + + if(LNot(LGreater(BYT2,BYT1))) + {Return(36)} + + if(LNot(LLess(BYT1,BYT2))) + {Return(37)} + + //test LGreaterEqual with byte data + if(LNot(LGreaterEqual(BYT2,BYT1))) + {Return(38)} + + //test LLessEqual byte data + if(LNot(LLessEqual(BYT1,BYT2))) + {Return(39)} + + + //test on Word data + Store(0x1212,WRD1) + Store(0x2121,WRD2) + + if(LNot(LGreater(WRD2,WRD1))) + {Return(310)} + + if(LNot(LLess(WRD1,WRD2))) + {Return(311)} + + //Test LGreaterEqual with Word Data + if(LNot(LGreaterEqual(WRD2,WRD1))) + {Return(312)} + + + //Test LLessEqual with Word Data + if(LNot(LLessEqual(WRD1,WRD2))) + {Return(313)} + + //test on DWord data + Store(0x12121212,DWD1) + Store(0x21212121,DWD2) + + if(LNot(LGreater(DWD2,DWD1))) + {Return(314)} + + if(LNot(LLess(DWD1,DWD2))) + {Return(315)} + + + //Test LGreaterEqual with Dword + if(LNot(LGreaterEqual(DWD2,DWD1))) + {Return(316)} + + //Test LLessEqual DWord + if(LNot(LLessEqual(DWD1,DWD2))) + {Return(317)} + + Return(0) + }//LSGR + + //The test method + Method(TEST) + { + Store ("++++++++ LOps Test", Debug) + + Store(0,RSLT) + //Call LAndOp method + Store(ANDL(2,2),RSLT) + if(LNotEqual(RSLT,0)) + {Return(RSLT)} + + //Call LOrOp Method + Store(ORL_(5,5),RSLT) + if(LNotEqual(RSLT,0)) + {Return(RSLT)} + + //Call LSGR Method + Store(LSGR(5,7),RSLT) + if(LNotEqual(RSLT,0)) + {Return(RSLT)} + + Return(0) + }//TEST + }//LOPS + +// +// test FdSetOps.asl +// +// FindSetLeftBit - Find Set Left Bit +// FindSetLeftBitTerm := FindSetLeftBit +// ( Source, //TermArg=>Integer +// Result //Nothing | SuperName +// ) => Integer +// Source is evaluated as integer data type, and the one-based bit location of +// the first MSb (most significant set bit) is optionally stored into Result. +// The result of 0 means no bit was set, 1 means the left-most bit set is the +// first bit, 2 means the left-most bit set is the second bit, and so on. +// FindSetRightBit - Find Set Right Bit + +// FindSetRightBitTerm := FindSetRightBit +// ( Source, //TermArg=>Integer +// Result //Nothing | SuperName +// ) => Integer +// Source is evaluated as integer data type, and the one-based bit location of +// the most LSb (least significant set bit) is optionally stored in Result. +// The result of 0 means no bit was set, 32 means the first bit set is the +// 32nd bit, 31 means the first bit set is the 31st bit, and so on. + +// If the Control method is success Zero is returned. Otherwise a non-zero +// number is returned. +// + Device (FDSO) + { // FDSO + + // Create System Memory Operation Region and field overlays + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + SMDW, 32, // 32-bit DWORD + SMWD, 16, // 16-bit WORD + SMBY, 8, // 8-bit BYTE + } // Field(RAM) + + // Byte Data + Name (BYT1, 1) + Name (BRSL, 0x00) + + // Word Data + Name (WRD1, 0x100) + Name (WRSL, 0x0000) + + // DWord Data + Name (DWD1, 0x10000) + Name (DRSL, 0x00000000) + Name (RSLT, 1) + Name (CNTR, 1) + + Method (SHFT,2) + // Arg0 is the actual data and Arg1 is the bit position + { // SHFT + Store (Arg0, Local0) + Store (Arg1, Local1) + + FindSetLeftBit (Arg0, BRSL) + If (LNotEqual (BRSL, Arg1)) + { Return (0x11) } + If (LNotEqual (Arg0, Local0)) + { Return (0x12) } + + FindSetLeftBit (Local0, BRSL) + If (LNotEqual (BRSL, Local1)) + { Return (0x13) } + If (LNotEqual (Arg0, Local0)) + { Return (0x14) } + + // test the byte value for SetLeftBit + Store (7, BYT1) + FindSetLeftBit (BYT1, BRSL) + If (LNotEqual (BRSL, 3)) + { Return (0x15) } + If (LNotEqual (BYT1, 7)) + { Return (0x16) } + + Store (1, BYT1) + Store (1, CNTR) + While (LLessEqual (CNTR, 8)) + { // FindSetLeftBit check loop for byte data + FindSetLeftBit (BYT1, BRSL) + If (LNotEqual (BRSL, CNTR)) + { Return (0x17) } + + // Shift the bits to check the same + ShiftLeft (BYT1, 1, BYT1) + Increment (CNTR) + } // FindSetLeftBit check loop for byte data + + + // Check BYTE value for SetRightBit + Store (7, BYT1) + FindSetRightBit (BYT1, BRSL) + If (LNotEqual (BRSL, 1)) + { Return (0x21) } + If (LNotEqual (BYT1, 7)) + { Return (0x22) } + + Store (1, CNTR) + Store (0xFF, BYT1) + While (LLessEqual (CNTR, 8)) + { // FindSetRightBit check loop for byte data + FindSetRightBit (BYT1, BRSL) + If (LNotEqual (BRSL, CNTR)) + { Return (0x23) } + + ShiftLeft (BYT1, 1, BYT1) + Increment (CNTR) + } // FindSetRightBit check loop for byte data + + + // Test Word value for SetLeftBit + Store (9, CNTR) + Store (0x100, WRD1) + While (LLessEqual (CNTR, 16)) + { + // FindSetLeftBit check loop for Word data + FindSetLeftBit (WRD1, WRSL) + If (LNotEqual (WRSL, CNTR)) + { Return (0x31) } + + // Shift the bits to check the same + ShiftLeft (WRD1, 1, WRD1) + Increment (CNTR) + } // FindSetLeftBit check loop for Word data + + // Check Word value for SetRightBit + Store (9, CNTR) + Store (0xFF00, WRD1) + While (LLessEqual (CNTR, 16)) + { + // FindSetRightBit check loop for Word data + FindSetRightBit (WRD1, WRSL) + If (LNotEqual (WRSL, CNTR)) + { Return (0x32) } + + ShiftLeft (WRD1, 1, WRD1) + Increment (CNTR) + } // FindSetRightBit check loop for Word data + + // Test the DWord value for SetLeftBit + Store (17, CNTR) + Store (0x10000, DWD1) + While (LLessEqual (CNTR, 32)) + { + // FindSetLeftBit check loop for Dword + FindSetLeftBit (DWD1, DRSL) + If (LNotEqual (DRSL, CNTR)) + { Return (0x41) } + + // Shift the bits to check the same + ShiftLeft (DWD1, 1, DWD1) + Increment (CNTR) + } // FindSetLeftBit check loop for Dword + + // Check DWord value for SetRightBit + Store (17, CNTR) + Store (0xFFFF0000, DWD1) + While (LLessEqual (CNTR, 32)) + { // FindSetRightBit Check loop for DWORD + FindSetRightBit (DWD1, DRSL) + If (LNotEqual (DRSL, CNTR)) + { Return (0x42) } + + ShiftLeft (DWD1, 1, DWD1) + Increment (CNTR) + } // FindSetRightBit Check loop for DWORD + + Return (0) + } // SHFT + + // Test method called from amlexec + Method (TEST) + { // TEST + + Store ("++++++++ FdSetOps Test", Debug) + + Store (SHFT (0x80, 8), RSLT) + If (LNotEqual (RSLT, 0)) + { Return (RSLT) } + + Return (0) // pass + } // TEST + } // Device FDSO + +// +// test MulDivOp.asl +// + Device (MLDV) + { + // create System Memory Operation Region and field overlays + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + SMDW, 32, // 32-bit DWORD + SMWD, 16, // 16-bit WORD + SMBY, 8, // 8-bit BYTE + } // Field(RAM) + + Method (TEST) + { + Store ("++++++++ MulDivOp Test", Debug) + + Name (RMDR, 0) + Name (DWRD, 0x12345678) + Name (WRD, 0x1234) + Name (BYT, 0x12) + + // Test MultiplyOp with DWORD data + Store (0x12345678, DWRD) + Multiply (DWRD, 3, DWRD) + If (LNotEqual (DWRD, 0x369D0368)) + { Return (DWRD) } + + // Test MultiplyOp with WORD data + Multiply (WRD, 4, WRD) + If (LNotEqual (WRD, 0x48D0)) + { Return (WRD) } + + // Test MultiplyOp with BYTE data + Multiply (BYT, 5, BYT) + If (LNotEqual (BYT, 0x5A)) + { Return (BYT) } + + // Test DivideOp with DWORD data + Divide (DWRD, 3, DWRD, RMDR) + If (LNotEqual (DWRD, 0x12345678)) + { Return (DWRD) } + If (LNotEqual (RMDR, 0)) + { Return (RMDR) } + + // Test DivideOp with WORD data + Divide (WRD, 4, WRD, RMDR) + If (LNotEqual (WRD, 0x1234)) + { Return (WRD) } + If (LNotEqual (RMDR, 0)) + { Return (RMDR) } + + // Test DivideOp with BYTE data + Divide (BYT, 5, BYT, RMDR) + If (LNotEqual (BYT, 0x12)) + { Return (BYT) } + If (LNotEqual (RMDR, 0)) + { Return (RMDR) } + + + // test MultiplyOp with DWORD SystemMemory OpRegion + Store (0x01234567, SMDW) + Multiply (SMDW, 2, SMDW) + If (LNotEqual (SMDW, 0x02468ACE)) + { Return (SMDW) } + + // test DivideOp with DWORD SystemMemory OpRegion + Divide (SMDW, 3, SMDW, RMDR) + If (LNotEqual (SMDW, 0x00C22E44)) + { Return (SMDW) } + If (LNotEqual (RMDR, 2)) + { Return (RMDR) } + + + // test MultiplyOp with WORD SystemMemory OpRegion + Store (0x0123, SMWD) + Multiply (SMWD, 3, SMWD) + If (LNotEqual (SMWD, 0x369)) + { Return (SMWD) } + + // test DivideOp with WORD SystemMemory OpRegion + Divide (SMWD, 2, SMWD, RMDR) + If (LNotEqual (SMWD, 0x01B4)) + { Return (SMWD) } + If (LNotEqual (RMDR, 1)) + { Return (RMDR) } + + + // test MultiplyOp with BYTE SystemMemory OpRegion + Store (0x01, SMBY) + Multiply (SMBY, 7, SMBY) + If (LNotEqual (SMBY, 0x07)) + { Return (SMBY) } + + // test DivideOp with BYTE SystemMemory OpRegion + Divide (SMBY, 4, SMBY, RMDR) + If (LNotEqual (SMBY, 0x01)) + { Return (SMBY) } + If (LNotEqual (RMDR, 3)) + { Return (RMDR) } + + Return (0) + } // TEST + } // MLDV + +// +// test NBitOps.asl +// +//NAnd - Bit-wise NAnd +//NAndTerm := NAnd( +// Source1, //TermArg=>Integer +// Source2 //TermArg=>Integer +// Result //Nothing | SuperName +//) => Integer +//Source1 and Source2 are evaluated as integer data types, a bit-wise NAND is performed, and the result is optionally +//stored in Result. + +//NOr - Bitwise NOr +//NOrTerm := NOr( +// Source1, //TermArg=>Integer +// Source2 //TermArg=>Integer +// Result //Nothing | SuperName +//) => Integer +//Source1 and Source2 are evaluated as integer data types, a bit-wise NOR is performed, and the result is optionally +//stored in Result. +// Not - Not +//NotTerm := Not( +// Source, //TermArg=>Integer +// Result //Nothing | SuperName +//) => Integer +//Source1 is evaluated as an integer data type, a bit-wise NOT is performed, and the result is optionally stored in +//Result. + +//If the Control method is success Zero is returned else a non-zero number is returned + + Device (NBIT) + {//NBIT + + //Create System Memory Operation Region and field overlays + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + SMDW, 32, // 32-bit DWORD + SMWD, 16, // 16-bit WORD + SMBY, 8, // 8-bit BYTE + }// Field(RAM) + + + //And with Byte Data + Name (BYT1, 0xff) + Name (BYT2, 0xff) + Name (BRSL, 0x00) + + //And with Word Data + Name (WRD1, 0xffff) + Name (WRD2, 0xffff) + Name (WRSL, 0x0000) + + //And with DWord Data + Name (DWD1, 0xffffffff) + Name (DWD2, 0xffffffff) + Name (DRSL, 0x00000000) + Name(RSLT,1) + + + Name(ARSL,0x00) + Name(LRSL,0x00) + + Method(NNDB,2) + {//NNDB + + Store(0xffffffff,SMDW) + Store(0xffff,SMWD) + Store(0xff,SMBY) + + + NAnd(Arg0,Arg1,ARSL) + if(LNotEqual(ARSL,0xfffffffd)) + {Return(11)} + + Store(Arg0,local0) + Store(Arg1,Local1) + + NAnd(Local0,Local1,LRSL) + if(LNotEqual(LRSL,0xfffffffd)) + {Return(12)} + + + //Byte data + NAnd(BYT1,BYT2,BRSL) + if(LNotEqual(BRSL,0xffffff00)) + {Return(13)} + + //Word Data + NAnd(WRD1,WRD2,WRSL) + if(LNotEqual(WRSL,0xffff0000)) + {Return(14)} + + //DWord Data + NAnd(DWD1,DWD2,DRSL) + if(LNotEqual(DRSL,0x00000000)) + {Return(15)} + + //Byte data + NAnd(SMBY,0xff,BRSL) + if(LNotEqual(BRSL,0xffffff00)) + {Return(16)} + + //Word Data + NAnd(SMWD,0xffff,WRSL) + if(LNotEqual(WRSL,0xffff0000)) + {Return(17)} + + //DWord Data + NAnd(SMDW,0xffffffff,DRSL) + if(LNotEqual(DRSL,0x00000000)) + {Return(18)} + + Return(0) + + }//NNDB + + Method(NNOR,2) + {//NNOR + + NOr(Arg0,Arg1,ARSL) + if(LNotEqual(ARSL,0xfffffffd)) + {Return(21)} + + Store(Arg0,local0) + Store(Arg1,Local1) + + NOr(Local0,Local1,LRSL) + if(LNotEqual(LRSL,0xfffffffd)) + {Return(22)} + + + //Byte data + NOr(BYT1,BYT2,BRSL) + if(LNotEqual(BRSL,0xffffff00)) + {Return(23)} + + //Word Data + NOr(WRD1,WRD2,WRSL) + if(LNotEqual(WRSL,0xffff0000)) + {Return(24)} + + //DWord Data + NOr(DWD1,DWD2,DRSL) + if(LNotEqual(DRSL,0x00000000)) + {Return(25)} + + //System Memory Byte data + NOr(SMBY,0xff,BRSL) + if(LNotEqual(BRSL,0xffffff00)) + {Return(26)} + + //System Memory Word Data + NOr(SMWD,0xffff,WRSL) + if(LNotEqual(WRSL,0xffff0000)) + {Return(27)} + + //System Memory DWord Data + NOr(SMDW,0xffffffff,DRSL) + if(LNotEqual(DRSL,0x00000000)) + {Return(28)} + + Return(0) + + }//NNOR + + Method(NNOT,2) + {//NNOT + + Or(Arg0,Arg1,ARSL) + Not(ARSL,ARSL) + if(LNotEqual(ARSL,0xfffffffd)) + {Return(31)} + + Store(Arg0,local0) + Store(Arg1,Local1) + + Or(Local0,Local1,LRSL) + Not(LRSL,LRSL) + if(LNotEqual(LRSL,0xfffffffd)) + {Return(32)} + + + //Byte data + Or(BYT1,BYT2,BRSL) + Not(BRSL,BRSL) + if(LNotEqual(BRSL,0xffffff00)) + {Return(33)} + + //Word Data + Or(WRD1,WRD2,WRSL) + Not(WRSL,WRSL) + if(LNotEqual(WRSL,0xffff0000)) + {Return(34)} + + //DWord Data + Or(DWD1,DWD2,DRSL) + Not(DRSL,DRSL) + if(LNotEqual(DRSL,0x00000000)) + {Return(35)} + + //System Memory Byte data + Or(SMBY,0xff,BRSL) + Not(BRSL,BRSL) + if(LNotEqual(BRSL,0xffffff00)) + {Return(36)} + + //System Memory Word Data + Or(SMWD,0xffff,WRSL) + Not(WRSL,WRSL) + if(LNotEqual(WRSL,0xffff0000)) + {Return(37)} + + //System Memory DWord Data + Or(SMDW,0xffffffff,DRSL) + Not(DRSL,DRSL) + if(LNotEqual(DRSL,0x00000000)) + {Return(38)} + + Return(0) + }//NNOT + + + Method(TEST) + { + + Store ("++++++++ NBitOps Test", Debug) + + Store(NNDB(2,2),RSLT) + if(LNotEqual(RSLT,0)) + {Return(RSLT)} + + Store(NNOR(2,2),RSLT) + if(LNotEqual(RSLT,0)) + {Return(RSLT)} + + Store(NNOT(2,2),RSLT) + if(LNotEqual(RSLT,0)) + {Return(RSLT)} + + + Return(0) + } + + }//Device NBIT + +// +// test ShftOp.asl +// +//ShiftRightTerm := ShiftRight( +// Source, //TermArg=>Integer +// ShiftCount //TermArg=>Integer +// Result //Nothing | SuperName +//) => Integer +//Source and ShiftCount are evaluated as integer data types. Source is shifted right with the most significant bit +//zeroed ShiftCount times. The result is optionally stored into Result. + +//ShiftLeft( +// Source, //TermArg=>Integer +// ShiftCount //TermArg=>Integer +// Result //Nothing | SuperName +//) => Integer +//Source and ShiftCount are evaluated as integer data types. Source is shifted left with the least significant +//bit zeroed ShiftCount times. The result is optionally stored into Result. + +//If the Control method is success Zero is returned else a non-zero number is returned + Device (SHFT) + {//SHFT + + //Create System Memory Operation Region and field overlays + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + SMDW, 32, // 32-bit DWORD + SMWD, 16, // 16-bit WORD + SMBY, 8, // 8-bit BYTE + }// Field(RAM) + + + Name(SHFC,0x00) + + //And with Byte Data + Name (BYT1, 0xff) + Name (BRSL, 0x00) + + //And with Word Data + Name (WRD1, 0xffff) + Name (WRSL, 0x0000) + + //And with DWord Data + Name (DWD1, 0xffffffff) + Name (DRSL, 0x00000000) + + Name(RSLT,1) + + Name(ARSL,0x00) + Name(LRSL,0x00) + + Method(SLFT,2) + {//SLFT + + Store(0xffffffff,SMDW) + Store(0xffff,SMWD) + Store(0xff,SMBY) + + + //Arg0-> 2 & Arg1->2 + ShiftLeft(Arg0,Arg1,ARSL) + if(LNotEqual(ARSL,8)) + {Return(11)} + + Store(Arg0,local0) + Store(Arg1,Local1) + + //Local0->8 and Local1->2 + ShiftLeft(Local0,Local1,LRSL) + if(LNotEqual(LRSL,8)) + {Return(12)} + + Store(2,SHFC) + //Byte data + ShiftLeft(BYT1,SHFC,BRSL) + if(LNotEqual(BRSL,0x3FC)) + {Return(13)} + + Store(4,SHFC) + //Word Data + ShiftLeft(WRD1,SHFC,WRSL) + if(LNotEqual(WRSL,0xFFFF0)) + {Return(14)} + + Store(8,SHFC) + //DWord Data + ShiftLeft(DWD1,SHFC,DRSL) + if(LNotEqual(DRSL,0xFFFFFF00)) + {Return(15)} + + + //System Memory Byte data + Store(4,SHFC) + ShiftLeft(SMBY,SHFC,BRSL) + if(LNotEqual(BRSL,0xFF0)) + {Return(16)} + + //Word Data + Store(4,SHFC) + ShiftLeft(SMWD,SHFC,WRSL) + if(LNotEqual(WRSL,0xffff0)) + {Return(17)} + + //DWord Data + Store(8,SHFC) + ShiftLeft(SMDW,SHFC,DRSL) + if(LNotEqual(DRSL,0xFFFFFF00)) + {Return(18)} + + Return(0) + + }//SLFT + + Method(SRGT,2) + {//SRGT + //And with Byte Data + Store (0xff,BYT1) + Store (0x00,BRSL) + + //And with Word Data + Store (0xffff,WRD1) + Store (0x0000,WRSL) + + //And with DWord Data + Store(0xffffffff,DWD1) + Store (0x00000000,DRSL) + + //Reinitialize the result objects + Store(0x00,ARSL) + Store(0x00,LRSL) + + Store(0xffffffff,SMDW) + Store(0xffff,SMWD) + Store(0xff,SMBY) + + //Arg0-> 2 & Arg1->2 + ShiftRight(Arg0,Arg1,ARSL) + if(LNotEqual(ARSL,0)) + {Return(21)} + + Store(Arg0,local0) + Store(Arg1,Local1) + + //Local0->8 and Local1->2 + ShiftRight(Local0,Local1,LRSL) + if(LNotEqual(LRSL,0)) + {Return(22)} + + Store(2,SHFC) + //Byte data + ShiftRight(BYT1,SHFC,BRSL) + if(LNotEqual(BRSL,0x3F)) + {Return(23)} + + Store(4,SHFC) + //Word Data + ShiftRight(WRD1,SHFC,WRSL) + if(LNotEqual(WRSL,0xFFF)) + {Return(24)} + + Store(8,SHFC) + //DWord Data + ShiftRight(DWD1,SHFC,DRSL) + if(LNotEqual(DRSL,0xFFFFFF)) + {Return(25)} + + //System Memory Byte data + Store(4,SHFC) + ShiftRight(SMBY,SHFC,BRSL) + if(LNotEqual(BRSL,0xF)) + {Return(26)} + + //Word Data + Store(4,SHFC) + ShiftRight(SMWD,SHFC,WRSL) + if(LNotEqual(WRSL,0xFFF)) + {Return(27)} + + //DWord Data + Store(8,SHFC) + ShiftRight(SMDW,SHFC,DRSL) + if(LNotEqual(DRSL,0xFFFFFF)) + {Return(28)} + + Return(0) + }//SRGT + + //Test method called from amlexec + Method(TEST) + { + Store ("++++++++ ShftOp Test", Debug) + + Store(SLFT(2,2),RSLT) + if(LNotEqual(RSLT,0)) + {Return(RSLT)} + Store(SRGT(2,2),RSLT) + if(LNotEqual(RSLT,0)) + {Return(RSLT)} + Return(0) + } + + }//Device SHFT + +// +// test Xor.asl and slightly modified +// +//This code tests the XOR opcode term +//Syntax of XOR term +// XOr( +// Source1 //TermArg=>BufferTerm +// Source2 //TermArg=>Integer +// Result //NameString +// ) +//"Source1" and "Source2" are evaluated as integers, a bit-wise XOR is performed, and the result is optionally stored in +// Result + Device (XORD) + { + //This Method tests XOr operator for all the data types i.e. BYTE, WORD and DWORD + Method (TEST) + { + Store ("++++++++ Xor Test", Debug) + + //Overlay in system memory + OperationRegion (RAM, SystemMemory, 0x800000, 256) + Field (RAM, ByteAcc, NoLock, Preserve) + { + RES1, 1, //Offset + BYT1, 8, //First BYTE + BYT2, 8, //Second BYTE + RBYT, 8, //Result Byte + RES2, 1, //Offset + WRD1, 16, //First WORD field + WRD2, 16, //Second WORD field + RWRD, 16, //RSLT WORD field + RES3, 1, //Offset + DWD1, 32, //First Dword + DWD2, 32, //Second Dword + RDWD, 32, //Result Dword + RES4, 1, //Offset + } + + // Store bits in the single bit fields for checking + // at the end + Store(1, RES1) + Store(1, RES2) + Store(1, RES3) + Store(1, RES4) + + // Check the stored single bits + if(LNotEqual(RES1, 1)) + { + Return(1) + } + + if(LNotEqual(RES2, 1)) + { + Return(1) + } + + if(LNotEqual(RES3, 1)) + { + Return(1) + } + + if(LNotEqual(RES4, 1)) + { + Return(1) + } + + //************************************************ + // (BYT1) Bit1 ->0 and (BYT2)Bit2 -> 0 condition + Store(0x00,BYT1) + Store(0x00,BYT2) + XOr(BYT1,BYT2,Local0) + Store (Local0, RBYT) + if(LNotEqual(RBYT,0)) + { Return(1)} + + // (BYT1) Bit1 ->1 and (BYT2)Bit2 -> 1 condition + Store(0xff,BYT1) + Store(0xff,BYT2) + XOr(BYT1,BYT2,Local0) + Store (Local0, RBYT) + if(LNotEqual(RBYT,0)) + { Return(1)} + + // (BYT1) Bit1 ->1 and (BYT)Bit2 -> 0 condition + Store(0x55,BYT1) + Store(0xAA,BYT2) + XOr(BYT1,BYT2,Local0) + Store (Local0, RBYT) + if(LNotEqual(RBYT,0xFF)) + { Return(1)} + + //(BYT1) Bit1 ->0 and (BYT2)Bit2 -> 1 condition + Store(0xAA,BYT1) + Store(0x55,BYT2) + XOr(BYT1,BYT2,Local0) + Store (Local0, RBYT) + if(LNotEqual(RBYT,0xFF)) + { Return(1)} + + Store(0x12,BYT1) + Store(0xED,BYT2) + + XOr(BYT1,BYT2,Local0) + Store (Local0, RBYT) + if(LNotEqual(RBYT,0xFF)) + { + Return(1) + } + + // Store known values for checking later + Store(0x12, BYT1) + if(LNotEqual(BYT1, 0x12)) + { + Return(1) + } + + Store(0xFE, BYT2) + if(LNotEqual(BYT2, 0xFE)) + { + Return(1) + } + + Store(0xAB, RBYT) + if(LNotEqual(RBYT, 0xAB)) + { + Return(1) + } + + //*********************************************** + // (WRD1) Bit1 ->0 and (WRD2)Bit2 -> 0 condition + Store(0x0000,WRD1) + Store(0x0000,WRD2) + XOr(WRD1,WRD2,RWRD) + if(LNotEqual(RWRD,0)) + { Return(1)} + + // (WRD1) Bit1 ->1 and (WRD2)Bit2 -> 1 condition + Store(0xffff,WRD1) + Store(0xffff,WRD2) + XOr(WRD1,WRD2,RWRD) + if(LNotEqual(RWRD,0)) + { Return(1)} + + // (WRD1) Bit1 ->1 and (WRD2)Bit2 -> 0 condition + Store(0x5555,WRD1) + Store(0xAAAA,WRD2) + XOr(WRD1,WRD2,RWRD) + if(LNotEqual(RWRD,0xFFFF)) + { Return(1)} + + //(WRD1) Bit1 ->0 and (WRD2)Bit2 -> 1 condition + Store(0xAAAA,WRD1) + Store(0x5555,WRD2) + XOr(WRD1,WRD2,RWRD) + if(LNotEqual(RWRD,0xFFFF)) + { Return(1)} + + Store(0x1234,WRD1) + Store(0xEDCB,WRD2) + XOr(WRD1,WRD2,RWRD) + if(LNotEqual(RWRD,0xFFFF)) + { Return(1)} + + // Store known values for checking later + Store(0x1234, WRD1) + if(LNotEqual(WRD1, 0x1234)) + { + Return(1) + } + + Store(0xFEDC, WRD2) + if(LNotEqual(WRD2, 0xFEDC)) + { + Return(1) + } + + Store(0x87AB, RWRD) + if(LNotEqual(RWRD, 0x87AB)) + { + Return(1) + } + + + //************************************************** + // (DWD1) Bit1 ->0 and (DWD2)Bit2 -> 0 condition + Store(0x00000000,DWD1) + Store(0x00000000,DWD2) + XOr(DWD1,DWD2,RDWD) + if(LNotEqual(RDWD,0)) + { Return(1)} + + // (DWD1) Bit1 ->1 and (DWD2)Bit2 -> 1 condition + Store(0xffffffff,DWD1) + Store(0xffffffff,DWD2) + XOr(DWD1,DWD2,RDWD) + if(LNotEqual(RDWD,0)) + { Return(1)} + + // (DWD1) Bit1 ->1 and (DWD2)Bit2 -> 0 condition + Store(0x55555555,DWD1) + Store(0xAAAAAAAA,DWD2) + XOr(DWD1,DWD2,RDWD) + if(LNotEqual(RDWD,0xFFFFFFFF)) + { Return(1)} + + //(DWD1) Bit1 ->0 and (DWD2)Bit2 -> 1 condition + Store(0xAAAAAAAA,DWD1) + Store(0x55555555,DWD2) + XOr(DWD1,DWD2,RDWD) + if(LNotEqual(RDWD,0xFFFFFFFF)) + { Return(1)} + + // (DWD1) Bit1 ->1 and (DWD2)Bit2 -> 0 condition + Store(0x12345678,DWD1) + Store(0xEDCBA987,DWD2) + XOr(DWD1,DWD2,RDWD) + if(LNotEqual(RDWD,0xFFFFFFFF)) + { Return(1)} + + Store(0x12345678,DWD1) + if(LNotEqual(DWD1,0x12345678)) + { + Return(1) + } + + Store(0xFEDCBA98,DWD2) + if(LNotEqual(DWD2,0xFEDCBA98)) + { + Return(1) + } + + Store(0x91827364,RDWD) + if(LNotEqual(RDWD,0x91827364)) + { + Return(1) + } + + //**************************************************** + // Check the stored single bits + if(LNotEqual(RES1, 1)) + { + Return(1) + } + + if(LNotEqual(RES2, 1)) + { + Return(1) + } + + if(LNotEqual(RES3, 1)) + { + Return(1) + } + + if(LNotEqual(RES4, 1)) + { + Return(1) + } + + // Change all of the single bit fields to zero + Store(0, RES1) + Store(0, RES2) + Store(0, RES3) + Store(0, RES4) + + // Now, check all of the fields + + // Byte + if(LNotEqual(BYT1, 0x12)) + { + Return(1) + } + + if(LNotEqual(BYT2, 0xFE)) + { + Return(1) + } + + if(LNotEqual(RBYT, 0xAB)) + { + Return(1) + } + + // Word + if(LNotEqual(WRD1, 0x1234)) + { + Return(1) + } + + if(LNotEqual(WRD2, 0xFEDC)) + { + Return(1) + } + + if(LNotEqual(RWRD, 0x87AB)) + { + Return(1) + } + + // Dword + if(LNotEqual(DWD1, 0x12345678)) + { + Return(1) + } + + if(LNotEqual(DWD2, 0xFEDCBA98)) + { + Return(1) + } + + if(LNotEqual(RDWD, 0x91827364)) + { + Return(1) + } + + // Bits + if(LNotEqual(RES1, 0)) + { + Return(1) + } + + if(LNotEqual(RES2, 0)) + { + Return(1) + } + + if(LNotEqual(RES3, 0)) + { + Return(1) + } + + if(LNotEqual(RES4, 0)) + { + Return(1) + } + + + Return(0) + } // TEST + } // XORD + +// +// test CrBytFld.asl +// +// CrBytFld test +// Test for CreateByteField. +// Tests creating byte field overlay of buffer stored in Local0. +// Tests need to be added for Arg0 and Name buffers. +// + Device (CRBF) + { // Test device name + Method (TEST) + { + Store ("++++++++ CrBytFld Test", Debug) + + // Local0 is unitialized buffer with 4 elements + Store (Buffer (4) {}, Local0) + + // create Byte Field named BF0 based on Local0 element 0 + CreateByteField (Local0, 0, BF0) + + // validate CreateByteField did not alter Local0 + Store (ObjectType (Local0), Local1) // Local1 = Local0 object type + If (LNotEqual (Local1, 3)) // Buffer object type value is 3 + { Return (2) } + + // store something into BF0 + Store (1, BF0) + + // validate Store did not alter Local0 object type + Store (ObjectType (Local0), Local1) // Local1 = Local0 object type + If (LNotEqual (Local1, 3)) // Buffer object type value is 3 + { Return (3) } + + // verify that the Store into BF0 was successful + If (LNotEqual (BF0, 1)) + { Return (4) } + + + // create Byte Field named BF1 based on Local0 element 1 + CreateByteField (Local0, 1, BF1) + + // validate CreateByteField did not alter Local0 + Store (ObjectType (Local0), Local1) // Local1 = Local0 object type + If (LNotEqual (Local1, 3)) // Buffer object type value is 3 + { Return (10) } + + // store something into BF1 + Store (5, BF1) + + // validate Store did not alter Local0 object type + Store (ObjectType (Local0), Local1) // Local1 = Local0 object type + If (LNotEqual (Local1, 3)) // Buffer object type value is 3 + { Return (11) } + + // verify that the Store into BF1 was successful + If (LNotEqual (BF1, 5)) + { Return (12) } + + // verify that the Store into BF1 did not alter BF0 + If (LNotEqual (BF0, 1)) + { Return (13) } + + + // store something into BF0 + Store (0xFFFF, BF0) + + // verify that the Store into BF0 was successful + If (LNotEqual (BF0, 0xFF)) + { Return (20) } + + // verify that the Store into BF0 did not alter BF1 + If (LNotEqual (BF1, 5)) + { Return (21) } + + + Return (0) + } // TEST + } // CRBF + +// +// test IndexOp4.asl +// +// IndexOp4 test +// This is just a subset of the many RegionOp/Index Field test cases. +// Tests access of index fields smaller than 8 bits. +// + Device (IDX4) + { // Test device name + + // MADM: Misaligned Dynamic RAM SystemMemory OperationRegion + // Tests OperationRegion memory access using misaligned BYTE, + // WORD, and DWORD field element accesses. Validation is performed + // using both misaligned field entries and aligned field entries. + // + // MADM returns 0 if all test cases pass or non-zero identifying + // the failing test case for debug purposes. This non-zero numbers + // are not guaranteed to be in perfect sequence (i.e., test case + // index), but are guaranteed to be unique so the failing test + // case can be uniquely identified. + // + Method (MADM, 1) // Misaligned Dynamic RAM SystemMemory OperationRegion + // Arg0 -- SystemMemory OperationRegion base address + { // MADM: Misaligned Dynamic RAM SystemMemory OperationRegion + OperationRegion (RAM, SystemMemory, Arg0, 0x100) + Field (RAM, DwordAcc, NoLock, Preserve) + { // aligned field definition (for verification) + DWD0, 32, // aligned DWORD field + DWD1, 32 // aligned DWORD field + } + Field (RAM, ByteAcc, NoLock, Preserve) + { // bit access field definition + BIT0, 1, // single bit field entry + BIT1, 1, // single bit field entry + BIT2, 1, // single bit field entry + BIT3, 1, // single bit field entry + BIT4, 1, // single bit field entry + BIT5, 1, // single bit field entry + BIT6, 1, // single bit field entry + BIT7, 1, // single bit field entry + BIT8, 1, // single bit field entry + BIT9, 1, // single bit field entry + BITA, 1, // single bit field entry + BITB, 1, // single bit field entry + BITC, 1, // single bit field entry + BITD, 1, // single bit field entry + BITE, 1, // single bit field entry + BITF, 1, // single bit field entry + BI10, 1, // single bit field entry + BI11, 1, // single bit field entry + BI12, 1, // single bit field entry + BI13, 1, // single bit field entry + BI14, 1, // single bit field entry + BI15, 1, // single bit field entry + BI16, 1, // single bit field entry + BI17, 1, // single bit field entry + BI18, 1, // single bit field entry + BI19, 1, // single bit field entry + BI1A, 1, // single bit field entry + BI1B, 1, // single bit field entry + BI1C, 1, // single bit field entry + BI1D, 1, // single bit field entry + BI1E, 1, // single bit field entry + BI1F, 1 // single bit field entry + } // bit access field definition + + Field (RAM, ByteAcc, NoLock, Preserve) + { // two-bit access field definition + B2_0, 2, // single bit field entry + B2_1, 2, // single bit field entry + B2_2, 2, // single bit field entry + B2_3, 2, // single bit field entry + B2_4, 2, // single bit field entry + B2_5, 2, // single bit field entry + B2_6, 2, // single bit field entry + B2_7, 2, // single bit field entry + B2_8, 2, // single bit field entry + B2_9, 2, // single bit field entry + B2_A, 2, // single bit field entry + B2_B, 2, // single bit field entry + B2_C, 2, // single bit field entry + B2_D, 2, // single bit field entry + B2_E, 2, // single bit field entry + B2_F, 2 // single bit field entry + } // bit access field definition + + // initialize memory contents using aligned field entries + Store (0x5AA55AA5, DWD0) + Store (0x5AA55AA5, DWD1) + + // set memory contents to known values using misaligned field entries + Store (0, BIT0) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT0, 0)) + { Return (1) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55AA4)) + { Return (2) } + + // set memory contents to known values using misaligned field entries + Store (1, BIT1) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT1, 1)) + { Return (3) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55AA6)) + { Return (4) } + + // set memory contents to known values using misaligned field entries + Store (0, BIT2) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT2, 0)) + { Return (5) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55AA2)) + { Return (6) } + + // set memory contents to known values using misaligned field entries + Store (1, BIT3) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT3, 1)) + { Return (7) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55AAA)) + { Return (8) } + + // set memory contents to known values using misaligned field entries + Store (1, BIT4) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT4, 1)) + { Return (9) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55ABA)) + { Return (10) } + + // set memory contents to known values using misaligned field entries + Store (0, BIT5) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT5, 0)) + { Return (11) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55A9A)) + { Return (12) } + + // set memory contents to known values using misaligned field entries + Store (1, BIT6) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT6, 1)) + { Return (13) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55ADA)) + { Return (14) } + + // set memory contents to known values using misaligned field entries + Store (0, BIT7) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT7, 0)) + { Return (15) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55A5A)) + { Return (16) } + + // set memory contents to known values using misaligned field entries + Store (1, BIT8) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT8, 1)) + { Return (17) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55B5A)) + { Return (18) } + + // set memory contents to known values using misaligned field entries + Store (0, BIT9) + // verify memory contents using misaligned field entries + If (LNotEqual (BIT9, 0)) + { Return (19) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA5595A)) + { Return (20) } + + // set memory contents to known values using misaligned field entries + Store (1, BITA) + // verify memory contents using misaligned field entries + If (LNotEqual (BITA, 1)) + { Return (21) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA55D5A)) + { Return (22) } + + // set memory contents to known values using misaligned field entries + Store (0, BITB) + // verify memory contents using misaligned field entries + If (LNotEqual (BITB, 0)) + { Return (23) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA5555A)) + { Return (24) } + + // set memory contents to known values using misaligned field entries + Store (0, BITC) + // verify memory contents using misaligned field entries + If (LNotEqual (BITC, 0)) + { Return (25) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA5455A)) + { Return (26) } + + // set memory contents to known values using misaligned field entries + Store (1, BITD) + // verify memory contents using misaligned field entries + If (LNotEqual (BITD, 1)) + { Return (27) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA5655A)) + { Return (28) } + + // set memory contents to known values using misaligned field entries + Store (0, BITE) + // verify memory contents using misaligned field entries + If (LNotEqual (BITE, 0)) + { Return (29) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA5255A)) + { Return (30) } + + // set memory contents to known values using misaligned field entries + Store (1, BITF) + // verify memory contents using misaligned field entries + If (LNotEqual (BITF, 1)) + { Return (31) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA5A55A)) + { Return (32) } + + // set memory contents to known values using misaligned field entries + Store (0, BI10) + // verify memory contents using misaligned field entries + If (LNotEqual (BI10, 0)) + { Return (33) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA4A55A)) + { Return (34) } + + // set memory contents to known values using misaligned field entries + Store (1, BI11) + // verify memory contents using misaligned field entries + If (LNotEqual (BI11, 1)) + { Return (35) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA6A55A)) + { Return (36) } + + // set memory contents to known values using misaligned field entries + Store (0, BI12) + // verify memory contents using misaligned field entries + If (LNotEqual (BI12, 0)) + { Return (37) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AA2A55A)) + { Return (38) } + + // set memory contents to known values using misaligned field entries + Store (1, BI13) + // verify memory contents using misaligned field entries + If (LNotEqual (BI13, 1)) + { Return (39) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5AAAA55A)) + { Return (40) } + + // set memory contents to known values using misaligned field entries + Store (1, BI14) + // verify memory contents using misaligned field entries + If (LNotEqual (BI14, 1)) + { Return (41) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5ABAA55A)) + { Return (42) } + + // set memory contents to known values using misaligned field entries + Store (0, BI15) + // verify memory contents using misaligned field entries + If (LNotEqual (BI15, 0)) + { Return (43) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5A9AA55A)) + { Return (44) } + + // set memory contents to known values using misaligned field entries + Store (1, BI16) + // verify memory contents using misaligned field entries + If (LNotEqual (BI16, 1)) + { Return (45) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5ADAA55A)) + { Return (46) } + + // set memory contents to known values using misaligned field entries + Store (0, BI17) + // verify memory contents using misaligned field entries + If (LNotEqual (BI17, 0)) + { Return (47) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5A5AA55A)) + { Return (48) } + + // set memory contents to known values using misaligned field entries + Store (1, BI18) + // verify memory contents using misaligned field entries + If (LNotEqual (BI18, 1)) + { Return (49) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5B5AA55A)) + { Return (50) } + + // set memory contents to known values using misaligned field entries + Store (0, BI19) + // verify memory contents using misaligned field entries + If (LNotEqual (BI19, 0)) + { Return (51) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x595AA55A)) + { Return (52) } + + // set memory contents to known values using misaligned field entries + Store (1, BI1A) + // verify memory contents using misaligned field entries + If (LNotEqual (BI1A, 1)) + { Return (53) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x5D5AA55A)) + { Return (54) } + + // set memory contents to known values using misaligned field entries + Store (0, BI1B) + // verify memory contents using misaligned field entries + If (LNotEqual (BI1B, 0)) + { Return (55) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x555AA55A)) + { Return (56) } + + // set memory contents to known values using misaligned field entries + Store (0, BI1C) + // verify memory contents using misaligned field entries + If (LNotEqual (BI1C, 0)) + { Return (57) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x455AA55A)) + { Return (58) } + + // set memory contents to known values using misaligned field entries + Store (1, BI1D) + // verify memory contents using misaligned field entries + If (LNotEqual (BI1D, 1)) + { Return (59) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x655AA55A)) + { Return (60) } + + // set memory contents to known values using misaligned field entries + Store (0, BI1E) + // verify memory contents using misaligned field entries + If (LNotEqual (BI1E, 0)) + { Return (61) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x255AA55A)) + { Return (62) } + + // set memory contents to known values using misaligned field entries + Store (1, BI1F) + // verify memory contents using misaligned field entries + If (LNotEqual (BI1F, 1)) + { Return (63) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55AA55A)) + { Return (64) } + + + // set memory contents to known values using misaligned field entries + Store (3, B2_0) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_0, 3)) + { Return (65) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55AA55B)) + { Return (66) } + + // set memory contents to known values using misaligned field entries + Store (1, B2_1) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_1, 1)) + { Return (67) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55AA557)) + { Return (68) } + + // set memory contents to known values using misaligned field entries + Store (0, B2_2) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_2, 0)) + { Return (69) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55AA547)) + { Return (70) } + + // set memory contents to known values using misaligned field entries + Store (3, B2_3) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_3, 3)) + { Return (71) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55AA5C7)) + { Return (72) } + + // set memory contents to known values using misaligned field entries + Store (3, B2_4) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_4, 3)) + { Return (73) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55AA7C7)) + { Return (74) } + + // set memory contents to known values using misaligned field entries + Store (0, B2_5) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_5, 0)) + { Return (75) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55AA3C7)) + { Return (76) } + + // set memory contents to known values using misaligned field entries + Store (1, B2_6) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_6, 1)) + { Return (77) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55A93C7)) + { Return (78) } + + // set memory contents to known values using misaligned field entries + Store (1, B2_7) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_7, 1)) + { Return (79) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55A53C7)) + { Return (80) } + + // set memory contents to known values using misaligned field entries + Store (0, B2_8) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_8, 0)) + { Return (81) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55853C7)) + { Return (82) } + + // set memory contents to known values using misaligned field entries + Store (1, B2_9) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_9, 1)) + { Return (83) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA55453C7)) + { Return (84) } + + // set memory contents to known values using misaligned field entries + Store (2, B2_A) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_A, 2)) + { Return (85) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA56453C7)) + { Return (86) } + + // set memory contents to known values using misaligned field entries + Store (2, B2_B) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_B, 2)) + { Return (87) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA5A453C7)) + { Return (88) } + + // set memory contents to known values using misaligned field entries + Store (3, B2_C) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_C, 3)) + { Return (89) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xA7A453C7)) + { Return (90) } + + // set memory contents to known values using misaligned field entries + Store (3, B2_D) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_D, 3)) + { Return (91) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0xAFA453C7)) + { Return (92) } + + // set memory contents to known values using misaligned field entries + Store (1, B2_E) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_E, 1)) + { Return (93) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x9FA453C7)) + { Return (94) } + + // set memory contents to known values using misaligned field entries + Store (0, B2_F) + // verify memory contents using misaligned field entries + If (LNotEqual (B2_F, 0)) + { Return (95) } + // verify memory contents using aligned field entries + If (LNotEqual (DWD0, 0x1FA453C7)) + { Return (96) } + + + Return (0) // pass + } // MADM: Misaligned Dynamic RAM SystemMemory OperationRegion + + Method (TEST) + { + Store ("++++++++ IndexOp4 Test", Debug) + + // MADM (Misaligned Dynamic RAM SystemMemory OperationRegion) arguments: + // Arg0 -- SystemMemory OperationRegion base address + Store (MADM (0x800000), Local0) + If (LNotEqual (Local0, 0)) // MADM returns zero if successful + { Return (Local0) } // failure: return MADM error code + + Return (Local0) + } // TEST + } // IDX4 + +// +// test Event.asl +// +// EventOp, ResetOp, SignalOp, and WaitOp test cases. +// + Device (EVNT) + { + Event (EVNT) // event synchronization object + + Method (TEVN, 1) + // Arg0: time to Wait for event in milliseconds + { // TEVN control method to test ResetOp, SignalOp, and WaitOp + // reset EVNT to initialization (zero) state + Reset (EVNT) + + // prime EVNT with two outstanding signals + Signal (EVNT) + Signal (EVNT) + + + // acquire existing signal + Store (Wait (EVNT, Arg0), Local0) + + // validate Local0 is a Number + Store (ObjectType (Local0), Local1) + If (LNotEqual (Local1, 1)) // Number is type 1 + { Return (0x21) } // Local1 indicates Local0 is not a Number + + If (LNotEqual (Local0, 0)) // Number is type 1 + { Return (0x22) } // timeout occurred without acquiring signal + + Store ("Acquire 1st existing signal PASS", Debug) + + + // acquire existing signal + Store (Wait (EVNT, Arg0), Local0) + + // validate Local0 is a Number + Store (ObjectType (Local0), Local1) + If (LNotEqual (Local1, 1)) // Number is type 1 + { Return (0x31) } // Local1 indicates Local0 is not a Number + + If (LNotEqual (Local0, 0)) // Number is type 1 + { Return (0x32) } // timeout occurred without acquiring signal + + Store ("Acquire 2nd existing signal PASS", Debug) + + + // ensure WaitOp timeout test cases do not hang + if (LEqual (Arg0, 0xFFFF)) + { Store (0xFFFE, Arg0) } + + // acquire non-existing signal + Store (Wait (EVNT, Arg0), Local0) + + // validate Local0 is a Number + Store (ObjectType (Local0), Local1) + If (LNotEqual (Local1, 1)) // Number is type 1 + { Return (0x41) } // Local1 indicates Local0 is not a Number + + If (LEqual (Local0, 0)) // Number is type 1 + { Return (0x42) } // non-existant signal was acquired + + Store ("Acquire signal timeout PASS", Debug) + + + // prime EVNT with two outstanding signals + Signal (EVNT) + Signal (EVNT) + + // reset EVNT to initialization (zero) state + Reset (EVNT) + + // acquire non-existing signal + Store (Wait (EVNT, Arg0), Local0) + + // validate Local0 is a Number + Store (ObjectType (Local0), Local1) + If (LNotEqual (Local1, 1)) // Number is type 1 + { Return (0x51) } // Local1 indicates Local0 is not a Number + + If (LEqual (Local0, 0)) // Number is type 1 + { Return (0x52) } // non-existant signal was acquired + + Store ("Reset signal PASS", Debug) + + + // acquire non-existing signal using Lvalue timeout + Store (Wait (EVNT, Zero), Local0) + + // validate Local0 is a Number + Store (ObjectType (Local0), Local1) + If (LNotEqual (Local1, 1)) // Number is type 1 + { Return (0x61) } // Local1 indicates Local0 is not a Number + + If (LEqual (Local0, 0)) // Number is type 1 + { Return (0x62) } // non-existant signal was acquired + + Store ("Zero Lvalue PASS", Debug) + + + // acquire non-existing signal using Lvalue timeout + Store (Wait (EVNT, One), Local0) + + // validate Local0 is a Number + Store (ObjectType (Local0), Local1) + If (LNotEqual (Local1, 1)) // Number is type 1 + { Return (0x71) } // Local1 indicates Local0 is not a Number + + If (LEqual (Local0, 0)) // Number is type 1 + { Return (0x72) } // non-existant signal was acquired + + Store ("One Lvalue PASS", Debug) + + // Lvalue Event test cases + // ILLEGAL SOURCE OPERAND Store (EVNT, Local2) + + // validate Local2 is an Event + Store (ObjectType (EVNT), Local1) + If (LNotEqual (Local1, 7)) // Event is type 7 + { Return (0x81) } // Local1 indicates Local0 is not a Number + + // reset EVNT to initialization (zero) state + Reset (EVNT) + + // prime EVNT with two outstanding signals + Signal (EVNT) + + // acquire existing signal + Store (Wait (EVNT, Arg0), Local0) + + // validate Local0 is a Number + Store (ObjectType (Local0), Local1) + If (LNotEqual (Local1, 1)) // Number is type 1 + { Return (0x82) } // Local1 indicates Local0 is not a Number + + If (LNotEqual (Local0, 0)) // Number is type 1 + { Return (0x83) } // timeout occurred without acquiring signal + + Store ("Acquire Lvalue existing signal PASS", Debug) + + + // acquire non-existing signal + Store (Wait (EVNT, Arg0), Local0) + + // validate Local0 is a Number + Store (ObjectType (Local0), Local1) + If (LNotEqual (Local1, 1)) // Number is type 1 + { Return (0x84) } // Local1 indicates Local0 is not a Number + + If (LEqual (Local0, 0)) // Number is type 1 + { Return (0x85) } // non-existant signal was acquired + + Store ("Acquire Lvalue signal timeout PASS", Debug) + + + Return (0) // success + } // TEVN control method to test ResetOp, SignalOp, and WaitOp + + Method (TEST) + { + Store ("++++++++ Event Test", Debug) + + Store (TEVN (100), Local0) + + Return (Local0) + } // TEST + } // EVNT + +// +// test SizeOfLv.asl +// +// Test for SizeOf (Lvalue) +// +// This next section will contain the packages that the SizeOfOp will be +// exercised on. The first one, PKG0, is a regular package of 3 elements. +// The 2nd one, PKG1, is a nested package with 3 packages inside it, each +// with 3 elements. It is expected that SizeOf operator will return the +// same value for these two packages since they both have 3 elements. The +// final package, PKG2, has 4 elements and the SizeOf operator is expected +// to return different results for this package. + + Name (PKG0, + Package (3) + {0x0123, 0x4567, 0x89AB} + ) // PKG0 + + Name (PKG1, + Package (3) + { + Package (3) {0x0123, 0x4567, 0x89AB}, + Package (3) {0xCDEF, 0xFEDC, 0xBA98}, + Package (3) {0x7654, 0x3210, 0x1234} + } + ) // PKG1 + + Name (PKG2, + Package (4) + {0x0123, 0x4567, 0x89AB, 0x8888} + ) // PKG2 + + Name (PKG3, + Package (5) + {0x0123, 0x4567, 0x89AB, 0x8888, 0x7777} + ) // PKG3 + +// End Packages ********************************************************** + +// The following section will declare the data strings that will be used to +// exercise the SizeOf operator. STR0 and STR1 are expected to be equal, +// STR2 is expected to have a different SizeOf value than STR0 and STR1. + + Name (STR0, "ACPI permits very flexible methods of expressing a system") + + Name (STR1, "MIKE permits very flexible methods of expressing a system") + + Name (STR2, "Needless to say, Mike and ACPI are frequently at odds") + +// This string is being made in case we want to do a SizeOf comparison +// between strings and packages or buffers + Name (STR3, "12345") + +// End Strings ********************************************************** + +// The following section will declare the buffers that will be used to exercise +// the SizeOf operator. + + Name (BUF0, Buffer (10) {}) + Name (BUF1, Buffer (10) {}) + Name (BUF2, Buffer (8) {}) + Name (BUF3, Buffer (5) {}) + +// End Buffers ********************************************************** + Device (SZLV) + { + + Method (CMPR, 2) + { + // CMPR is passed two arguments. If unequal, return 1 to indicate + // that, otherwise return 0 to indicate SizeOf each is equal. + + Store (0x01, Local0) + + if (LEqual (SizeOf(Arg0), SizeOf(Arg1))) + { + Store (0x00, Local0) + } + + return (Local0) + } // CMPR + + + Method (TEST) + { + + Store ("++++++++ SizeOfLv Test", Debug) + + // TBD: SizeOf ("string") + // SizeOf (Buffer) + // SizeOf (Package) + // SizeOf (String) + // SizeOf (STR0) -- where Name (STR0,...) -- lot's of cases + // buffer, string, package, + // SizeOf (METH) -- where METH control method returns + // buffer, string, package, + + // TBD: SLOC [SizeOf (Local0)] -- dup SARG + + // Compare the elements that we expect to be the same. Exit out with an error + // code on the first failure. + if (LNotEqual (0x00, CMPR (STR0, STR1))) + { + Return (0x01) + } + + if (LNotEqual (0x00, CMPR (STR3, BUF3))) + { + Return (0x02) + } + + if (LNotEqual (0x00, CMPR (STR3, PKG3))) + { + Return (0x03) + } + + // In the following section, this test will cover the SizeOf + // operator for Local values. + // In this case, both Local0 and Local1 should have the same Size + Store (STR0, Local0) + Store (STR1, Local1) + + if (LNotEqual (SizeOf (Local0), SizeOf (Local1))) + { + Return (0x04) + } + + // Now create a case where Local0 and Local1 are different + Store (STR2, Local1) + + if (LEqual (SizeOf (Local0), SizeOf (Local1))) + { + Return (0x05) + } + + // Finally, check for the return of SizeOf for a known Buffer. Just + // in case we magically pass above cases due to all Buffers being Zero + // bytes in size, or Infinity, etc. + if (LNotEqual (0x05, SizeOf (BUF3))) + { + Return (0x06) + } + + Return (0) + } // TEST + } // SZLV + + +// +// test BytField.asl +// +// BytField test +// This is just a subset of the many RegionOp/Index Field test cases. +// Tests access of TBD. +// + Scope (\_SB) // System Bus + { // _SB system bus + Device (BYTF) + { // Test device name + Method (TEST) + { + Store ("++++++++ BytField Test", Debug) + + Return (\_TZ.C19B.RSLT) + } // TEST + } // BYTF + + Device (C005) + { // Device C005 + Device (C013) + { // Device C013 + } // Device C013 + } // Device C005 + + Method (C115) + { // C115 control method + Acquire (\_GL, 0xFFFF) + Store (\_SB.C005.C013.C058.C07E, Local0) + Release (\_GL) + And (Local0, 16, Local0) + Store (ShiftRight (Local0, 4, ), Local1) + If (LEqual (Local1, 0)) + { Return (1) } + Else + { Return (0) } + } // C115 control method + } // _SB system bus + + OperationRegion (C018, SystemIO, 0x5028, 4) + Field (C018, AnyAcc, NoLock, Preserve) + { // Field overlaying C018 + C019, 32 + } // Field overlaying C018 + + OperationRegion (C01A, SystemIO, 0x5030, 4) + Field (C01A, ByteAcc, NoLock, Preserve) + { // Field overlaying C01A + C01B, 8, + C01C, 8, + C01D, 8, + C01E, 8 + } // Field overlaying C01A + + Mutex (\C01F, 0) + Name (\C020, 0) + Name (\C021, 0) + + Method (\C022, 0) + { // \C022 control method + Acquire (\C01F, 0xFFFF) + If (LEqual (\C021, 0)) + { + Store (C019, Local0) + And (Local0, 0xFFFEFFFE, Local0) + Store (Local0, C019) + Increment (\C021) + } + Release (\C01F) + } // \C022 control method + + Scope (\_SB.C005.C013) + { // Scope \_SB.C005.C013 + Device (C058) + { // Device C058 + Name (_HID, "*PNP0A06") + + OperationRegion (C059, SystemIO, 0xE0, 2) + Field (C059, ByteAcc, NoLock, Preserve) + { // Field overlaying C059 + C05A, 8, + C05B, 8 + } // Field overlaying C059 + + OperationRegion (C05C, SystemIO, 0xE2, 2) + Field (C05C, ByteAcc, NoLock, Preserve) + { // Field overlaying C05C + C05D, 8, + C05E, 8 + } // Field overlaying C05C + IndexField (C05D, C05E, ByteAcc, NoLock, Preserve) + { // IndexField overlaying C05D/C05E + , 0x410, // skip + C05F, 8, + C060, 8, + C061, 8, + C062, 8, + C063, 8, + C064, 8, + C065, 8, + C066, 8, + C067, 8, + C068, 8, + C069, 8, + C06A, 8, + C06B, 8, + C06C, 8, + C06D, 8, + C06E, 8, + , 0x70, // skip + C06F, 8, + C070, 8, + C071, 8, + C072, 8, + C073, 8, + C074, 8, + C075, 8, + C076, 8, + C077, 8, + C078, 8, + C079, 8, + C07A, 8, + C07B, 8, + C07C, 8, + C07D, 8, + C07E, 8 + } // IndexField overlaying C05D/C05E + + OperationRegion (C07F, SystemIO, 0xE4, 2) + Field (C07F, ByteAcc, NoLock, Preserve) + { // Field overlaying C07F + C080, 8, + C081, 8 + } // Field overlaying C07F + + OperationRegion (C082, SystemIO, 0xE0, 1) + Field (C082, ByteAcc, NoLock, Preserve) + { // Field overlaying C082 + C083, 8 + } // Field overlaying C082 + + OperationRegion (C084, SystemIO, 0xFF, 1) + Field (C084, ByteAcc, NoLock, Preserve) + { // Field overlaying C084 + C085, 8 + } // Field overlaying C084 + + OperationRegion (C086, SystemIO, 0xFD, 1) + Field (C086, ByteAcc, NoLock, Preserve) + { // Field overlaying C086 + C087, 8 + } // Field overlaying C086 + + Mutex (C088, 0) + Mutex (C089, 0) + Mutex (C08A, 0) + Mutex (C08B, 0) + Mutex (C08C, 0) + Mutex (C08D, 0) + + Name (C08E, 0xFFFFFFFD) + Name (C08F, 0) + + Method (C0AA, 4) + { // C0AA control method + Store (Buffer (4) {}, Local7) + CreateByteField (Local7, 0, C0AB) + CreateByteField (Local7, 1, C0AC) + CreateByteField (Local7, 2, C0AD) + CreateByteField (Local7, 3, C0AE) + Acquire (^C08B, 0xFFFF) + Acquire (\_GL, 0xFFFF) + \C022 () + Store (1, \_SB.C005.C013.C058.C06B) + While (LNot (LEqual (0, \_SB.C005.C013.C058.C06B))) + { Stall (100) } + Store (Arg3, \_SB.C005.C013.C058.C06E) + Store (Arg2, \_SB.C005.C013.C058.C06D) + Store (Arg1, \_SB.C005.C013.C058.C06C) + Store (Arg0, \_SB.C005.C013.C058.C06B) + While (LNot (LEqual (0, \_SB.C005.C013.C058.C06B))) + { Stall (100) } + Store (\_SB.C005.C013.C058.C06E, C0AB) + Store (\_SB.C005.C013.C058.C06D, C0AC) + Store (\_SB.C005.C013.C058.C06C, C0AD) + Store (\_SB.C005.C013.C058.C06B, C0AE) + If (LNot (LEqual (Arg0, 23))) + { + Store (2, \_SB.C005.C013.C058.C06B) + Stall (100) + } + Release (\_GL) + Release (^C08B) + Return (Local7) + } // C0AA control method + } // Device C058 + } // Scope \_SB.C005.C013 + + Scope (\_TZ) + { // \_TZ thermal zone scope + Name (C18B, Package (2) + { + Package (2) + { + Package (5) {0x05AC, 0x0CD2, 0x0D68, 0x0DE0, 0x0E4E}, + Package (5) {0x0D04, 0x0D9A, 0x0DFE, 0x0E80, 0x0FA2} + }, + Package (2) + { + Package (5) {0x05AC, 0x0CD2, 0x0D68, 0x0DE0, 0x0E4E}, + Package (5) {0x0D04, 0x0D9A, 0x0DFE, 0x0E80, 0x0FA2} + } + }) // C18B + + Name (C18C, Package (2) + { + Package (2) + { + Package (3) {0x64, 0x4B, 0x32}, + Package (3) {0x64, 0x4B, 0x32} + } + }) // C81C + + Name (C18D, 0) + Name (C18E, 0) + Name (C18F, 0) + Name (C190, 0) + Name (C191, 3) + Name (C192, 0) + Name (C193, 1) + Name (C194, 2) + Mutex (C195, 0) + Name (C196, 1) + Name (C197, 0x0B9C) + Name (C198, 0x0B9C) + Name (C199, 0xFFFFFFFD) + Name (C19A, 0) + + Device (C19B) + { // Device C19B + Name (RSLT, 0) // default to zero + + Method (XINI) + { // _INI control method (Uses Global Lock -- can't run under AcpiExec) + Store (\_SB.C115, C19A) + \_TZ.C19C._SCP (0) + Subtract (0x0EB2, 0x0AAC, Local1) // Local1 = AACh - EB2h + Divide (Local1, 10, Local0, Local2) // Local0 = Local1 / 10 + // Local2 = Local1 % 10 + \_SB.C005.C013.C058.C0AA (14, Local2, 0, 0) + Store + (DerefOf (Index (DerefOf (Index (\_TZ.C18C, C19A, )), 0, )), C18D) + Store + (DerefOf (Index (DerefOf (Index (\_TZ.C18C, C19A, )), 1, )), C18E) + Store + (DerefOf (Index (DerefOf (Index (\_TZ.C18C, C19A, )), 2, )), C18F) + + Store (1, RSLT) // set RSLT to 1 if _INI control method completes + } // _INI control method + + // PowerResource (C19D) {...} + } // Device C19B + + ThermalZone (C19C) + { + Method (_SCP, 1) + { // _SCP control method + Store (Arg0, Local0) + If (LEqual (Local0, 0)) + { + Store (0, \_TZ.C192) + Store (1, \_TZ.C193) + Store (2, \_TZ.C194) + Store (3, \_TZ.C191) + } + Else + { + Store (0, \_TZ.C191) + Store (1, \_TZ.C192) + Store (2, \_TZ.C193) + Store (3, \_TZ.C194) + } + } // _SCP control method + } // ThermalZone C19C + } // \_TZ thermal zone scope + + +// +// test DwrdFld.asl +// + Name (BUFR, buffer(10) {0,0,0,0,0,0,0,0,0,0} ) + + Device (DWDF) + { + Method (TEST) + { + Store ("++++++++ DwrdFld Test", Debug) + + CreateByteField (BUFR, 0, BYTE) + Store (0xAA, BYTE) + + CreateWordField (BUFR, 1, WORD) + Store (0xBBCC, WORD) + + CreateDWordField (BUFR, 3, DWRD) + Store (0xDDEEFF00, DWRD) + + CreateByteField (BUFR, 7, BYT2) + Store (0x11, BYT2) + + CreateWordField (BUFR, 8, WRD2) + Store (0x2233, WRD2) + + Return (0) + + } // End Method TEST + } // Device DWDF + + // + // test DivAddx.asl + // + Name (B1LO, 0xAA) + Name (B1HI, 0xBB) + + Method (MKW_, 2) + { // This control method will take two bytes and make them into a WORD + + Multiply (B1HI, 256, Local0) // Make high byte.....high + Or (Local0, B1LO, Local0) // OR in the low byte + Return (Local0) // Return the WORD + + } // MKW_ + + Device (DVAX) + { + Method (TEST) + { + + Store ("++++++++ DivAddx Test", Debug) + + Store (25, B1LO) + Store (0, B1HI) + + // We'll multiply 25 * 3 to get 75, add 99 to it then divide + // by 100. We expect to get 74 for the remainder and 1 for + // the quotient. + Divide( + Add (Multiply (3, MKW_ (B1LO, B1HI)), 0x63), + // Dividend, + 100, // Divisor + Local4, // Remainder + Local2) // Quotient + + If (LAnd (LEqual (74, Local4), LEqual (1, Local2))) + { // Indicate Pass + Store (0x00, Local0) + } + + Else + { // Indicate Fail + Store (0x01, Local0) + } + + Return (Local0) + } // End Method TEST + } // Device DVAX + +// +// test IndexFld.asl (IndexOp6.asl) +// +// IndexFld test +// This is just a subset of the many RegionOp/Index Field test cases. +// Tests index field element AccessAs macro. +// Also tests name resolution of index field elements with same names +// but different namespace scopes. +// + Device (IDX6) + { // Test device name + + OperationRegion (SIO, SystemIO, 0x100, 2) + Field (SIO, ByteAcc, NoLock, Preserve) + { + INDX, 8, + DATA, 8 + } + IndexField (INDX, DATA, AnyAcc, NoLock, WriteAsOnes) + { + AccessAs (ByteAcc, 0), + IFE0, 8, + IFE1, 8, + IFE2, 8, + IFE3, 8, + IFE4, 8, + IFE5, 8, + IFE6, 8, + IFE7, 8, + IFE8, 8, + IFE9, 8, + } + + Device (TST_) + { // TST_: provides a different namespace scope for IFE0 and IFE1 + OperationRegion (SIO2, SystemIO, 0x100, 2) + Field (SIO2, ByteAcc, NoLock, Preserve) + { + IND2, 8, + DAT2, 8 + } + IndexField (IND2, DAT2, AnyAcc, NoLock, WriteAsOnes) + { + IFE0, 8, // duplicate IndexField name with different scope + IFE1, 8 + } + } // TST_: provides a different namespace scope for IFE0 and IFE1 + + Method (TEST) + { + Store ("++++++++ IndexOp6 Test", Debug) + + Store (IFE0, Local0) + Store (IFE1, Local1) + Store (IFE2, Local2) + + // validate name resolution of IndexFields with different scopes + Store (\IDX6.IFE0, Local3) + Store (\IDX6.IFE1, Local4) + // verioading of namespace can resolve following names + Store (\IDX6.TST_.IFE0, Local5) + Store (\IDX6.TST_.IFE1, Local6) + + Return (0) + } // TEST + } // IDX6 + +// +// test IndexOp5.asl +// +// IndexOp5 test +// This is just a subset of the many RegionOp/Index Field test cases. +// Tests copying string into buffer then performing IndexOp on result. +// + Device (IDX5) + { // Test device name + + Name (OSFL, 0) // 0 == Windows 98, 1 == Windows NT + + // MCTH is a control method to compare two strings. It returns + // zero if the strings mismatch, or 1 if the strings match. + // This exercises the test case of copying a string into a buffer + // and performing an IndexOp on the resulting buffer. + Method (MCTH, 2) // Control Method to compare two strings + { // MCTH: Control Method to compare two strings + // Arg0: first string to compare + // Arg1: second string to compare + // Return: zero if strings mismatch, 1 if strings match + + // check if first string's length is less than second string's length + If (LLess (SizeOf (Arg0), SizeOf (Arg1))) + { Return (0) } + + // increment length to include NULL termination character + Add (SizeOf (Arg0), 1, Local0) // Local0 = strlen(Arg0) + 1 + + // create two buffers of size Local0 [strlen(Arg0)+1] + Name (BUF0, Buffer (Local0) {}) + Name (BUF1, Buffer (Local0) {}) + + // copy strings into buffers + Store (Arg0, BUF0) + Store (Arg1, BUF1) + + // validate BUF0 and BUF1 are still buffers + Store (ObjectType (BUF0), Local1) + If (LNotEqual (Local1, 3)) // Buffer is type 3 + { Return (20) } + Store (ObjectType (BUF1), Local1) + If (LNotEqual (Local1, 3)) // Buffer is type 3 + { Return (21) } + + // Decrement because the Index base below is zero based + // while Local0 length is one based. + Decrement (Local0) + + While (Local0) + { // loop through all BUF0 buffer elements + Decrement (Local0) + + // check if BUF0[n] == BUF1[n] + If (LEqual (DerefOf (Index (BUF0, Local0, )), + DerefOf (Index (BUF1, Local0, )))) + { } // this is how the code was really implemented + Else + { Return (Zero) } + } // loop through all BUF0 buffer elements + + Return (One) // strings / buffers match + } // MCTH: Control Method to compare two strings + + + Method (TEST) + { + Store ("++++++++ IndexOp5 Test", Debug) + + If (MCTH (\_OS, "Microsoft Windows NT")) + { Store (1, OSFL) } + + If (LNotEqual (OSFL, 1)) + { Return (11) } + + Return (0) + } // TEST + } // IDX5 + +// +// test IndexOp.asl +// + Scope (\_SB) // System Bus + { // _SB system bus + + Method (C097) + { Return (1) } + + Device (PCI2) + { // Root PCI Bus + Name (_HID, EISAID("PNP0A03")) + Name (_ADR, 0x00000000) + Name (_CRS, Buffer(26) {"\_SB_.PCI2._CRS..........."}) + Method (_STA) {Return (0x0F)} + + Device (ISA) + { // ISA bridge + Name (_ADR, 0x00030000) // ISA bus ID + + Device (EC0) + { // Embedded Controller + Name (_GPE, 0) // EC use GPE0 + Name (_ADR, 0x0030000) // PCI address + + Method (_STA,0) // EC Status + { Return(0xF) } // EC is functioning + + Name (_CRS, ResourceTemplate() + { + IO (Decode16, 0x62, 0x62, 1, 1) + IO (Decode16, 0x66, 0x66, 1, 1) + } + ) + + // create EC's region and field + OperationRegion (RAM, SystemMemory, 0x400000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { + // AC information + ADP, 1, // AC Adapter 1:On-line, 0:Off-line + AFLT, 1, // AC Adapter Fault 1:Fault 0:Normal + BAT0, 1, // BAT0 1:present, 0:not present + , 1, // reserved + , 28, // filler to force DWORD alignment + + // CMBatt information + BPU0, 32, // Power Unit + BDC0, 32, // Designed Capacity + BFC0, 32, // Last Full Charge Capacity + BTC0, 32, // Battery Technology + BDV0, 32, // Design Voltage + BST0, 32, // Battery State + BPR0, 32, // Battery Present Rate + // (Designed Capacity)x(%)/{(h)x100} + BRC0, 32, // Battery Remaining Capacity + // (Designed Capacity)(%)^100 + BPV0, 32, // Battery Present Voltage + BTP0, 32, // Trip Point + BCW0, 32, // Design capacity of Warning + BCL0, 32, // Design capacity of Low + BCG0, 32, // capacity granularity 1 + BG20, 32, // capacity granularity 2 + BMO0, 32, // Battery model number field + BIF0, 32, // OEM Information(00h) + BSN0, 32, // Battery Serial Number + BTY0, 32, // Battery Type (e.g., "Li-Ion") + BTY1, 32 // Battery Type (e.g., "Li-Ion") + } // Field + } // EC0: Embedded Controller + } // ISA bridge + } // PCI2 Root PCI Bus + + Device (IDX0) + { // Test device name + Name (_HID, EISAID ("PNP0C0A")) // Control Method Battey ID + Name (_PCL, Package() {\_SB}) + Method (_STA) + { + // _STA bits 0-3 indicate existence of battery slot + // _STA bit 4 indicates battery (not) present + If (\_SB.PCI2.ISA.EC0.BAT0) + { Return (0x1F) } // Battery present + else + { Return (0x0F) } // Battery not present + } // _STA + + Method (_BIF) + { + Name (BUFR, Package(13) {}) + Store (\_SB.PCI2.ISA.EC0.BPU0, Index (BUFR,0)) // Power Unit + Store (\_SB.PCI2.ISA.EC0.BDC0, Index (BUFR,1)) // Designed Capacity + Store (\_SB.PCI2.ISA.EC0.BFC0, Index (BUFR,2)) // Last Full Charge Capa. + Store (\_SB.PCI2.ISA.EC0.BTC0, Index (BUFR,3)) // Battery Technology + Store (\_SB.PCI2.ISA.EC0.BDV0, Index (BUFR,4)) // Designed Voltage + Store (\_SB.PCI2.ISA.EC0.BCW0, Index (BUFR,5)) // Designed warning level + Store (\_SB.PCI2.ISA.EC0.BCL0, Index (BUFR,6)) // Designed Low level + Store (\_SB.PCI2.ISA.EC0.BCG0, Index (BUFR,7)) // Capacity granularity 1 + Store (\_SB.PCI2.ISA.EC0.BG20, Index (BUFR,8)) // Capacity granularity 2 + + Store ("", Index (BUFR,9)) // Model Number + + Store ("", Index (BUFR,10)) // Serial Number + + Store ("LiOn", Index (BUFR,11)) // Battery Type + + Store ("Chicony", Index (BUFR,12)) // OEM Information + + Return (BUFR) + } // _BIF + + Method (_BST) + { + Name (BUFR, Package(4) {1, 0x100, 0x76543210, 0x180}) + Return (BUFR) + } // _BST + + Method (_BTP,1) + { + Store (arg0, \_SB.PCI2.ISA.EC0.BTP0) // Set Battery Trip point + } + + Method (TEST) + { + + Store ("++++++++ IndexOp Test", Debug) + + // test storing into uninitialized package elements + Name (PBUF, Package(4) {}) // leave unitialized + Store (0x01234567, Index (PBUF,0)) + Store (0x89ABCDEF, Index (PBUF,1)) + Store (0xFEDCBA98, Index (PBUF,2)) + Store (0x76543210, Index (PBUF,3)) + + // verify values stored into uninitialized package elements + If (LNotEqual (DerefOf (Index (PBUF,0)), 0x01234567)) + { Return (0x10) } + + If (LNotEqual (DerefOf (Index (PBUF,1)), 0x89ABCDEF)) + { Return (0x11) } + + If (LNotEqual (DerefOf (Index (PBUF,2)), 0xFEDCBA98)) + { Return (0x12) } + + If (LNotEqual (DerefOf (Index (PBUF,3)), 0x76543210)) + { Return (0x13) } + + + // store _BIF package return value into Local0 + Store (_BIF, Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Package + If (LNotEqual (Local1, 4)) // Package type is 4 + { Return (0x21) } // failure + + + // test storing into buffer field elements + Name (BUFR, Buffer(16) + { // initial values + 00, 00, 00, 00, 00, 00, 00, 00, + 00, 00, 00, 00, 00, 00, 00, 00, + } + ) // BUFR + // test storing into buffer field elements + Store (0x01234567, Index (BUFR,0)) // should only store 0x67 + Store (0x89ABCDEF, Index (BUFR,4)) // should only store 0xEF + Store (0xFEDCBA98, Index (BUFR,8)) // should only store 0x98 + Store (0x76543210, Index (BUFR,12)) // should only store 0x10 + + // verify storing into buffer field elements + If (LNotEqual (DerefOf (Index (BUFR,0)), 0x67)) + { Return (0x30) } + + If (LNotEqual (DerefOf (Index (BUFR,1)), 0)) + { Return (0x31) } + + If (LNotEqual (DerefOf (Index (BUFR,4)), 0xEF)) + { Return (0x34) } + + If (LNotEqual (DerefOf (Index (BUFR,8)), 0x98)) + { Return (0x38) } + + If (LNotEqual (DerefOf (Index (BUFR,12)), 0x10)) + { Return (0x3C) } + + + Return (0) // pass + } // TEST + } // IDX0 + } // _SB system bus + +// +// test BitIndex.asl +// +// BitIndex test +// This is a test case for accessing fields defined as single bits in +// memory. This is done by creating two index fields that overlay the +// same DWORD in memory. One field accesses the DWORD as a DWORD, the +// other accesses individual bits of the same DWORD field in memory. +// + Scope (\_SB) // System Bus + { // _SB system bus + OperationRegion (RAM, SystemMemory, 0x800000, 0x100) + Field (RAM, AnyAcc, NoLock, Preserve) + { // Any access + TREE, 3, + WRD0, 16, + WRD1, 16, + WRD2, 16, + WRD3, 16, + WRD4, 16, + DWRD, 32, // DWORD field + } + Field (RAM, AnyAcc, NoLock, Preserve) + { // Any access + THRE, 3, + WD00, 16, + WD01, 16, + WD02, 16, + WD03, 16, + WD04, 16, + BYT0, 8, // Start off with a BYTE + BIT0, 1, // single-bit field + BIT1, 1, // single-bit field + BIT2, 1, // single-bit field + BIT3, 1, // single-bit field + BIT4, 1, // single-bit field + BIT5, 1, // single-bit field + BIT6, 1, // single-bit field + BIT7, 1, // single-bit field + BIT8, 1, // single-bit field + BIT9, 1, // single-bit field + BITA, 1, // single-bit field + BITB, 1, // single-bit field + BITC, 1, // single-bit field + BITD, 1, // single-bit field + BITE, 1, // single-bit field + BITF, 1, // single-bit field + BYTZ, 8, // End with a BYTE for a total of 32 bits + } + + Device (BITI) + { // Test device name + + Method (MBIT) // Test single bit memory accesses + { + + If (LNotEqual (DWRD, 0x00)) + { + Store (0xFF00, Local0) + } + Else + { + // Prime Local0 with 0...assume passing condition + Store (0, Local0) + + // set memory contents to known values using DWORD field + Store (0x5A5A5A5A, DWRD) + + // Given the value programmed into DWRD, only the odd bits + // of the lower nibble should be set. BIT1, BIT3 should be set. + // BIT0 and BIT2 should be clear + + If (BIT0) + { + Or (Local0, 0x01, Local0) + } + + If (LNot (BIT1)) + { + Or (Local0, 0x02, Local0) + } + + If (BIT2) + { + Or (Local0, 0x04, Local0) + } + + If (LNot (BIT3)) + { + Or (Local0, 0x08, Local0) + } + + // Now check the upper nibble. Only the "even" bits should + // be set. BIT4, BIT6. BIT5 and BIT7 should be clear. + If (LNot (BIT4)) + { + Or (Local0, 0x10, Local0) + } + + If (BIT5) + { + Or (Local0, 0x20, Local0) + } + + If (LNot (BIT6)) + { + Or (Local0, 0x40, Local0) + } + + If (BIT7) + { + Or (Local0, 0x80, Local0) + } + } // End Else DWRD zeroed out + + Return (Local0) + } // MBIT: Test single bit memory accesses + + Method (TEST) + { + + Store ("++++++++ BitIndex Test", Debug) + + // Zero out DWRD + Store (0x00000000, DWRD) + + // MBIT returns zero if successful + // This may be causing problems -- Return (MBIT) + Store (MBIT, Local0) + + Return (Local0) + } // TEST + } // BITI + } // _SB system bus + +// +// test IndexOp3.asl +// +// Additional IndexOp test cases to support ACPICMB (control method battery +// test) on Compaq laptops. Test cases include storing a package into +// an IndexOp target and validating that changing source and destination +// package contents are independent of each other. +// + Scope (\_SB) // System Bus + { // _SB system bus + + Name (C174, 13) + Name (C175, 8) + + Device (C158) + { // C158: AC Adapter device + Name (_HID, "ACPI0003") // AC Adapter device + Name (_PCL, Package (1) {\_SB}) + + Method (_PSR) + { + Acquire (\_GL, 0xFFFF) + Release (\_GL) + And (Local0, 1, Local0) // Local0 &= 1 + Return (Local0) + } // _PSR + } // C158: AC Adapter device + + Name (C176, Package (4) {"Primary", "MultiBay", "DockRight", "DockLeft"}) + + Name (C177, Package (4) {0x99F5, 0x99F5, 0x995F, 0x995F}) + + Name (C178, Package (4) + { + Package (4) {0, 0, 0x966B, 0x4190}, + Package (4) {0, 0, 0x966B, 0x4190}, + Package (4) {0, 0, 0x966B, 0x4190}, + Package (4) {0, 0, 0x966B, 0x4190} + }) // C178 + + Name (C179, Package (4) {0, 0, 0x966B, 0x4190}) + + Name (C17A, Package (4) + { + Package (3) {0, 0, 0}, + Package (3) {0, 0, 0}, + Package (3) {0, 0, 0}, + Package (3) {0, 0, 0} + }) // C17A + + Method (C17B, 1) + { // C17B: _BIF implementation + Name (C17C, Package (13) + { // C17C: _BIF control method return package + 0, // Power Unit (0 ==> mWh and mW) + 0x99F5, // Design Capacity + 0x99F5, // Last Full Charge Capacity + 1, // Battery Technology (1 ==> rechargeable) + 0x3840, // Design Voltage + 0x1280, // Design Capacity of Warning + 0x0AC7, // Design Capacity of Low + 1, // Battery Capacity Granularity 1 (Low -- Warning) + 1, // Battery Capacity Granularity 2 (Warning -- Full) + "2891", // Model Number (ASCIIZ) + "(-Unknown-)", // Serial Number (ASCIIZ) + "LIon", // Battery Type (ASCIIZ) + 0 // OEM Information (ASCIIZ) + }) // C17C: _BIF control method return package + + And (Arg0, 7, Local0) // Local0 = Arg0 & 7 + + ShiftRight (Local0, 1, Local4) // Local4 = Local0 >> 1 + + Store (C179, Index (C178, Local4, )) // C178->Local4 = C179 + + // verify source and destination packages can be altered independent + // of each other (i.e., changing one's contents does NOT change other's + // contents) + Store (0x1234, Index (C179, 2, )) // C179[2] = 0x1234 + Store (DerefOf (Index (C179, 2, )), Local2) // Local2 = C179[2] + if (LNotEqual (Local2, 0x1234)) + { Return (0x1234) } + // Local2 = C178[0,2] + Store (DerefOf (Index (DerefOf (Index (C178, 0, )), 2, )), Local2) + if (LNotEqual (Local2, 0x966B)) + { Return (0x1234) } + + // Restore data to allow iterative execution + Store (0x966B, Index (C179, 2, )) // C179[2] = 0x966B + + // C178[0,3] = 0x5678 + Store (0x5678, Index (DerefOf (Index (C178, 0, )), 3, )) + // Local2 = C178[0,3] + Store (DerefOf (Index (DerefOf (Index (C178, 0, )), 3, )), Local2) + if (LNotEqual (Local2, 0x5678)) + { Return (0x5678) } + + Store (DerefOf (Index (C179, 3, )), Local2) // Local2 = C179[3] + if (LNotEqual (Local2, 0x4190)) + { Return (0x5678) } + + // Restore data to allow iterative execution + Store (0x4190, Index (DerefOf (Index (C178, 0, )), 3, )) // C179[2] = 0x4190 + + Return (C17C) + } // C17B: _BIF implementation + + Device (C154) + { // C154: Battery 0 + Name (_HID, "*PNP0C0A") // Control Method Battey ID + Name (_UID, 0) // first instance + + Method (_BIF) + { // _BIF + Return (C17B (48)) + } // _BIF + } // C154: Battery 0 + + Device (IDX3) + { + Method (LCLB) + { // LCLB control method: test Index(Local#) where Local# is buffer + // Local0 is index counter + // Local1 is buffer + // Local2 receives BUFR[Local0] via Deref(Index(Local1...)) + // Local3 is Local1 or Local2 object type + // Local4 is return error code + + Name (BUFR, Buffer () {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) + + // save PKG into Local1 + Store (BUFR, Local1) + + // save Local2 object type value into Local3 + Store (ObjectType (Local1), Local3) + + // validate Local1 is a Buffer + If (LNotEqual (Local3, 3)) // Buffer type is 3 + { Return (0x9F) } + + + Store (0, Local0) + While (LLess (Local0, 5)) + { // While (Local0 < 5) + // Local2 = Local1[Local0] + Store (DerefOf (Index (Local1, Local0, )), Local2) + + // save Local2 object type value into Local3 + Store (ObjectType (Local2), Local3) + + // validate Local2 is a Number + If (LNotEqual (Local3, 1)) // Number type is 1 + { Return (0x9E) } + + // validate Local1[Local0] value == Local0 + If (LNotEqual (Local0, Local2)) + { // Local0 != Local2 == PKG[Local0] + // Local4 = 0x90 + loop index (Local0) + Add (0x90, Local0, Local4) + + // return 0x90 + loop index + Return (Local4) + } + + Increment (Local0) + } // While (Local0 < 5) + + Store ("DerefOf(Index(LocalBuffer,,)) PASS", Debug) + + Return (0) // Pass + } // LCLB control method: test Index(Local#) where Local# is buffer + + Method (LCLP) + { // LCLP control method: test Index(Local#) where Local# is package + // Local0 is index counter + // Local1 is package + // Local2 receives PKG[Local0] via Deref(Index(Local1...)) + // Local3 is Local1 or Local2 object type + // Local4 is return error code + + Name (PKG, Package () {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}) + + // save PKG into Local1 + Store (PKG, Local1) + + // save Local2 object type value into Local3 + Store (ObjectType (Local1), Local3) + + // validate Local1 is a Package + If (LNotEqual (Local3, 4)) // Package type is 4 + { Return (0x8F) } + + + Store (0, Local0) + While (LLess (Local0, 5)) + { // While (Local0 < 5) + // Local2 = Local1[Local0] + Store (DerefOf (Index (Local1, Local0, )), Local2) + + // save Local2 object type value into Local3 + Store (ObjectType (Local2), Local3) + + // validate Local2 is a Number + If (LNotEqual (Local3, 1)) // Number type is 1 + { Return (0x8E) } + + // validate Local1[Local0] value == Local0 + If (LNotEqual (Local0, Local2)) + { // Local0 != Local2 == PKG[Local0] + // Local4 = 0x80 + loop index (Local0) + Add (0x80, Local0, Local4) + + // return 0x80 + loop index + Return (Local4) + } + + Increment (Local0) + } // While (Local0 < 5) + + Store ("DerefOf(Index(LocalPackage,,)) PASS", Debug) + + Return (0) // Pass + } // LCLP control method: test Index(Local#) where Local# is package + + Method (TEST) + { + + Store ("++++++++ IndexOp3 Test", Debug) + + // store _BIF package return value into Local0 + Store (\_SB.C154._BIF, Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Package + If (LNotEqual (Local1, 4)) // Package type is 4 + { // failure: did not return a Package (type 4) + // if Local0 is a Number, it contains an error code + If (LEqual (Local1, 1)) // Number type is 1 + { Return (Local0) } // return Local0 error code + Else // Local0 is not a Number + { Return (1) } // return default error code + } // failure: did not return a Package (type 4) + + // save LCLB control method return value into Local2 + Store (LCLB, Local2) + If (LNotEqual (Local2, 0)) + { Return (Local2) } // return failure code + + // save LCLP control method return value into Local2 + Store (LCLP, Local2) + If (LNotEqual (Local2, 0)) + { Return (Local2) } // return failure code + + Return (0) // Pass + } // TEST + } // IDX3: Test device name + } // _SB system bus + +// +// MTL developed test to exercise Indexes into buffers +// + Device(IDX7) + { + + Name (PKG4, Package() { + 0x2, + "A short string", + Buffer() {0xA, 0xB, 0xC, 0xD}, + 0x1234, + Package() {IDX7, 0x3} + }) + + // + // Generic Test method + // + // This test returns 0xE (14) - ObjectType = Buffer Field + Method(TST1) + { + Name (DEST, Buffer () // 62 characters plus NULL + {"Destination buffer that is longer than the short source buffer"}) + + // verify object type returned by Index(Buffer,Element,) + Store (Index (DEST, 2, ), Local1) + Store (ObjectType (Local1), Local2) + If (LEqual(Local2, 14)) + { + Return(0) + } + Else + { + Return(0x1) + } + + } + + Method(TST2) + { + Name (BUF0, Buffer() {0x1, 0x2, 0x3, 0x4, 0x5}) + Store(0x55, Index(BUF0, 2)) + Store(DerefOf(Index(BUF0, 2)), Local0) + If (LEqual(Local0, 0x55)) + { + Return(0) + } + Else + { + Return(0x2) + } + + + } + + Method(TST3) + { + Name (BUF1, Buffer() {0x1, 0x2, 0x3, 0x4, 0x5}) + Store(Index(BUF1, 1), Local0) + Store(DerefOf(Local0), Local1) + If (LEqual(Local1, 0x2)) + { + Return(0) + } + Else + { + Return(0x3) + } + + } + + Method(TST4) + { + // Index (PKG4, 0) is a Number + Store (Index (PKG4, 0), Local0) + Store (ObjectType(Local0), Local1) + If (LEqual(Local1, 0x1)) + { + Return(0) + } + Else + { + Return(0x4) + } + + } + + Method(TST5) + { + // Index (PKG4, 1) is a String + Store (Index (PKG4, 1), Local0) + Store (ObjectType(Local0), Local1) + If (LEqual(Local1, 0x2)) + { + Return(0) + } + Else + { + Return(0x5) + } + + } + + Method(TST6) + { + // Index (PKG4, 2) is a Buffer + Store (Index (PKG4, 2), Local0) + Store (ObjectType(Local0), Local1) + If (LEqual(Local1, 0x3)) + { + Return(0) + } + Else + { + Return(0x6) + } + + } + + Method(TST7) + { + // Index (PKG4, 3) is a Number + Store (Index (PKG4, 3), Local0) + Store (ObjectType(Local0), Local1) + If (LEqual(Local1, 0x1)) + { + Return(0) + } + Else + { + Return(0x7) + } + + } + + Method(TST8) + { + // Index (PKG4, 4) is a Package + Store (Index (PKG4, 4), Local0) + Store (ObjectType(Local0), Local1) + If (LEqual(Local1, 0x4)) + { + Return(0) + } + Else + { + Return(0x8) + } + + } + + Method(TST9) + { + // DerefOf (Index (PKG4, 0)) is a Number + Store (DerefOf (Index (PKG4, 0)), Local0) + If (LEqual(Local0, 0x2)) + { + Return(0) + } + Else + { + Return(0x9) + } + + } + + Method(TSTA) + { + // DerefOf (Index (PKG4, 1)) is a String + Store (DerefOf (Index (PKG4, 1)), Local0) + Store (SizeOf(Local0), Local1) + If (LEqual(Local1, 0xE)) + { + Return(0) + } + Else + { + Return(0xA) + } + + } + + Method(TSTB) + { + // DerefOf (Index (PKG4, 2)) is a Buffer + Store (DerefOf (Index (PKG4, 2)), Local0) + Store (SizeOf(Local0), Local1) + If (LEqual(Local1, 0x4)) + { + Return(0) + } + Else + { + Return(0xB) + } + + } + + Method(TSTC) + { + // DerefOf (Index (PKG4, 3)) is a Number + Store (DerefOf (Index (PKG4, 3)), Local0) + If (LEqual(Local0, 0x1234)) + { + Return(0) + } + Else + { + Return(0xC) + } + + } + + Method(TSTD) + { + // DerefOf (Index (PKG4, 4)) is a Package + Store (DerefOf (Index (PKG4, 4)), Local0) + Store (SizeOf(Local0), Local1) + If (LEqual(Local1, 0x2)) + { + Return(0) + } + Else + { + Return(0xD) + } + + } + + Method(TSTE) + { + // DerefOf (Index (PKG4, 2)) is a Buffer + Store (DerefOf (Index (PKG4, 2)), Local0) + // DerefOf (Index (Local0, 1)) is a Number + Store (DerefOf (Index (Local0, 1)), Local1) + If (LEqual(Local1, 0xB)) + { + Return(0) + } + Else + { + Return(0xE) + } + + } + + Method (TSTF) + { + Name (SRCB, Buffer (12) {}) // 12 characters + Store ("Short Buffer", SRCB) + + Name (DEST, Buffer () // 62 characters plus NULL + {"Destination buffer that is longer than the short source buffer"}) + + // overwrite DEST contents, starting at buffer position 2 + Store (SRCB, Index (DEST, 2)) + + // + // The DEST buffer element should be replaced with the last element of + // the SRCB element (i.e. 's'->'r') + Store (DerefOf (Index (DEST, 2)), Local0) + + If (LNotEqual (Local0, 0x72)) // 'r' + { + // DEST element does not match the value from SRCB + Return(Or(Local0, 0x1000)) + } + + Return(0) + } + + Method (TSTG) + { + + Name (SRCB, Buffer (12) {}) // 12 characters + Store ("Short Buffer", SRCB) + + Name (DEST, Buffer () // 62 characters plus NULL + {"Destination buffer that is longer than the short source buffer"}) + + // overwrite DEST contents, starting at buffer position 2 + Store (SRCB, Index (DEST, 2)) + + // + // The next element of DEST should be unchanged + // + Store (DerefOf (Index (DEST, 3)), Local0) + + If (LNotEqual (Local0, 0x74)) // 't' + { + // DEST has been changed + Return(Or(Local0, 0x2000)) + } + + // + // The next element of DEST should be unchanged + // + Store (DerefOf (Index (DEST, 4)), Local0) + + If (LNotEqual (Local0, 0x69)) // 'i' + { + // DEST has been changed + Return(Or(Local0, 0x2100)) + } + + // + // The next element of DEST should be unchanged + // + Store (DerefOf (Index (DEST, 5)), Local0) + + If (LNotEqual (Local0, 0x6E)) // 'n' + { + // DEST has been changed + Return(Or(Local0, 0x2200)) + } + + // + // The next element of DEST should be unchanged + // + Store (DerefOf (Index (DEST, 6)), Local0) + + If (LNotEqual (Local0, 0x61)) // 'a' + { + // DEST has been changed + Return(Or(Local0, 0x2300)) + } + + // + // The next element of DEST should be unchanged + // + Store (DerefOf (Index (DEST, 7)), Local0) + + If (LNotEqual (Local0, 0x74)) // 't' + { + // DEST has been changed + Return(Or(Local0, 0x2400)) + } + + // + // Verify DEST elements beyond end of SRCB buffer copy + // have not been changed + Store (DerefOf (Index (DEST, 14)), Local0) + + If (LNotEqual (Local0, 0x66)) // 'f' + { + // DEST has been changed + Return(Or(Local0, 0x2400)) + } + + Return(0) + } + + // + // This test shows that MS ACPI.SYS stores only the lower 8-bits of a 32-bit + // number into the index'ed buffer + // + Method (TSTH) + { + // Create a Destination Buffer + Name (DBUF, Buffer () {"abcdefghijklmnopqrstuvwxyz"}) + + // Store a number > UINT8 into an index of the buffer + Store (0x12345678, Index(DBUF, 2)) + + // Check the results + Store (DerefOf (Index (DBUF, 2)), Local0) + If (LNotEqual (Local0, 0x78)) // 0x78 + { + Return(Or(Local0, 0x3000)) + } + + Store (DerefOf (Index (DBUF, 3)), Local0) + If (LNotEqual (Local0, 0x64)) // 'd' + { + Return(Or(Local0, 0x3100)) + } + + Store (DerefOf (Index (DBUF, 4)), Local0) + If (LNotEqual (Local0, 0x65)) // 'e' + { + Return(Or(Local0, 0x3200)) + } + + Store (DerefOf (Index (DBUF, 5)), Local0) + If (LNotEqual (Local0, 0x66)) // 'f' + { + Return(Or(Local0, 0x3300)) + } + + Return(0) + } + + Method (TSTI) + { + // Create a Destination Buffer + Name (DBUF, Buffer () {"abcdefghijklmnopqrstuvwxyz"}) + + // Store a String into an index of the buffer + Store ("ABCDEFGH", Index(DBUF, 2)) + + // Check the results + Store (DerefOf (Index (DBUF, 2)), Local0) + If (LNotEqual (Local0, 0x48)) // 'H' + { + Return(Or(Local0, 0x4000)) + } + + Store (DerefOf (Index (DBUF, 3)), Local0) + If (LNotEqual (Local0, 0x64)) // 'd' + { + Return(Or(Local0, 0x4100)) + } + + Store (DerefOf (Index (DBUF, 4)), Local0) + If (LNotEqual (Local0, 0x65)) // 'e' + { + Return(Or(Local0, 0x4200)) + } + + Store (DerefOf (Index (DBUF, 5)), Local0) + If (LNotEqual (Local0, 0x66)) // 'f' + { + Return(Or(Local0, 0x4300)) + } + + Return(0) + } + + Method(TSTJ) + { + // Create a Destination Buffer + Name (DBUF, Buffer () {"abcdefghijklmnopqrstuvwxyz"}) + + // Store a number > UINT8 into an index of the buffer + Store (0x1234, Index(DBUF, 2)) + + // Check the results + Store (DerefOf (Index (DBUF, 2)), Local0) + If (LNotEqual (Local0, 0x34)) // 0x34 + { + Return(Or(Local0, 0x3000)) + } + + Store (DerefOf (Index (DBUF, 3)), Local0) + If (LNotEqual (Local0, 0x64)) // 'd' + { + Return(Or(Local0, 0x3100)) + } + + Store (DerefOf (Index (DBUF, 4)), Local0) + If (LNotEqual (Local0, 0x65)) // 'e' + { + Return(Or(Local0, 0x3200)) + } + + Store (DerefOf (Index (DBUF, 5)), Local0) + If (LNotEqual (Local0, 0x66)) // 'f' + { + Return(Or(Local0, 0x3300)) + } + + Return(0) + } + + Method(TSTK) + { + // Create a Destination Buffer + Name (DBUF, Buffer () {"abcdefghijklmnopqrstuvwxyz"}) + + // Store a number > UINT8 into an index of the buffer + Store (0x123456, Index(DBUF, 2)) + + // Check the results + Store (DerefOf (Index (DBUF, 2)), Local0) + If (LNotEqual (Local0, 0x56)) // 0x56 + { + Return(Or(Local0, 0x3000)) + } + + Store (DerefOf (Index (DBUF, 3)), Local0) + If (LNotEqual (Local0, 0x64)) // 'd' + { + Return(Or(Local0, 0x3100)) + } + + Store (DerefOf (Index (DBUF, 4)), Local0) + If (LNotEqual (Local0, 0x65)) // 'e' + { + Return(Or(Local0, 0x3200)) + } + + Store (DerefOf (Index (DBUF, 5)), Local0) + If (LNotEqual (Local0, 0x66)) // 'f' + { + Return(Or(Local0, 0x3300)) + } + + Return(0) + } + + Method(TSTL) + { + // Create a Destination Buffer + Name (DBUF, Buffer () {"abcdefghijklmnopqrstuvwxyz"}) + + // Store a number > UINT8 into an index of the buffer + Store (0x12, Index(DBUF, 2)) + + // Check the results + Store (DerefOf (Index (DBUF, 2)), Local0) + If (LNotEqual (Local0, 0x12)) // 0x12 + { + Return(Or(Local0, 0x3000)) + } + + Store (DerefOf (Index (DBUF, 3)), Local0) + If (LNotEqual (Local0, 0x64)) // 'd' + { + Return(Or(Local0, 0x3100)) + } + + Store (DerefOf (Index (DBUF, 4)), Local0) + If (LNotEqual (Local0, 0x65)) // 'e' + { + Return(Or(Local0, 0x3200)) + } + + Store (DerefOf (Index (DBUF, 5)), Local0) + If (LNotEqual (Local0, 0x66)) // 'f' + { + Return(Or(Local0, 0x3300)) + } + + Return(0) + } + + Method(TEST) + { + Store ("++++++++ IndexOp7 Test", Debug) + + Store(TST1(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TST2(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TST3(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TST4(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TST5(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TST6(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TST7(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TST8(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TST9(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TSTA(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TSTB(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TSTC(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TSTD(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TSTE(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + /* No longer ACPI compliant */ + /* + Store(TSTF(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + */ + + Store(TSTG(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TSTH(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + /* No longer ACPI compliant */ + /* + Store(TSTI(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + */ + Store(TSTJ(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TSTK(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Store(TSTL(), Local0) + if (LGreater (Local0, 0)) + { + Return(Local0) + } + + Return(Local0) + + } + + } // Device(IDX7) + +// +// test MatchOp.asl +// +// MatchOp test cases that utilize nested DerefOf(Index(...)) to validate +// MatchOp, DerefOfOp, and IndexOp of nested packages. +// + Device (MTCH) + { + + Method (TEST) + { + Store ("++++++++ MatchOp Test", Debug) + + Name (TIM0, Package () + { + Package () {0x78, 0xB4, 0xF0, 0x0384}, + Package () {0x23, 0x21, 0x10, 0}, + Package () {0x0B, 9, 4, 0}, + Package () {0x70, 0x49, 0x36, 0x27, 0x19}, + Package () {0, 1, 2, 1, 2}, + Package () {0, 0, 0, 1, 1}, + Package () {4, 3, 2, 0}, + Package () {2, 1, 0, 0} + }) // TIM0 + + Name (TMD0, Buffer (20) {0xFF, 0xFF, 0xFF, 0xFF }) + CreateDWordField (TMD0, 0, PIO0) // 0xFFFFFFFF + CreateDWordField (TMD0, 4, DMA0) + CreateDWordField (TMD0, 8, PIO1) + CreateDWordField (TMD0, 12, DMA1) + CreateDWordField (TMD0, 16, CHNF) + + + // validate PIO0 value + Store (PIO0, Local3) + + // save Local3 object type value into Local2 + Store (ObjectType (Local3), Local2) + + // validate Local3 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { Return (2) } // failure + + // validate Local3 Number value + If (LNotEqual (Local3, 0xFFFFFFFF)) // Number value 0xFFFFFFFF + { Return (3) } // failure + + Store ("DWordField PASS", Debug) + + + Store (0, Local5) + Store (Match (DerefOf (Index (TIM0, 1, )), MLE, Local5, MTR, 0, 0), Local6) + + // save Local6 object type value into Local2 + Store (ObjectType (Local6), Local2) + + // validate Local6 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { Return (4) } // failure + + Store ("Match(DerefOf(Index(TIM0,1)),... PASS", Debug) + + + // validate following produces a nested package to validate + // that MatchOp did not corrupt SearchPackage (TIM0) + Store (DerefOf (Index (TIM0, 1, )), Local4) + + // save Local4 object type value into Local2 + Store (ObjectType (Local4), Local2) + + // validate Local4 is a Package + If (LNotEqual (Local2, 4)) // Package type is 4 + { Return (5) } // failure + + Store ("DerefOf(Index(TIM0,1)),... PASS", Debug) + + + And (Match (DerefOf (Index (TIM0, 0, )), MGE, PIO0, MTR, 0, 0), 3, Local0) + + // save Local0 object type value into Local2 + Store (ObjectType (Local0), Local2) + + // validate Local0 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { Return (6) } // failure + + // validate Local0 Number value + If (LNotEqual (Local0, 3)) // Number value 3 + { Return (7) } // failure + + Store ("And(Match(DerefOf(Index(TIM0,0)),... PASS", Debug) + + + // again, validate following produces a nested package + Store (DerefOf (Index (TIM0, 1, )), Local4) + + // save Local4 object type value into Local2 + Store (ObjectType (Local4), Local2) + + // validate Local4 is a Package + If (LNotEqual (Local2, 4)) // Package type is 4 + { Return (8) } // failure + + Store ("DerefOf(Index(TIM0,1)),... PASS again", Debug) + + + // again, validate following produces a nested package + Store (DerefOf (Index (TIM0, 1, )), Local4) + + // save Local4 object type value into Local2 + Store (ObjectType (Local4), Local2) + + // validate Local4 is a Package + If (LNotEqual (Local2, 4)) // Package type is 4 + { Return (9) } // failure + + Store ("DerefOf(Index(TIM0,1)),... PASS again", Debug) + + + // test nested DerefOf(Index) operators + Store (DerefOf (Index (DerefOf (Index (TIM0, 1, )), Local0, )), Local1) + + // save Local1 object type value into Local2 + Store (ObjectType (Local1), Local2) + + // validate Local1 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { Return (10) } // failure + + // zero indicates pass, non-zero is an error code + If (LNotEqual (Local1, 0)) + { Return (11) } // failure + + Store ("DerefOf(Index(DerefOf(Index(TIM0,1)),... PASS", Debug) + + + // again, validate following produces a nested package + Store (DerefOf (Index (TIM0, 1, )), Local4) + + // save Local4 object type value into Local2 + Store (ObjectType (Local4), Local2) + + // validate Local4 is a Package + If (LNotEqual (Local2, 4)) // Package type is 4 + { Return (12) } // failure + + Store ("DerefOf(Index(TIM0,1)),... PASS again", Debug) + + + // retest nested DerefOf(Index) operators + Store (DerefOf (Index (DerefOf (Index (TIM0, 1, )), Local0, )), Local1) + + // save Local1 object type value into Local2 + Store (ObjectType (Local1), Local2) + + // validate Local1 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { Return (13) } // failure + + // zero indicates pass, non-zero is an error code + If (LNotEqual (Local1, 0)) + { Return (14) } // failure + + Store ("DerefOf(Index(DerefOf(Index(TIM0,1)),... PASS again", Debug) + + + // again, validate following produces a nested package + Store (DerefOf (Index (TIM0, 1, )), Local4) + + // save Local4 object type value into Local2 + Store (ObjectType (Local4), Local2) + + // validate Local4 is a Package + If (LNotEqual (Local2, 4)) // Package type is 4 + { Return (15) } // failure + + Store ("DerefOf(Index(TIM0,1)),... PASS again", Debug) + + + Return (0) // pass + } // TEST + } // MTCH + +// +// test WhileBrk.asl +// +// This code tests the Break term and While term +// +// Syntax of Break term +// BreakTerm := Break +// The break operation causes the current package execution to complete. +// +// Syntax of While Term +// WhileTerm := While( +// Predicate //TermArg=>Integer +// ) {TermList} +// Predicate is evaluated as an integer. +// If the integer is non-zero, the list of terms in TermList is executed. +// The operation repeats until the Predicate evaluates to zero. +// +// MTL NOTE: This test has been modified to reflect ACPI 2.0 break +// NOTE: This test, when run under the MS ACPI.SYS grinds the system to +// a halt. +// + Device (WHLB) + { + Name (CNT0, 0) + Name (CNT1, 0) + + Method (TEST) + { + // Check Break statement nested in If nested in While nested in + // While only exits inner-most While loop + Store (0, CNT0) + + While (LLess (CNT0, 4)) + { + Store (0, CNT1) + While (LLess (CNT1, 10)) + { + if (LEqual (CNT1, 1)) + { + Break // exit encompassing loop + } + + Increment (CNT1) + } + + If (LNotEqual (CNT1, 1)) + { + // failure + Return (7) + } + + Increment (CNT0) + } + + // Verify Break only exited inner-most While loop + + If (LNotEqual (CNT0, 4)) + { + // failure + Return (8) + } + + Store ("While/While/If/Break PASS", Debug) + + Store ("++++++++ WhileBrk Test", Debug) + + // Check Break statement nested in While + Store (0, CNT0) + + While (LLess (CNT0, 10)) + { + Break // exit encompassing package + Increment (CNT0) + } + + If (LNotEqual (CNT0, 0)) // instruction after Break executed + { + Return (4) + } + + + Store (0, CNT0) + + // Test While Term + While (LLess (CNT0, 10)) + { + Increment (CNT0) + } + + // Check if the while loop was executed until the condition is satisfied. + If (LNotEqual (CNT0, 10)) + { + Return (1) + } + + + // While loop in a reverse order + While (LGreater (CNT0, 0)) + { + Decrement (CNT0) + } + + // Check if the while loop was executed until the condition is satisfied. + If (LNotEqual (CNT0, 0)) + { + Return (2) + } + + + Store ("While/Break PASS", Debug) + + + // Check Break statement nested in If nested in While + Store (0, CNT0) + + While (LLess (CNT0, 10)) + { + if (LEqual (CNT0, 5)) + { + Break // exit encompassing Package (If) + + // if we execute the next instruction, + // Break did not exit the loop + Store (20, CNT0) // exit While loop with value larger + // than above + } + + Increment (CNT0) // check if Break exited both If and While + } // While + + If (LGreater (CNT0, 19)) + { // instruction after Break inside IfOp executed + Return (5) + } + + // + // Break will exit out of the while loop, therefore + // the CNT0 counter should still Increment until 5 + // + If (LNotEqual (CNT0, 5)) + { // instruction after Break inside WhileOp executed + Return (6) + } + Store ("While/If/Break PASS", Debug) + + + // All the conditions passed + Return (0) + } // TEST + } // WHLB + + +// +// test IndexOp2.asl +// +// Additional IndexOp test cases to support ACPICMB (control method battery +// test) on Toshiba Portege 7020CT. Test cases include appropriate bit +// shifting of Field elements and reading Field elements greater than 64 bits. +// +// MTL NOTE: This test has been modified slightly from the original test +// to take into account ACPI specification limitations. +// + Scope (\_SB) // System Bus + { // _SB system bus + + Device (MEM) + { // MEM + Name (_HID, 0x010CD041) + Name (_STA, 0x0F) + + OperationRegion (SMEM, SystemMemory, 0x800000, 0x100) + Field (SMEM, AnyAcc, NoLock, Preserve) + { // Field: SMEM overlay using 32-bit field elements + SMD0, 32, // 32-bits + SMD1, 32, // 32-bits + SMD2, 32, // 32-bits + SMD3, 32 // 32-bits + } // Field: SMEM overlay using 32-bit field elements + Field (SMEM, AnyAcc, NoLock, Preserve) + { // Field: SMEM overlay using greater than 32-bit field elements + SME0, 69, // larger than an integer (32 or 64) + SME1, 97 // larger than an integer + } // Field: SMEM overlay using greater than 32-bit field elements + + OperationRegion (SRAM, SystemMemory, 0x100B0000, 0xF000) + Field (SRAM, AnyAcc, NoLock, Preserve) + { // Field: SRAM overlay + , 0x34000, // skip + IEAX, 0x20, + IEBX, 0x20, + IECX, 0x20, + IEDX, 0x20, + IESI, 0x20, + IEDI, 0x20, + IEBP, 0x20, + , 0x20, + OEAX, 0x20, + OEBX, 0x20, + OECX, 0x20, + OEDX, 0x20, + OESI, 0x20, + OEDI, 0x20, + OEBP, 0x20, + , 0x618, // skip + ACST, 1, + BES1, 1, + BES2, 1, + , 5, // skip + BMN1, 0x68, + BSN1, 0x58, + BTP1, 0x48, + BPU1, 0x20, + BDC1, 0x20, + BLF1, 0x20, + BTC1, 0x20, + BDV1, 0x20, + BST1, 0x20, + BPR1, 0x20, + BRC1, 0x20, + BPV1, 0x20, + , 0x20, + BCW1, 0x20, + BCL1, 0x20, + BG11, 0x20, + BG21, 0x20, + BOI1, 0x20, + , 0x530, // skip + BMN2, 0x68, + BSN2, 0x58, + BTP2, 0x48, + BPU2, 0x20, + BDC2, 0x20, + BLF2, 0x20, + BTC2, 0x20, + BDV2, 0x20, + BST2, 0x20, + BPR2, 0x20, + BRC2, 0x20, + BPV2, 0x20, + , 0x20, + BCW2, 0x20, + BCL2, 0x20, + BG12, 0x20, + BG22, 0x20, + BOI2, 0x20, + , 0x518, // skip + AC01, 0x10, + AC11, 0x10, + PSV1, 0x10, + CRT1, 0x10, + TMP1, 0x10, + AST1, 0x10, + AC21, 0x10, + AC31, 0x10, + AC02, 0x10, + AC12, 0x10, + PSV2, 0x10, + CRT2, 0x10, + TMP2, 0x10, + AST2, 0x10, + AC22, 0x10, + AC32, 0x10, + AC03, 0x10, + AC13, 0x10, + PSV3, 0x10, + CRT3, 0x10, + TMP3, 0x10, + AST3, 0x10, + AC23, 0x10, + AC33, 0x10, + , 0x80, // skip + TMPF, 0x10, + , 0x570, // skip + FANH, 1, + FANL, 7, + TF11, 1, + TF21, 1, + TF31, 1, + , 1, + TF10, 1, + TF20, 1, + TF30, 1, + , 1, + TP11, 1, + TP21, 1, + TP31, 1, + , 0x6D, // 109 + GP50, 1, + GP51, 1, + GP52, 1, + GP53, 1, + , 4, + GP60, 1, + GP61, 1, + GP62, 1, + GP63, 1, + GP64, 1, + GP65, 1, + GP66, 1, + , 1, + GP70, 1, + GP71, 1, + GP72, 1, + GP73, 1, + GP74, 1, + GP75, 1, + GP76, 1, + , 1, + WED0, 1, + WED1, 1, + WED2, 1, + WED3, 1, + WED4, 1, + , 3, + SBL0, 1, + SBL1, 1, + SBL2, 1, + SBL3, 1, + , 4, + LIDS, 1, + VALF, 1, + , 2, + DCKI, 1, + DCKF, 1, + BT1F, 1, + BT2F, 1, + , 0x7D0, // skip + HKCD, 8, + , 8, + DLID, 0x20, + DSRN, 0x20, + , 0x20, + BDID, 0x20, + DSPW, 1, + VGAF, 1, + VWE0, 1, + VWE1, 1, + PPSC, 1, + SPSC, 1, + EWLD, 1, + EWPS, 1, + , 0x1768, // skip + PRES, 0x8000 + } // Field: SRAM overlay + } // MEM + + Device (BAT1) + { // BAT1 + Name (_HID, EISAID ("PNP0C0A")) // Control Method Battey ID + Name (_UID, 1) + Name (_PCL, Package (1) {\_SB}) + + Method (_STA) + { // _STA + If (\_SB.MEM.BES1) + { Return (0x1F) } // battery present + Else + { Return (0x0F) } // battery not present + } // _STA + + Method (_BIF) + { // _BIF + Name (BUFR, Package (13) {}) + + Store (\_SB.MEM.BPU1, Index (BUFR, 0)) + Store (\_SB.MEM.BDC1, Index (BUFR, 1)) + Store (\_SB.MEM.BLF1, Index (BUFR, 2)) + Store (\_SB.MEM.BTC1, Index (BUFR, 3)) + Store (\_SB.MEM.BDV1, Index (BUFR, 4)) + Store (\_SB.MEM.BCW1, Index (BUFR, 5)) + Store (\_SB.MEM.BCL1, Index (BUFR, 6)) + Store (\_SB.MEM.BG11, Index (BUFR, 7)) + Store (\_SB.MEM.BG21, Index (BUFR, 8)) + Store (\_SB.MEM.BMN1, Index (BUFR, 9)) + Store (\_SB.MEM.BSN1, Index (BUFR, 10)) + Store (\_SB.MEM.BTP1, Index (BUFR, 11)) + Store (\_SB.MEM.BOI1, Index (BUFR, 12)) + + Return (BUFR) + } // _BIF + } // BAT1 + + Device (IDX2) + { + Method (B2IB) + { // B2IB: store from Buffer into Index'ed Buffer + + Name (SRCB, Buffer () {"Short Buffer"}) // 12 characters plus NULL + + Name (DEST, Buffer () // 62 characters plus NULL + {"Destination buffer that is longer than the short source buffer"}) + + + // verify object type returned by Index(Buffer,Element,) + + Store (Index (DEST, 2, ), Local1) + Store (ObjectType (Local1), Local2) + + If (LNotEqual (Local2, 14)) // Buffer Field is type 14 + { + // Local2 indicates Local1 is not a Buffer Field + + Return (0x61) + } + + // verify object type and value returned by DerefOf(Index(Buffer,Element,)) + // should return Number containing element value + + Store (DerefOf (Local1), Local3) + Store (ObjectType (Local3), Local4) + + If (LNotEqual (Local4, 1)) // Number is type 1 + { + // Local2 indicates Local1 is not a Number + Return (0x62) + } + Else + { + If (LNotEqual (Local3, 0x73)) // expect 's' element from DEST + { + Return (0x63) + } + } + + Store ("DerefOf(Index(Buffer,,)) PASS", Debug) + + + // + // The following sections have been rewritten because storing into + // an Indexed buffer only changes one byte - the FIRST byte of the + // buffer is written to the source index. This is the ONLY byte + // written -- as per ACPI 2.0 + // + // Overwrite DEST contents, at buffer position 2 [only] + + Store (SRCB, Index (DEST, 2, )) + + // + // Check that the next byte is not changed + // + Store (DerefOf (Index (DEST, 3, )), Local0) + If (LNotEqual (Local0, 0x74)) // 't' + { + // DEST element is not matching original value + If (LEqual (Local0, 0x68)) + { + // DEST element was altered to 'h' + Return (0x68) + } + Else + { + // DEST element is an unknown value + Return (0x69) + } + } + + // + // Check that the elements beyond the SRCB buffer copy + // have not been altered. + // + Store (DerefOf (Index (DEST, 14)), Local0) + + // + // This should be an 'f'. + // + If (LNotEqual (Local0, 0x66)) + { + // DEST element was zero'd by buffer copy + If (LEqual (Local0, 0)) + { + // DEST element is zero + Return (0x6A) + } + Else + { + // DEST element is unknown value + Return (0x6B) + } + } + + Store ("Store(SRCB,Index(Buffer,,)) PASS", Debug) + + // + // verify altering SRCB does NOT alter DEST + // + Store (0x6A, Index (SRCB, 1)) // SRCB = "Sjort Buffer" + + Store (DerefOf (Index (SRCB, 1)), Local0) + + If (LNotEqual (Local0, 0x6A)) // 'j' + { + // SRCB element is unaltered + Return (0x71) + } + + Store (DerefOf (Index (DEST, 3)), Local0) // DEST = "Destination buffer that... + + If (LNotEqual (Local0, 0x74)) // 't' + { + // DEST element is altered + If (LEqual (Local0, 0x6A)) // 'j' + { + // SRCB change altered DEST element + Return (0x72) + } + Else + { + // DEST element is unknown value + Return (0x73) + } + } + + // verify altering DEST does NOT alter SRCB + + Store (0x6B, Index (DEST, 4, )) // DEST = "DeSkination buffer..." + + Store (DerefOf (Index (DEST, 4, )), Local0) + + If (LNotEqual (Local0, 0x6B)) // 'k' + { + // DEST element is unaltered + Return (0x74) + } + + Store (DerefOf (Index (SRCB, 2, )), Local0) + + If (LNotEqual (Local0, 0x6F)) // 'o' + { // SRC element is altered + If (LEqual (Local0, 0x6B)) // 'k' + { + // DEST change altered SRCB element + Return (0x75) + } + Else + { + // SRCB element is unknown value + Return (0x76) + } + } + + Store ("SRCB and DEST independent PASS", Debug) + + + // verify string can be written to Index target/destination + // Only FIRST byte is written + + Store ("New Buff", Index (DEST, 2, )) // DEST = "DeNkination buffer..." + + Store (DerefOf (Index (DEST, 2, )), Local0) + + If (LNotEqual (Local0, 0x4E)) // 'N' + { + // DEST element is unaltered + Return (0x81) + } + + Store (DerefOf (Index (DEST, 6, )), Local0) + + If (LNotEqual (Local0, 0x61)) // 'a' + { + // DEST element is unaltered + Return (0x82) + } + + Store (DerefOf (Index (DEST, 10, )), Local0) + + If (LNotEqual (Local0, 0x6E)) // 'n' + { + // DEST element is unaltered + Return (0x83) + } + + Store ("Store(String,Index) PASS", Debug) + + + Return (0) // pass + } // B2IB: store from Buffer into Index'ed Buffer + + Method (FB2P) + { // FB2P: store from Field Buffer into Index'ed Package + Name (DEST, Package (2) {}) + + // initialize memory using 32-bit field elements + Store (0x01234567, \_SB.MEM.SMD0) + Store (0x89ABCDEF, \_SB.MEM.SMD1) + Store (0xFEDCBA98, \_SB.MEM.SMD2) + Store (0x76543210, \_SB.MEM.SMD3) + + // move greater than 64-bit buffers into DEST package + Store (\_SB.MEM.SME0, Index (DEST, 0)) + Store (\_SB.MEM.SME1, Index (DEST, 1)) + + // validate DEST contents + Store (DerefOf (Index (DEST, 0, )), Local0) + Store (DerefOf (Index (DEST, 1, )), Local1) + + // verify Local0 and Local1 are Buffers + Store (ObjectType (Local0), Local2) + if (LNotEqual (Local2, 3)) // Buffer type is 3 + { + Return (0x11) + } + + Store (ObjectType (Local1), Local3) + if (LNotEqual (Local3, 3)) // Buffer type is 3 + { + Return (0x12) + } + + // validate DEST buffer contents + Store (DerefOf (Index (DerefOf (Index (DEST, 0)), 0)), Local4) + If (LNotEqual (Local4, 0x67)) + { + Return (0x13) + } + + Store (DerefOf (Index (DerefOf (Index (DEST, 0)), 1)), Local4) + If (LNotEqual (Local4, 0x45)) + { + Return (0x14) + } + + Store (DerefOf (Index (DerefOf (Index (DEST, 0)), 4)), Local4) + If (LNotEqual (Local4, 0xEF)) + { + Return (0x15) + } + + Store (DerefOf (Index (DerefOf (Index (DEST, 0, )), 5, )), Local4) + If (LNotEqual (Local4, 0xCD)) + { + Return (0x16) + } + + Store ("Store(Mem,PkgElement) PASS", Debug) + + + // validate changing source \_SB.MEM.SMD* does not impact DEST + Store (0x12345678, \_SB.MEM.SMD0) + + Store (DerefOf (Index (DerefOf (Index (DEST, 0, )), 0, )), Local5) + If (LNotEqual (Local5, 0x67)) + { + Return (0x21) + } + + Store (DerefOf (Index (DerefOf (Index (DEST, 0, )), 1, )), Local5) + If (LNotEqual (Local5, 0x45)) + { + Return (0x22) + } + + // validate changing DEST does not impact source \_SB.MEM.SMD* + Store (0x30, Index (DerefOf (Index (DEST, 0)), 0)) + + Store (DerefOf(Index (DerefOf (Index (DEST, 0)), 0)), Local5) + If (LNotEqual (Local5, 0x30)) + { + Return (0x23) + } + + // + // This section was modified from the original iPCO code because + // it attempted to compare two buffers. This is not allowed until + // ACPI v2.0, so the test has been modified to just check the + // changed \_SB.MEM.SMD0 + // + Store (\_SB.MEM.SMD0, Local5) + + If(LNotEqual(Local5, 0x12345678)) + { + Return (0x24) + } + + Store ("Mem and Pkg independent PASS", Debug) + + + Return (0) + } // FB2P: store from Field Buffer into Index'ed Package + + Method (TEST) + { + Store ("++++++++ IndexOp2 Test", Debug) + + // store _BIF package return value into Local0 + + Store (\_SB.BAT1._BIF, Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Package + If (LNotEqual (Local1, 4)) // Package type is 4 + { + // failure + Return (2) + } + + // validate source and destination buffers are independent of each + // of each other (i.e., changing one's contents does not change + // other's contents) using B2IB (store from Buffer into Index'ed + // Buffer) and FB2P (store from Field Buffer into Index'ed Package) + + // call B2IB (store from Buffer into Index'ed Buffer) + Store (B2IB, Local2) // Local2 is B2IB return value + + // save Local2 object type value into Local3 + Store (ObjectType (Local2), Local3) + + // validate Local2 is a Number + If (LNotEqual (Local3, 1)) // Number type is 1 + { + // failure + Return (4) + } + + // zero indicates pass, non-zero is an error code + If (LNotEqual (Local2, 0)) + { + // return B2IB error code + Return (Local2) + } + + // call FB2P (store from Field Buffer into Index'ed Package) + Store (FB2P, Local2) // Local2 is FB2P return value + + // save Local2 object type value into Local3 + Store (ObjectType (Local2), Local3) + + // validate Local2 is a Number + If (LNotEqual (Local3, 1)) // Number type is 1 + { + // failure + Return (5) + } + + // zero indicates pass, non-zero is an error code + If (LNotEqual (Local2, 0)) + { + // return FB2P error code + Return (Local2) + } + + + Return (0) + } // TEST + } // IDX2: Test device name + } // _SB system bus + +// +// test SizeOf.asl +// +// Test for SizeOf +// test cases include following SizeOf arguments: +// buffer, buffer field; +// control method argument, control method local variable; +// control method return values; +// direct string, string; +// package; +// buffer, package, and string package elements +// +// MTL NOTE: This test has been modified to remove any SizeOf(Index(Buff,... +// calls because it is not legal to perform a SizeOf operation on a Buffer Field. +// This test has also been extended to test additional Package element sizes. +// + Device (SIZO) + { + // SAR0 control method validates SizeOf(Arg) + // SAR0 should only be called by SARG + Method (SAR0, 2) + // Arg0 object to determine size of + // Arg1 expected Arg length + { // SAR0: SizeOf(Arg) test control method + // Local0 Arg0 length + // Local1 Local0 object type + + // Store first string size (Arg0) into Local7 + Store (SizeOf (Arg0), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { Return (0x21) } + + // If strings are not of equal size, return error code + If (LNotEqual (Local0, Arg1)) + { Return (0x22) } + + Return (0) + } // SAR0: SizeOf(Arg) test control method + + Method (SARG) + { // SARG: SizeOf(Arg) test control method + Name (BUFR, Buffer (12) {}) // uninitialized Buffer + Name (BUF1, Buffer() {0x01, 0x02, 0x03, 0x04, 0x05}) + Name (PKG0, Package (4) {}) // uninitialized Package + Name (STR0, "String") + Name (PKG1, Package (4) + { + BUFR, + "String2", + STR0, + PKG0 + }) // PKG1 + + Name (PKG2, Package (4) + { + Buffer (15) {}, + "String 1", + Package (2) {} + }) // PKG2 + + // Namespace entry buffer reference + Store (SAR0 (BUFR, 12), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x23) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=BUFR) PASS", Debug) + + + // Namespace entry package reference + Store (SAR0 (PKG0, 4), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x24) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=PKG0) PASS", Debug) + + + // Namespace entry string reference + Store (SAR0 (STR0, 6), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x25) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=STR0) PASS", Debug) + + + // direct string reference + Store (SAR0 ("String", 6), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x26) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=String) PASS", Debug) + + Store (0x55, Index (BUF1, 2)) + + /**************************************************** + // + // This section is commented because it is illegal to + // perform a SizeOf operation on a Buffer Field + // + // Namespace BufferField reference + Store (SAR0 (Index (BUFR, 2, ), 10), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { Return (0x27) } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { Return (Local0) } + + Store ("SizeOf(Arg=BufferField) PASS", Debug) + ****************************************************/ + + // Namespace BufferPackageElement reference + // + Store (SAR0 (Index(PKG1, 0), 12), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x28) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=PackageBuffer NTE Reference Element) PASS", Debug) + + + // Namespace StringPackageElement reference + Store (SAR0 (Index (PKG1, 1, ), 7), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x29) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=Package String Element) PASS", Debug) + + + // Namespace StringPackageElement reference + Store (SAR0 (Index (PKG1, 2, ), 6), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x2A) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=Package String NTE Reference Element) PASS", Debug) + + + // Namespace PackagePackageElement reference + Store (SAR0 (Index (PKG1, 3, ), 4), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x2B) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=Package Package NTE Reference Element) PASS", Debug) + + // Package Buffer Element + Store (SAR0 (Index (PKG2, 0), 15), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x2B) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=Package Buffer Element) PASS", Debug) + + // Package String Element + Store (SAR0 (Index (PKG2, 1), 8), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x2B) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=Package String Element) PASS", Debug) + + // Package Package Element + Store (SAR0 (Index (PKG2, 2), 2), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x2B) + } + + If (LNotEqual (Local0, 0)) // Local0 is SAR0 return error code + { + Return (Local0) + } + + Store ("SizeOf(Arg=Package Package Element) PASS", Debug) + + Store ("SizeOf(Arg) PASS", Debug) + + Return (0) + } // SARG: SizeOf(Arg) test control method + + Method (SBUF) + { // SBUF: SizeOf(Buffer) test control method + Name (BUFR, Buffer (12) {}) + + // store size of BUFR buffer into Local0 + Store (SizeOf (BUFR), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x31) + } + + If (LNotEqual (Local0, 12)) // BUFR size is 12 + { + Return (0x32) + } + + Store ("SizeOf(BUFR) PASS", Debug) + + Return (0) + } // SBUF: SizeOf(Buffer) test control method + + + /**************************************************** + // + // This section is commented because it is illegal to + // perform a SizeOf operation on a Buffer Field + // + Method (SIND) + { // SIND: SizeOf(Index(,,)) test control method + Name (BUFR, Buffer (12) {}) + + // store size of Index(BUFR,2,) buffer into Local0 + Store (SizeOf (Index (BUFR, 2, )), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x41) + } + + If (LNotEqual (Local0, 10)) // 12 - 2 = 10 + { + Return (0x42) + } + + Store ("SizeOf(Index(BUFR,,)) PASS", Debug) + + // TBD: strings and packages + + Return (0) + } // SIND: SizeOf(Index(,,)) test control method + ****************************************************/ + + Method (SLOC) + { // SLOC: SizeOf(Local) test control method + Name (BUFR, Buffer (12) {}) // uninitialized Buffer + Name (STR0, "String") + Name (PKG0, Package (4) {}) // uninitialized Package + + + // store BUFR Buffer into Local2 + Store (BUFR, Local2) + + // store size of BUFR buffer into Local0 + Store (SizeOf (Local2), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x51) + } + + If (LNotEqual (Local0, 12)) // BUFR size is 12 + { + Return (0x52) + } + + Store ("SizeOf(Local2=Buffer) PASS", Debug) + + + // store STR0 string into Local2 + Store (STR0, Local2) + + // store size of STR0 buffer into Local0 + Store (SizeOf (Local2), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x53) + } + + If (LNotEqual (Local0, 6)) // STR0 size is 6 + { + Return (0x54) + } + + Store ("SizeOf(Local2=String) PASS", Debug) + + + // store PKG0 Package into Local2 + Store (PKG0, Local2) + + // store size of PKG0 buffer into Local0 + Store (SizeOf (Local2), Local0) + + // save Local0 object type value into Local1 + Store (ObjectType (Local0), Local1) + + // validate Local0 is a Number + If (LNotEqual (Local1, 1)) // Number type is 1 + { + Return (0x55) + } + + If (LNotEqual (Local0, 4)) // PKG0 size is 4 + { + Return (0x56) + } + + Store ("SizeOf(Local2=Package) PASS", Debug) + + + Return (0) + } // SLOC: SizeOf(Local) test control method + + Method (TEST) + { + Store ("++++++++ SizeOf Test", Debug) + + // Store current operating system string into Local0 + Store (_OS, Local0) + + Store (SizeOf (_OS), Local3) + + // save Local3 object type value into Local4 + Store (ObjectType (Local3), Local4) + + // validate Local3 is a Number + If (LNotEqual (Local4, 1)) // Number type is 1 + { + // failure + Return (0x61) + } + + // Store current operating system string into Local0 + // This verifies above SizeOf(_OS) did not corrupt ACPI namespace + Store (_OS, Local0) + + // Store SARG [Validate SizeOf(Arg)] return value into Local1 + Store (SARG, Local1) + + // save Local1 object type value into Local2 + Store (ObjectType (Local1), Local2) + + // validate Local1 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { + // failure + Return (0x62) + } + + // zero indicates pass, non-zero is an error code + If (LNotEqual (Local1, 0)) + { + // return SARG error code + Return (Local1) + } + + + // Store SBUF [Validate SizeOf(Buffer)] return value into Local1 + Store (SBUF, Local1) + + // save Local1 object type value into Local2 + Store (ObjectType (Local1), Local2) + + // validate Local1 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { + // failure + Return (0x63) + } + + // zero indicates pass, non-zero is an error code + If (LNotEqual (Local1, 0)) + { + // return SBUF error code + Return (Local1) + } + + /**************************************************** + // + // This section is commented because it is illegal to + // perform a SizeOf operation on a Buffer Field + // + // Store SIND [verify SizeOf(Index(,,))] return value into Local1 + Store (SIND, Local1) + + // save Local1 object type value into Local2 + Store (ObjectType (Local1), Local2) + + // validate Local1 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { + // failure + Return (0x64) + } + + // zero indicates pass, non-zero is an error code + If (LNotEqual (Local1, 0)) + { + // return SARG error code + Return (Local1) + } + ****************************************************/ + + // Store SLOC [verify SizeOf(Local)] return value into Local1 + Store (SLOC, Local1) + + // save Local1 object type value into Local2 + Store (ObjectType (Local1), Local2) + + // validate Local1 is a Number + If (LNotEqual (Local2, 1)) // Number type is 1 + { + // failure + Return (0x65) + } + + // zero indicates pass, non-zero is an error code + If (LNotEqual (Local1, 0)) + { + // return SLOC error code + Return (Local1) + } + + + // TBD: SizeOf (METH) -- where METH control method returns + // buffer, BufferField, string, package, package element + + + Return (0) + } // TEST + } // SIZO + +// +// test SmiShare.asl +// + Scope (\_SB) // System Bus + { // _SB system bus + // Declare an OpRegion in Memory starting at offset 0x400000 that is 10 bytes long + OperationRegion(RAM1, SystemMemory, 0x400000, 0xA) + + Field (RAM1, AnyAcc, NoLock, Preserve) + { + BI1T, 1, // Create some bits in memory to access + BI2T, 2, + BI3T, 3, + LST2, 2 + } // End Field RAM1 + + Field (RAM1, WordAcc, NoLock, WriteAsZeros) + { + WRD, 16 + } // End 2nd Field RAM1 + + Field (RAM1, ByteAcc, NoLock, WriteAsOnes) + { + BYTE, 8 + } // End 3rd Field RAM1 + + Field (RAM1, ByteAcc, NoLock, Preserve) + { + SMIC, 8, + SMID, 8 + } + + Device (MBIT) + { + Method (_INI) + { + Store (0, BI1T) + Store (3, BI2T) + Store (7, BI3T) + Store (0, LST2) + } // End _INI Method + } // End Device MBIT + + Device (MWRD) + { + Method (_INI) + { + Store (0, WRD) + } // End _INI Method + } // End Device MWRD + + Device (MBYT) + { + Method (_INI) + { + Store (0, BYTE) + Store (0xC, SMIC) + Store (0xD, SMID) + } // End _INI Method + } // End Device MBYT + + /* + // Declare an OpRegion in Memory starting at offset 0x400000 that is 10 bytes long + OperationRegion(\RAM1, SystemMemory, 0x400000, 0xA) + + Field (\RAM1, AnyAcc, NoLock, Preserve) + { + BI1T, 1, // Create some bits in memory to access + BI2T, 2, + BI3T, 3, + LST2, 2 + } // End Field RAM1 + + Field (\RAM1, WordAcc, NoLock, WriteAsZeros) + { + WRD, 16 + } // End 2nd Field RAM1 + + Field (\RAM1, ByteAcc, NoLock, WriteAsOnes) + { + BYTE, 8 + } // End 3rd Field RAM1 + + Field (\RAM1, ByteAcc, NoLock, Preserve) + { + SMIC, 8, + SMID, 8 + } + */ + Method (SMIX) + { + Return (BYTE) + } // End SMIX + + Method (EVNT) + { + Store (SMIX, Local0) + + If (And (Local0, 0x01)) + { Notify (\_SB_.SMIS, 0x21)} + + If (And (Local0, 0x02)) + { Notify (\_SB_.SMIS, 0x22)} + + If (And (Local0, 0x04)) + { Notify (\_SB_.SMIS, 0x24)} + + If (And (Local0, 0x08)) + { Notify (\_SB_.SMIS, 0x28)} + + } // End Method EVNT + + Device (SMIS) + { + Method (BINK) + { + Store (0, Local0) // Zero out Local0 + + If (LNotEqual (SMID, 0xD)) + { Or (0x80, Local0, Local0)} + + If (LNotEqual (SMIC, 0xC)) + { Or (0x40, Local0, Local0)} + + If (LNotEqual (BYTE, 0)) + { Or (0x20, Local0, Local0)} + + If (LNotEqual (WRD, 0)) + { Or (0x10, Local0, Local0)} + + If (LNotEqual (LST2, 0)) + { Or (0x8, Local0, Local0)} + + If (LNotEqual (BI3T, 0x7)) + { Or (0x4, Local0, Local0)} + + If (LNotEqual (BI2T, 0x3)) + { Or (0x2, Local0, Local0)} + + If (LNotEqual (BI1T, 0)) + { Or (0x1, Local0, Local0)} + + Return (Local0) + } // End Method BINK + + Method (TEST) + { + Store ("++++++++ SmiShare Test", Debug) + + // Expect EVNT to generate Notify value we just previously + // stored in BYTE + Store (0x20, BYTE) + EVNT () + Store (0x21, BYTE) + EVNT () + Store (0x22, BYTE) + EVNT () + Store (0x23, BYTE) + EVNT () + + Return (0) // pass + } // End Method TEST + } // Device SMIS + + Device(CNDT) + { + Method(TEST) + { + If (ECOK) + { + return("Broken") + } + Else + { + return("Works") + } + } + + Method(ECOK) + { + Return(0x0) + } + } + + } // _SB system bus + + +/* Test a very big buffer */ + + Name(WQAB, Buffer(6756) + { + 0x46,0x4F,0x4D,0x42,0x01,0x00,0x00,0x00, + 0x54,0x1A,0x00,0x00,0xBA,0xAD,0x00,0x00, + 0x44,0x53,0x00,0x01,0x1A,0x7D,0xDA,0x54, + 0x98,0xBD,0x92,0x00,0x01,0x06,0x18,0x42, + 0x10,0x47,0x10,0x92,0x46,0x62,0x02,0x89, + 0x80,0x90,0x18,0x18,0x14,0x81,0x85,0x00, + 0x49,0x02,0x88,0xC4,0x41,0xE1,0x20,0xD4, + 0x9F,0x40,0x7E,0x05,0x20,0x74,0x28,0x40, + 0xA6,0x00,0x83,0x02,0x9C,0x22,0x88,0xA0, + 0x57,0x01,0x36,0x05,0x98,0x14,0x60,0x51, + 0x80,0x76,0x01,0x96,0x05,0xE8,0x16,0x20, + 0x1D,0x96,0x88,0x04,0x47,0x89,0x01,0x47, + 0xE9,0xC4,0x16,0x6E,0xD8,0xE0,0x85,0xA2, + 0x68,0x06,0x51,0x12,0x94,0x8B,0x20,0x5D, + 0x10,0x52,0x2E,0xC0,0x37,0x82,0x06,0x10, + 0xA5,0x77,0x01,0xB6,0x05,0x98,0x86,0x27, + 0xD2,0x20,0xE4,0x60,0x08,0x54,0xCE,0x80, + 0x20,0x69,0x44,0x21,0x1E,0xA7,0x44,0x08, + 0x0A,0x84,0x90,0xD4,0xF1,0xA0,0xA0,0x71, + 0x88,0xAD,0xCE,0x46,0x93,0xA9,0x74,0x7E, + 0x48,0x82,0x70,0xC6,0x2A,0x7E,0x3A,0x9A, + 0xD0,0xD9,0x9C,0x60,0xE7,0x18,0x72,0x3C, + 0x48,0xF4,0x20,0xB8,0x00,0x0F,0x1C,0x2C, + 0x34,0x84,0x22,0x6B,0x80,0xC1,0x8C,0xDD, + 0x63,0xB1,0x0B,0x4E,0x0A,0xEC,0x61,0xB3, + 0x01,0x19,0xA2,0x24,0x38,0xD4,0x11,0xC0, + 0x12,0x05,0x98,0x1F,0x87,0x0C,0x0F,0x95, + 0x8C,0x25,0x24,0x1B,0xAB,0x87,0xC2,0xA5, + 0x40,0x68,0x6C,0x27,0xED,0x19,0x45,0x2C, + 0x79,0x4A,0x82,0x49,0xE0,0x51,0x44,0x36, + 0x1A,0x27,0x28,0x1B,0x1A,0x25,0x03,0x42, + 0x9E,0x05,0x58,0x07,0x26,0x04,0x76,0x2F, + 0xC0,0x9A,0x00,0x73,0xB3,0x90,0xB1,0xB9, + 0xE8,0xFF,0x0F,0x71,0xB0,0x31,0xDA,0x9A, + 0xAE,0x90,0xC2,0xC4,0x88,0x12,0x2C,0x5E, + 0xC5,0xC3,0x10,0xCA,0x93,0x42,0xA8,0x48, + 0x95,0xA1,0x68,0xB4,0x51,0x2A,0x14,0xE0, + 0x4C,0x80,0x30,0x5C,0x1D,0x03,0x82,0x46, + 0x88,0x15,0x29,0x56,0xFB,0x83,0x20,0xF1, + 0x2D,0x40,0x54,0x01,0xA2,0x48,0xA3,0x41, + 0x9D,0x03,0x3C,0x5C,0x0F,0xF5,0xF0,0x3D, + 0xF6,0x93,0x0C,0x72,0x90,0x67,0xF1,0xA8, + 0x70,0x9C,0x06,0x49,0xE0,0x0B,0x80,0x4F, + 0x08,0x1E,0x38,0xDE,0x35,0xA0,0x66,0x7C, + 0xBC,0x4C,0x10,0x1C,0x6A,0x88,0x1E,0x68, + 0xB8,0x13,0x38,0x44,0x06,0xE8,0x49,0x3D, + 0x52,0x60,0x07,0x77,0x32,0xEF,0x01,0xAF, + 0x0A,0xCD,0x5E,0x12,0x08,0xC1,0xF1,0xF8, + 0x7E,0xC0,0x26,0x9C,0xC0,0xF2,0x07,0x81, + 0x1A,0x99,0xA1,0x3D,0xCA,0xD3,0x8A,0x19, + 0xF2,0x31,0xC1,0x04,0x16,0x0B,0x21,0x05, + 0x10,0x1A,0x0F,0xF8,0x6F,0x00,0x8F,0x17, + 0xBE,0x12,0xC4,0xF6,0x80,0x12,0x0C,0x0B, + 0x21,0x23,0xAB,0xF0,0x78,0xE8,0x28,0x7C, + 0x95,0x38,0x9C,0xD3,0x8A,0x67,0x82,0xE1, + 0x20,0xF4,0x05,0x90,0x00,0x51,0xE7,0x0C, + 0xD4,0x61,0xC1,0xE7,0x04,0x76,0x33,0x38, + 0x83,0x47,0x00,0x8F,0xE4,0x84,0xFC,0x2B, + 0xF1,0xC0,0xE0,0x03,0xE2,0xEF,0x1F,0xA7, + 0xEC,0x11,0x9C,0xA9,0x01,0x7D,0x1C,0xF0, + 0xFF,0x7F,0x28,0x7C,0x88,0x1E,0xDF,0x29, + 0x1F,0xAF,0x4F,0x17,0x96,0x35,0x4E,0xE8, + 0x77,0x08,0x9F,0x38,0x7C,0x64,0x71,0x44, + 0x08,0x39,0x39,0x05,0xA0,0x81,0x4F,0xF7, + 0xEC,0x22,0x9C,0xAE,0x27,0xE5,0x40,0xC3, + 0xA0,0xE3,0x04,0xC7,0x79,0x00,0x1C,0xE3, + 0x84,0x7F,0x2E,0x80,0x3F,0x40,0x7E,0xCA, + 0x78,0xC5,0x48,0xE0,0x98,0x23,0x44,0x9F, + 0x6B,0x3C,0x42,0x2C,0xFC,0x53,0x45,0xE1, + 0x03,0x21,0x63,0x04,0x17,0xA0,0xC7,0x08, + 0x7C,0x03,0x8E,0x11,0x7D,0x94,0xE0,0xEA, + 0x0F,0x1A,0x74,0x80,0xB8,0xFF,0xFF,0x00, + 0xE1,0x83,0x7A,0x80,0xC0,0x37,0xFA,0xD1, + 0x03,0x3D,0x2E,0x8B,0x3E,0x0F,0xC8,0xF8, + 0x89,0x46,0xF3,0xE2,0xA7,0x03,0x7E,0xF8, + 0x00,0x0F,0xA8,0x87,0x84,0x03,0xC5,0x4C, + 0x9B,0x83,0x3E,0xBB,0x1C,0x3A,0x76,0xB8, + 0xE0,0x3F,0x81,0x80,0x4B,0xDE,0x21,0x0C, + 0x14,0x23,0xC6,0x9F,0x83,0x7C,0x0A,0x03, + 0xFF,0xFF,0xFF,0x14,0x06,0xFE,0xE1,0xF0, + 0x20,0x4F,0x07,0x9F,0xB6,0xA8,0x74,0x18, + 0xD4,0x81,0x0B,0xB0,0x32,0x89,0x08,0xCF, + 0x12,0xB5,0x41,0xE8,0xD4,0xF0,0x36,0xF1, + 0xB6,0xE5,0x5B,0x40,0x9C,0xD3,0xEC,0xED, + 0xC0,0x45,0x30,0x22,0xD4,0x0C,0x45,0x4E, + 0x5A,0x11,0x63,0x44,0x79,0xDC,0x32,0xCA, + 0xDB,0xD6,0x0B,0x40,0xBC,0x13,0x7B,0xDE, + 0x32,0x46,0xF0,0xC8,0x0F,0x5C,0x2C,0xC6, + 0xEA,0xF5,0x5F,0xF3,0x81,0x0B,0x70,0xF6, + 0xFF,0x3F,0x70,0x01,0x1C,0x0A,0x7A,0x18, + 0x42,0x0F,0xC3,0x53,0x39,0x97,0x87,0xC8, + 0x53,0x89,0x18,0x35,0x4C,0xD4,0x67,0x28, + 0xDF,0x2D,0x7C,0x20,0x02,0xDF,0x99,0x0B, + 0xF8,0xFD,0xFF,0x0F,0x44,0x70,0x8E,0x29, + 0xB8,0x33,0x0D,0x78,0x7C,0xCE,0x40,0x20, + 0xA7,0xE2,0x43,0x0D,0x60,0x41,0xF4,0x13, + 0xC2,0x27,0x1A,0x2A,0x13,0x06,0x75,0xA8, + 0x01,0xAC,0x5C,0x61,0x9E,0x46,0xCF,0xF9, + 0x59,0xC6,0xA7,0x1A,0x1F,0x4A,0x8D,0x63, + 0x88,0x97,0x99,0x87,0x1A,0x1F,0x0B,0x5E, + 0x49,0x7D,0xA8,0x31,0x54,0x9C,0x87,0x1A, + 0x0F,0x37,0x50,0xD4,0x37,0x9B,0x67,0x1B, + 0xA3,0xC7,0xF7,0x0D,0xD5,0x10,0x0F,0x35, + 0x4C,0xF2,0x4A,0x35,0x16,0x1F,0x6A,0xC0, + 0xF1,0xFF,0x3F,0xD4,0x00,0xFC,0xFF,0xFF, + 0x1F,0x6A,0x00,0x47,0x47,0x03,0x38,0x47, + 0x46,0xDC,0xD1,0x00,0x5C,0x87,0x52,0xE0, + 0x70,0x34,0x00,0x1E,0x47,0x21,0x30,0x5F, + 0x68,0x7C,0x14,0x02,0x16,0xFF,0xFF,0xA3, + 0x10,0xF8,0x65,0x9F,0x83,0x50,0x42,0x8F, + 0x42,0x80,0xA0,0xDB,0xCF,0x53,0xC4,0xB3, + 0x8F,0x2F,0x3F,0x0F,0x04,0x11,0x5E,0xF3, + 0x7D,0x0A,0xF2,0x21,0xDF,0x47,0x21,0x06, + 0x63,0x28,0x5F,0x83,0x7C,0x14,0x62,0x50, + 0xAF,0x41,0xBE,0xEF,0x1B,0xE4,0xF1,0x22, + 0x48,0xEC,0x67,0x02,0x1F,0x85,0x98,0xE8, + 0xA3,0x10,0xA0,0xF0,0xFF,0x7F,0x14,0x02, + 0xF8,0xFF,0xFF,0x3F,0x0A,0x01,0xCE,0x02, + 0x1C,0x0D,0x40,0x37,0xAD,0x47,0x21,0xF0, + 0xDE,0x59,0x4E,0xFB,0x04,0x7C,0x16,0x02, + 0xCC,0xFE,0xFF,0xCF,0x42,0xC0,0xEC,0x28, + 0x74,0x14,0x67,0xF9,0x2A,0xF4,0x04,0xF0, + 0x02,0x10,0x23,0xCC,0x3B,0xD0,0x4B,0x26, + 0xBB,0x8B,0x1B,0xE7,0xC9,0xE5,0x2C,0x9E, + 0xC4,0x7D,0x09,0xF2,0x81,0xE2,0x59,0xC8, + 0x50,0xA7,0x1B,0xF4,0x8D,0xDC,0x03,0x8B, + 0x19,0x3F,0xC4,0xF3,0x90,0x21,0x9E,0x85, + 0x00,0x76,0xFD,0xFF,0xCF,0x42,0x00,0xFF, + 0xFF,0xFF,0x47,0x03,0xF8,0x2F,0x00,0x9F, + 0x85,0x80,0xE7,0x09,0xE0,0x41,0xDB,0x67, + 0x21,0x80,0x33,0x87,0xCB,0xF3,0x7F,0x05, + 0x3A,0x96,0xF7,0x08,0xCF,0xFA,0x24,0x5F, + 0x2F,0x3D,0xD3,0x87,0x82,0x67,0x21,0x86, + 0x75,0x18,0x3E,0x0B,0x31,0x88,0x17,0x4D, + 0x43,0xBC,0x70,0xFA,0x30,0xE0,0xFF,0x3F, + 0x5E,0xE0,0x57,0x4E,0x03,0x05,0x09,0xF4, + 0x2C,0x04,0x30,0xFE,0xFF,0x7F,0x16,0x02, + 0xC8,0xB8,0x46,0x9D,0x85,0x80,0xE5,0x6D, + 0xE5,0x19,0xDB,0xA7,0x95,0x04,0xFF,0xFF, + 0x67,0x21,0xC0,0x41,0x2E,0x23,0x07,0x21, + 0x4C,0xC4,0x87,0x83,0x8F,0x99,0x80,0x9E, + 0x29,0xBE,0xB8,0x1B,0xE3,0x09,0xE0,0x45, + 0xE2,0x31,0x93,0x1D,0x35,0x0D,0xF3,0x2C, + 0x64,0xBC,0xB3,0x78,0x0D,0x78,0x82,0xF7, + 0xE4,0x9F,0x85,0x18,0xD8,0x61,0x05,0x7B, + 0x14,0x32,0xA8,0xC1,0x63,0x87,0x08,0x13, + 0xE8,0x59,0x88,0xC5,0x7D,0xAE,0xE8,0x3C, + 0xE1,0xB3,0x10,0xF0,0xFE,0xFF,0x9F,0x25, + 0xE0,0x5E,0x0D,0x9E,0x85,0x00,0x13,0x87, + 0x0D,0x9F,0x35,0xC0,0x33,0x7C,0x8F,0xEA, + 0x1C,0x1E,0x8F,0x81,0x7F,0x56,0x1D,0xE7, + 0x04,0x96,0x7B,0xD1,0xB2,0x71,0xA0,0xA1, + 0x23,0xB2,0x3A,0x20,0x8D,0x0D,0x73,0x29, + 0x89,0x7C,0x72,0x6C,0xD4,0x56,0x04,0xA7, + 0x33,0x93,0x4F,0x00,0xD6,0x42,0x21,0x05, + 0x34,0x1A,0x8B,0xE1,0x9D,0xF9,0xE8,0x44, + 0x41,0x0C,0xE8,0xE3,0x90,0x6D,0x1C,0x0A, + 0x50,0x7B,0xD1,0x14,0xC8,0x39,0x07,0xA3, + 0x7F,0x76,0x74,0x36,0xBE,0x13,0x70,0x0D, + 0x10,0x3A,0x25,0x18,0xDA,0x6A,0x04,0xFC, + 0xFF,0x67,0x89,0x01,0x33,0xFE,0x53,0x8C, + 0x09,0x7C,0x8E,0xC1,0x1F,0x0C,0xF0,0x03, + 0x7F,0x31,0xA8,0xFA,0x5E,0xA0,0xFB,0x82, + 0xD5,0xDD,0x64,0x20,0xCC,0xC8,0x04,0xF5, + 0x9D,0x0E,0x40,0x01,0xE4,0x0B,0x81,0xCF, + 0x51,0x0F,0x05,0x6C,0x22,0x21,0xC2,0x44, + 0x33,0x3A,0x62,0xC2,0xA8,0xE8,0x13,0xA6, + 0x20,0x9E,0xB0,0x63,0x4D,0x18,0x3D,0x13, + 0x5F,0x74,0xD8,0x88,0x31,0x21,0xAE,0x1E, + 0xD0,0x26,0x18,0xD4,0x97,0x22,0x58,0x43, + 0xE6,0x63,0xF1,0x05,0x02,0x37,0x65,0x30, + 0xCE,0x89,0x5D,0x13,0x7C,0xD9,0xC1,0xCD, + 0x19,0x8C,0xF0,0x98,0xBB,0x18,0xBF,0x3A, + 0x79,0x74,0xFC,0xA0,0xE0,0x1B,0x0E,0xC3, + 0x7E,0x32,0xF3,0x8C,0xDE,0xCB,0x7C,0x8D, + 0xC3,0xC0,0x7A,0xBC,0x1C,0xD6,0x68,0x61, + 0x0F,0xED,0x3D,0xC4,0xFF,0xFF,0x43,0x8C, + 0xCF,0x13,0xC6,0x08,0xEB,0xDB,0x0B,0x38, + 0xEE,0x59,0xF0,0xEF,0x1A,0xE0,0xB9,0x84, + 0xF8,0xAE,0x01,0x30,0xF0,0xFF,0x7F,0xD7, + 0x00,0x4E,0xD7,0x04,0xDF,0x35,0x80,0xF7, + 0xD0,0x7D,0xD7,0x00,0xAE,0xD9,0xEF,0x1A, + 0xA8,0x63,0x80,0x15,0xDE,0x35,0xA0,0x5D, + 0xD9,0xDE,0xD7,0x9E,0xB0,0xAC,0xE9,0xB2, + 0x81,0x52,0x73,0xD9,0x00,0x14,0xFC,0xFF, + 0x2F,0x1B,0x80,0x01,0x29,0x13,0x46,0x85, + 0x9F,0x30,0x05,0xF1,0x84,0x1D,0xEC,0xB2, + 0x01,0x8A,0x18,0x97,0x0D,0xD0,0x8F,0xED, + 0x65,0x03,0x18,0xDC,0x13,0xF8,0x6D,0x03, + 0x78,0x43,0xFA,0xB6,0x01,0xD6,0xFF,0xFF, + 0x6D,0x03,0xAC,0xF9,0x6F,0x1B,0x28,0x0E, + 0xAB,0xBC,0x6D,0x40,0x3C,0xC9,0x33,0x02, + 0xAB,0xBA,0x6E,0xA0,0xF4,0x5C,0x37,0x00, + 0x12,0x88,0x99,0x30,0x2A,0xFE,0x84,0x29, + 0x88,0x27,0xEC,0x68,0xD7,0x0D,0x50,0x04, + 0xB9,0x6E,0x80,0x7E,0x5E,0x09,0xFE,0xFF, + 0xAF,0x1B,0xC0,0xE0,0xA2,0x80,0xB9,0x6F, + 0x00,0x6F,0x58,0x7E,0xDF,0x00,0x7C,0xDC, + 0xC4,0x31,0xF7,0x0D,0xC0,0xCC,0xFF,0xFF, + 0xBE,0x01,0xB0,0xE7,0xA2,0x80,0xBB,0x6F, + 0x00,0xEF,0x8B,0xB4,0xEF,0x1B,0x60,0xFE, + 0xFF,0xDF,0x37,0xC0,0x28,0x6D,0xFD,0x1E, + 0x1C,0x3D,0x21,0x78,0x7C,0xB8,0xFB,0xA5, + 0xC7,0xE7,0xBB,0x39,0x38,0x06,0x79,0x8C, + 0x87,0x76,0xC0,0xAF,0xEF,0x9E,0x98,0xEF, + 0xE6,0xC0,0xFF,0x4C,0x70,0x3C,0x18,0x68, + 0x1C,0x62,0xAB,0x97,0x06,0x72,0x34,0x38, + 0x3F,0xDC,0x19,0x81,0x61,0x15,0x7F,0xF2, + 0x47,0x38,0xC7,0xD0,0xD9,0xE1,0x20,0xB1, + 0x83,0xE0,0xC1,0x56,0x6D,0x02,0x85,0x86, + 0x50,0x14,0x18,0x14,0x8B,0x0F,0x18,0xF8, + 0x61,0xB3,0xB3,0x00,0x93,0x04,0x87,0x3A, + 0x02,0xF8,0x3E,0xD1,0xFC,0x38,0x74,0x37, + 0x38,0x54,0x8F,0xE5,0xA1,0x80,0x9E,0x01, + 0x71,0xC7,0x0C,0x32,0x69,0xCF,0x28,0xE2, + 0x53,0xC2,0x29,0x85,0x49,0xE0,0xF3,0x03, + 0x43,0xE3,0x04,0xAF,0x0D,0xA1,0xF9,0xFF, + 0xFF,0xA4,0xC0,0x3C,0xDF,0x31,0x04,0x6C, + 0x02,0xBB,0xBF,0x64,0xC8,0xDA,0xC0,0x75, + 0x4B,0x32,0x44,0x6F,0x38,0xB2,0x85,0xA2, + 0xE9,0x44,0x79,0xDF,0x88,0x62,0x67,0x08, + 0xC2,0x88,0x12,0x2C,0xC8,0xA3,0x42,0xAC, + 0x28,0x2F,0x05,0x46,0x88,0x18,0xE2,0x95, + 0x23,0xD0,0x09,0x87,0x0F,0xF2,0xD8,0x14, + 0xA7,0xFD,0x41,0x90,0x58,0x4F,0x02,0x8D, + 0xC5,0x91,0x46,0x83,0x3A,0x07,0x78,0xB8, + 0x3E,0xC4,0x78,0xF8,0x0F,0x21,0x06,0x39, + 0xC8,0x73,0x7B,0x54,0x38,0x4E,0x5F,0x25, + 0x4C,0xF0,0x02,0xE0,0x83,0x0A,0x1C,0xD7, + 0x80,0x9A,0xF1,0x33,0x06,0x58,0x8E,0xE3, + 0x3E,0xA9,0xC0,0x1D,0x8F,0xEF,0x07,0x6C, + 0xC2,0x09,0x2C,0x7F,0x10,0xA8,0xE3,0x0C, + 0x9F,0xE7,0x0B,0x8B,0x21,0x1F,0x13,0x4C, + 0x60,0xB1,0x27,0x1B,0x3A,0x1E,0xF0,0xDF, + 0x63,0x1E,0x2F,0x7C,0x32,0xF1,0x7C,0x4D, + 0x30,0x22,0x84,0x9C,0x8C,0x07,0x7D,0x87, + 0xC0,0x5C,0x6F,0xD8,0xB9,0x85,0x8B,0x3A, + 0x68,0xA0,0x4E,0x0B,0x3E,0x28,0xB0,0x9B, + 0x11,0xE6,0xB8,0xCE,0xCF,0x2A,0x60,0xF8, + 0xFF,0x9F,0x55,0x60,0x8F,0x10,0xFE,0xED, + 0xC1,0xF3,0xF2,0x95,0xE1,0xD5,0x21,0x81, + 0x43,0x8E,0x10,0x3D,0x2E,0x8F,0x10,0x73, + 0x3E,0xC2,0x0C,0x11,0x5C,0x67,0x01,0x70, + 0x0C,0x11,0xF8,0x1C,0x70,0xC0,0x71,0x69, + 0xE2,0x03,0xF5,0x01,0x07,0x70,0x70,0x4D, + 0xC3,0x1D,0x70,0xC0,0x71,0x16,0x60,0xFF, + 0xFF,0xC3,0x0D,0x2C,0x49,0x26,0x0E,0x23, + 0x18,0x11,0x30,0x28,0x02,0x02,0xA4,0xB3, + 0x80,0x0F,0x29,0x00,0x1F,0xAE,0x0C,0x0F, + 0x29,0xD8,0x93,0x86,0x07,0x8E,0x1B,0x85, + 0x07,0x8D,0x0B,0x30,0x68,0x7A,0xE2,0x80, + 0x7F,0x4C,0xF0,0x19,0x05,0x1C,0xE3,0x06, + 0xDF,0x2A,0x0C,0xFC,0xFF,0x3F,0x30,0xCC, + 0xE1,0xC2,0x63,0x39,0x8A,0xA0,0x07,0x1E, + 0xD4,0xF7,0x8C,0x33,0xF7,0x24,0x8F,0xD1, + 0x51,0x0F,0x27,0xF4,0xE4,0x85,0x3B,0x57, + 0xF9,0x0A,0x71,0x14,0x18,0xB8,0x77,0x29, + 0x8F,0xCF,0x17,0x2B,0xC3,0x63,0x46,0xFB, + 0x1E,0x72,0xD6,0x11,0x02,0xE2,0x2F,0x75, + 0x6C,0xC0,0x60,0x39,0x18,0x00,0x87,0x01, + 0xE3,0x13,0x0D,0x58,0x67,0x1B,0x3C,0xF4, + 0x69,0x31,0xC4,0xE3,0x0B,0xFB,0x56,0x61, + 0x82,0xEA,0x41,0x75,0x12,0xF4,0xD0,0xC0, + 0x01,0xE8,0xA1,0xC1,0x3F,0xB9,0x90,0xFB, + 0x2B,0x1D,0x82,0xB5,0xE2,0x69,0xDE,0x47, + 0x1E,0xF3,0xDC,0xA2,0xBC,0x0D,0x3C,0x07, + 0xF0,0xD3,0x82,0x87,0xE3,0x63,0x81,0xC7, + 0xE9,0x4B,0x58,0x82,0xF7,0x1A,0x9F,0x6C, + 0x1E,0x5C,0x58,0xB2,0x21,0xA0,0x06,0xEB, + 0x21,0x60,0xA6,0x9A,0xC0,0x49,0x46,0x80, + 0xCA,0x00,0xA1,0x1B,0xCB,0xE9,0x3E,0x8B, + 0x84,0x38,0xCD,0x47,0x99,0xC7,0x02,0x8F, + 0xF5,0xC1,0xC0,0xFF,0x7F,0xCD,0x23,0xD4, + 0x7D,0xCD,0x33,0x7B,0x3A,0xC0,0xAC,0x22, + 0xDC,0x7B,0xCE,0x1B,0x86,0xD1,0x9E,0x2D, + 0x7C,0xCD,0x78,0xD6,0x34,0x42,0x38,0x76, + 0x83,0xF3,0x48,0x8C,0xF0,0x82,0xC0,0x4E, + 0x0C,0x0F,0x30,0xC6,0x39,0x79,0xC3,0xFA, + 0xC2,0xCB,0x40,0x83,0x19,0xDB,0x97,0x01, + 0x36,0x2A,0xDF,0x88,0xC0,0x97,0xFC,0x62, + 0x00,0x65,0x16,0xBE,0x9E,0xF8,0xA0,0xC4, + 0x2E,0x06,0x2C,0xE5,0xC5,0x00,0x54,0x37, + 0x0C,0x5F,0x0C,0xE0,0x5F,0x89,0x5E,0x0C, + 0xC0,0x70,0x71,0xF2,0x3D,0xC0,0x1E,0xEE, + 0xA3,0x74,0x9C,0xBE,0xFD,0xBD,0x19,0xF8, + 0x6C,0xC0,0x60,0x3C,0xC3,0x30,0xC6,0x08, + 0xE3,0x51,0x86,0x31,0xC1,0xDC,0xB7,0x03, + 0xE8,0x39,0x87,0x81,0x4A,0x78,0x3B,0x80, + 0x72,0x0E,0xE8,0xF2,0x68,0x42,0x4F,0x01, + 0x4F,0x07,0x3E,0x29,0x1A,0xA2,0xAF,0xB1, + 0x0A,0x26,0x50,0xC4,0x07,0x0D,0x3E,0xB5, + 0x28,0x3E,0x15,0x78,0x2D,0xCF,0x4E,0xE1, + 0xE2,0x9C,0x89,0xA7,0x6A,0x38,0x03,0xBD, + 0xE6,0x86,0x63,0xFF,0x7F,0x38,0xFC,0xA9, + 0xE0,0x35,0x80,0x1D,0x24,0x3D,0x2D,0x23, + 0xC2,0x38,0xA4,0x3C,0x32,0xF8,0xB6,0x18, + 0xC7,0x90,0x0F,0x91,0xBE,0x13,0x18,0xF2, + 0x21,0xEF,0x79,0xC7,0xC0,0xAF,0x08,0x71, + 0x9E,0xB2,0x7C,0x67,0xF0,0x65,0x01,0x7C, + 0x91,0x2E,0x0B,0x68,0x68,0x9F,0x64,0x7C, + 0x41,0x30,0xEC,0x89,0xB3,0x00,0x77,0x05, + 0x50,0x81,0xFA,0xAE,0x00,0xFF,0x42,0xF0, + 0xAE,0x00,0x86,0x79,0xF9,0x56,0xC0,0x35, + 0x1D,0x4A,0xD0,0x67,0x12,0x5F,0x17,0x70, + 0x53,0x64,0xA9,0x8E,0x0A,0xD0,0x53,0x4C, + 0x02,0x75,0x47,0xF7,0x51,0x01,0xC6,0x4D, + 0xD9,0x07,0x54,0x76,0x5A,0x60,0x67,0x21, + 0x76,0x1D,0xC1,0x5D,0x49,0x18,0xCA,0xB3, + 0x81,0x2F,0x59,0xFC,0x70,0x00,0x03,0xDC, + 0xB3,0x38,0xC4,0x08,0xB1,0xD9,0x81,0xEB, + 0x75,0xD2,0x70,0x2F,0x44,0xEC,0xFF,0x7F, + 0x32,0x00,0xE3,0x51,0x1B,0x1C,0x27,0x9D, + 0xF0,0x91,0x9E,0x59,0xF8,0x49,0x19,0x30, + 0x71,0xF2,0x03,0xE3,0xC9,0x1A,0xC6,0x00, + 0xB8,0xBC,0x57,0x95,0x81,0xFC,0x43,0x90, + 0x20,0x18,0xD4,0x29,0x19,0x38,0x1C,0xC5, + 0x70,0xA7,0x64,0x78,0x50,0xF8,0xC3,0x00, + 0xE6,0x46,0xE8,0x7B,0x82,0xA1,0xDE,0x93, + 0x0E,0xE3,0x91,0xD0,0x04,0x3E,0x2D,0xC3, + 0xFA,0xFF,0x9F,0x96,0x81,0xD5,0xB1,0xDD, + 0x43,0xF6,0x59,0x01,0x77,0x76,0x80,0x3B, + 0x3D,0x7E,0x7A,0x00,0x9C,0x00,0x3D,0x3D, + 0x80,0xED,0xBC,0x01,0xF7,0x40,0x80,0x38, + 0xFE,0xA3,0x82,0x5F,0x59,0x28,0x1C,0x3F, + 0xB6,0xF3,0x63,0x09,0xEE,0x70,0xE0,0x23, + 0x83,0x0F,0x90,0xB8,0xA1,0xF8,0x50,0x81, + 0x3C,0x0B,0x80,0x62,0xF4,0x6C,0x04,0xEC, + 0x06,0xF3,0xD2,0x12,0xE5,0xFF,0xFF,0xDE, + 0xC0,0x4E,0x29,0xB8,0x83,0x00,0xF8,0x8E, + 0x01,0xE0,0x1D,0x0C,0x97,0x35,0x66,0x94, + 0x10,0x18,0x8D,0x19,0x77,0x08,0xE1,0x27, + 0x02,0xDC,0x98,0x3D,0x6E,0x8F,0x19,0x77, + 0x9C,0xE5,0xA3,0x7A,0xCA,0x08,0xE5,0x03, + 0x07,0x3B,0x67,0xBC,0x11,0xF0,0xA1,0x03, + 0x8F,0x03,0x0C,0xEE,0x48,0x01,0xC6,0xCB, + 0x01,0x1B,0x3B,0xB8,0x83,0x90,0x53,0x20, + 0x4B,0x87,0xD1,0xD8,0x71,0xB2,0x81,0x74, + 0x8C,0xF1,0x21,0xD7,0x63,0xC7,0x0D,0xD6, + 0x63,0xC7,0x1D,0x5F,0xB0,0xFF,0xFF,0xE3, + 0x0B,0x18,0xC6,0xC0,0xC5,0x0F,0x03,0x7D, + 0xF3,0xF3,0xE8,0x0C,0xEE,0x61,0xFB,0x04, + 0x13,0xE3,0xF9,0x25,0xC4,0x23,0xCC,0x8B, + 0x4B,0x84,0xA3,0x08,0xF2,0xE6,0x12,0xE7, + 0xD5,0x20,0xCC,0x63,0x4B,0x94,0x10,0x11, + 0x0E,0x26,0xCE,0x13,0x8C,0x11,0x0E,0x3C, + 0x8A,0x21,0x22,0x9C,0x40,0x88,0x93,0x3E, + 0xD9,0x20,0xE1,0x63,0x84,0x8D,0xF6,0x04, + 0xC3,0xC7,0xC2,0xCF,0x2B,0x1E,0x3C,0x3F, + 0xAD,0xF9,0x2E,0xE8,0xC9,0x9C,0xE3,0x43, + 0x96,0xA7,0xF6,0x38,0xE9,0xC3,0x2C,0x6E, + 0x50,0x0F,0x8E,0xEC,0xAE,0xE3,0xE3,0x35, + 0xF6,0x14,0xE4,0x21,0xF0,0x13,0x81,0x2F, + 0x88,0x9E,0xAC,0xEF,0x7A,0xEC,0x5E,0x66, + 0x8C,0xEA,0xA7,0x80,0x3A,0xA6,0x9C,0xC1, + 0x2B,0x04,0xBB,0xE7,0xF9,0x90,0xED,0xBB, + 0x24,0x1B,0x05,0xEE,0x90,0xE0,0x33,0x12, + 0x3F,0x55,0x78,0x18,0x1E,0x05,0x8C,0x19, + 0xBC,0x23,0x1C,0x5A,0x88,0x03,0x7E,0xDF, + 0x65,0x43,0x8D,0x71,0x7A,0x3E,0x7F,0xB0, + 0x41,0xC0,0x87,0x3A,0x54,0x0F,0xF3,0xA8, + 0x5E,0x0A,0x19,0xCE,0xD9,0xC1,0x1D,0x04, + 0xF6,0xF8,0xE1,0x41,0xF0,0x9B,0x25,0x1F, + 0x04,0x3B,0xDF,0xBC,0xC1,0x19,0xE4,0xFF, + 0x7F,0x0C,0xB0,0xCF,0x54,0x3E,0x9A,0x20, + 0x8E,0x80,0xE8,0xF3,0x87,0xC7,0xF0,0x26, + 0xC7,0x87,0x83,0x3D,0x7A,0xE0,0x4E,0x22, + 0x70,0x8F,0x5D,0x07,0xED,0x6B,0x9C,0x2F, + 0x5A,0x30,0xEE,0x7B,0xCF,0x22,0xE0,0xC7, + 0x78,0x6C,0x01,0xC7,0xA1,0x04,0xDC,0xC1, + 0x8E,0x6B,0x1C,0x42,0x51,0x60,0x74,0x28, + 0xC1,0xC5,0x00,0x12,0x8C,0x63,0x9C,0xD1, + 0xD0,0x97,0x48,0x1F,0xD2,0xE0,0x0C,0x1A, + 0xF6,0x3C,0x9F,0x50,0xB8,0x3D,0x01,0x8A, + 0x4E,0x28,0x20,0xC3,0x7D,0x06,0xC1,0x9E, + 0x10,0xF8,0x19,0x84,0xFD,0xFF,0x0F,0x8E, + 0x1E,0xF7,0x7B,0xA3,0x4F,0x8D,0x6C,0xEE, + 0x0F,0x01,0x27,0x70,0xEE,0xEC,0xD4,0x8C, + 0x3B,0x33,0x60,0xCF,0x1F,0x1E,0x02,0x3F, + 0x17,0x78,0xF8,0x1E,0x02,0x7E,0xF0,0x0F, + 0xCC,0x06,0x07,0xE3,0x29,0xC2,0xD7,0x0E, + 0x0E,0xCE,0x4F,0x03,0x06,0xE7,0xAF,0x50, + 0x9F,0xE7,0x19,0x38,0xF6,0xD4,0xEB,0x7B, + 0x87,0xE7,0xEB,0x43,0x05,0xFE,0xA6,0xE7, + 0x43,0x05,0x38,0x0E,0x0F,0xFC,0xB0,0xC2, + 0x86,0xF0,0x28,0x80,0x3F,0xB5,0xF8,0xF8, + 0x17,0xE7,0x29,0x82,0xDD,0x46,0xB0,0x87, + 0x0B,0xC0,0x51,0xB4,0xB3,0x18,0x2A,0xCC, + 0x59,0x8C,0xFC,0xFF,0xCF,0x51,0xA8,0xB3, + 0x18,0x3D,0x5C,0x00,0x2E,0x04,0x1F,0x0F, + 0x40,0x73,0x10,0x78,0x5C,0xF0,0x85,0xE0, + 0x48,0x0E,0xE4,0xE9,0x00,0xF0,0x19,0x4A, + 0xC3,0xA1,0x09,0x13,0x03,0x06,0x75,0x3E, + 0xF0,0x09,0xC5,0xC7,0x0E,0x7E,0x36,0xF0, + 0x8D,0xDC,0x43,0xE5,0xA7,0x66,0x5F,0xF2, + 0x11,0xE0,0x02,0x75,0xA0,0x61,0xA0,0x46, + 0xE4,0x23,0xD2,0xFF,0xFF,0xB9,0x0D,0x1B, + 0x60,0x68,0xF4,0x1C,0x0E,0xE3,0x80,0xEB, + 0x73,0x38,0x76,0x40,0x3E,0x87,0xC3,0x3F, + 0x47,0xC3,0x1F,0x1B,0x3B,0xDD,0xF3,0x81, + 0xC1,0xBA,0x7E,0x63,0x06,0x06,0xB6,0x6F, + 0x91,0x07,0x06,0x1C,0x51,0xCF,0xC6,0x57, + 0x08,0x0F,0x0C,0x6C,0x80,0x1E,0x18,0xF0, + 0x89,0x05,0x21,0x27,0x03,0x43,0x9D,0x32, + 0x8C,0x1C,0xF3,0x89,0xC3,0xC3,0xF0,0xA1, + 0x22,0xEA,0x33,0xC0,0x23,0x1E,0x1B,0x1B, + 0xFB,0xFF,0x8F,0x0D,0x2C,0xC7,0x16,0x8F, + 0x0D,0xFC,0x47,0x78,0xFC,0xD8,0xE0,0x8C, + 0xE5,0xD1,0xC4,0x97,0x99,0x23,0x3B,0x8D, + 0x33,0x7B,0x0D,0xF1,0xD1,0xEE,0xF1,0xDB, + 0x63,0x03,0x97,0x85,0xB1,0x01,0xA5,0x90, + 0x63,0x43,0x1F,0x52,0x7C,0x0A,0xB0,0x71, + 0x54,0x32,0x0F,0x1F,0xAF,0x7C,0x62,0x38, + 0xBA,0x20,0x6F,0xE8,0xBE,0x5C,0xF8,0x48, + 0x63,0x30,0x5F,0x5A,0x7C,0x06,0xE5,0x43, + 0x04,0xD7,0x57,0xC5,0x43,0x04,0x3E,0xA1, + 0x86,0x88,0x1E,0xCF,0xFF,0xFF,0x11,0xCC, + 0x43,0x64,0x43,0x03,0xAF,0x87,0xA1,0x01, + 0xA5,0x98,0xC0,0x5E,0x85,0x87,0x46,0x4F, + 0x3F,0x3E,0x04,0x30,0x08,0xDF,0x06,0xD8, + 0x55,0xC0,0x57,0x21,0x83,0x24,0x18,0xE7, + 0x64,0x41,0x07,0x07,0x8E,0x21,0x79,0x70, + 0xF0,0x07,0xE3,0x21,0x70,0x60,0xCF,0xE0, + 0xB9,0xE8,0x31,0xD8,0xA7,0x1D,0x9F,0x4A, + 0xC0,0x77,0xE6,0x04,0xC7,0xE9,0x1D,0x7B, + 0x29,0xF0,0x08,0x1E,0xAD,0x3C,0x02,0x7E, + 0xB4,0x02,0x66,0xFF,0xFF,0xA3,0x15,0x30, + 0x09,0x7A,0xE6,0xA4,0x03,0x77,0x34,0x18, + 0xD4,0xD1,0x0A,0x5C,0x11,0xC0,0x75,0xDC, + 0xF0,0xD1,0x02,0xCE,0x50,0x0F,0xDA,0x07, + 0x65,0xCF,0xDA,0x97,0x21,0x76,0xB4,0x00, + 0x97,0x89,0x43,0x08,0xD0,0x04,0x3E,0x89, + 0x67,0xEF,0x43,0x03,0xB3,0x8A,0xA1,0x01, + 0xA5,0xA3,0x01,0xEE,0x44,0x81,0xFD,0xFF, + 0x9F,0x28,0x60,0xDE,0x30,0x70,0x07,0x0A, + 0xC0,0xCD,0xE9,0xDB,0xE3,0xE2,0xD0,0x38, + 0xC4,0xE7,0xA7,0x73,0xF6,0xD1,0xE8,0x4C, + 0x71,0x67,0x11,0x30,0x9C,0x7D,0x11,0x8F, + 0x18,0x03,0xF9,0x81,0x21,0x59,0x30,0x28, + 0x16,0x0F,0xC5,0x07,0x03,0x0E,0xEC,0x23, + 0x02,0x3B,0x17,0xB0,0x73,0xAD,0xE1,0xF8, + 0x59,0xC0,0xA7,0x84,0xB7,0xA6,0x17,0x7B, + 0x9F,0xD7,0x7D,0xD6,0x08,0xC9,0xCE,0xF4, + 0x3E,0x89,0xE2,0x0E,0xA2,0x70,0x4E,0x9F, + 0xE0,0x22,0xF0,0x65,0xDF,0xA3,0xE0,0xA7, + 0x07,0xCF,0xF1,0x8D,0xC1,0xA7,0x07,0xE6, + 0x7E,0xF8,0x9A,0xF1,0x33,0xC3,0xE3,0x43, + 0x88,0x27,0xE2,0xDA,0xA6,0x20,0x5B,0x18, + 0x42,0x09,0xF4,0xFF,0x8F,0x10,0xE5,0x6D, + 0x20,0xCA,0x29,0x44,0x88,0x12,0xA4,0xB1, + 0xC9,0x0B,0x35,0xCA,0xD9,0x45,0x6E,0x6D, + 0xF6,0x82,0x0B,0x14,0x2A,0x66,0x9C,0x28, + 0xEF,0x10,0xB1,0xDA,0x1F,0x04,0x91,0xF4, + 0x32,0xD0,0x71,0xC9,0x91,0x0E,0x7D,0xE8, + 0x61,0xFB,0x04,0x8C,0x3F,0x48,0xE2,0xAE, + 0x2A,0x3E,0x28,0xF8,0x00,0x80,0x77,0x09, + 0xA8,0x5B,0x9D,0xC7,0xED,0xF3,0x06,0xF8, + 0xAF,0x17,0x58,0x82,0xF2,0x07,0x81,0x1A, + 0x99,0xA1,0x3D,0xCC,0xB7,0x19,0x43,0xBE, + 0x07,0x1C,0x16,0x3B,0x27,0xF9,0xF0,0x08, + 0x1C,0x8E,0x01,0x4F,0x1B,0xBE,0x51,0x7B, + 0xBE,0x3E,0x62,0x01,0x8E,0xFE,0xFF,0x47, + 0x2C,0x30,0x9D,0xDF,0x7D,0x82,0x01,0xC7, + 0xCD,0x82,0x9F,0x61,0x00,0x67,0x40,0xCF, + 0x30,0x60,0x1F,0x2A,0x6E,0x08,0x5C,0xEE, + 0x8A,0x28,0x90,0x05,0xC2,0xA0,0x0E,0xFD, + 0xE4,0x08,0x42,0xCF,0x9C,0x70,0x86,0x72, + 0xB2,0xBD,0x5F,0x1D,0xC8,0x2D,0xC2,0x43, + 0x3D,0x8B,0xC7,0x04,0x76,0xDA,0x02,0x36, + 0xFF,0xFF,0xE3,0x29,0xB0,0x98,0xF7,0xD3, + 0x69,0x84,0x63,0x03,0xFB,0x71,0x0B,0x38, + 0x1D,0xCC,0xE0,0xDC,0x7F,0xD8,0x2D,0x1A, + 0x37,0x34,0xB0,0x0D,0xCC,0x43,0x03,0x3E, + 0x27,0x47,0x30,0x9E,0x98,0xF8,0x55,0xE2, + 0xE1,0x89,0x1F,0x43,0xC0,0xFA,0xFF,0x3F, + 0x99,0x01,0xF6,0x84,0x1E,0xCB,0x50,0xD2, + 0x4E,0x66,0x80,0xC0,0xFB,0xD8,0x3B,0xC3, + 0x4B,0x83,0xE7,0x74,0xD2,0xCF,0x62,0x3E, + 0x99,0x19,0x21,0x0A,0xBB,0x8F,0x19,0xAD, + 0x37,0x14,0xCD,0x3C,0xE8,0x3B,0x99,0x51, + 0x62,0x46,0x6A,0x0E,0x4C,0x48,0x11,0x0F, + 0x27,0x4A,0x88,0x60,0xAF,0x13,0x6F,0x67, + 0x4F,0x66,0x4C,0xD6,0xC9,0x0C,0x24,0xFF, + 0xFF,0x93,0x19,0x98,0x5C,0x9F,0xCC,0x80, + 0xCA,0x39,0x0A,0x7F,0x32,0x03,0x78,0x74, + 0xC0,0xC2,0x9D,0xCC,0xC0,0xF2,0xFF,0x3F, + 0xC4,0x00,0xCE,0xC7,0x0A,0x63,0x0C,0x3C, + 0xDA,0xC1,0x0C,0x15,0xE6,0x6C,0x86,0x0E, + 0x72,0x08,0xA1,0xC1,0x0E,0x21,0x50,0xE6, + 0x72,0xA0,0xA7,0xF0,0x9A,0xE0,0x73,0x14, + 0xD8,0x0F,0x67,0xC0,0xE1,0xD4,0x80,0x0F, + 0x74,0xE2,0x42,0x8F,0xC2,0x23,0x0E,0x58, + 0xFD,0xC0,0xC8,0xFF,0xFF,0x64,0x06,0x18, + 0x78,0x6A,0xF8,0x40,0x82,0x63,0x31,0xEA, + 0x1B,0xC4,0x21,0xBE,0x8D,0xF8,0xE8,0xFE, + 0x6A,0xE2,0x4B,0x00,0xE6,0x42,0xE2,0xD3, + 0x09,0xB3,0x70,0x38,0x03,0x5A,0x43,0x60, + 0x57,0x26,0xCF,0x9C,0x0F,0xE1,0x6C,0x3C, + 0x7A,0xDC,0xE9,0x04,0xDE,0x38,0x7C,0x3A, + 0x01,0x5E,0x07,0x0C,0xCC,0x0C,0xC2,0x3F, + 0x84,0xB0,0x21,0x9C,0xAA,0xC7,0x70,0xEE, + 0xAF,0x38,0x3E,0x9D,0x80,0xF3,0xFF,0x7F, + 0x62,0x03,0x0C,0x0A,0x7E,0x32,0xF8,0xB8, + 0x46,0x25,0xC2,0xA0,0x8E,0xE6,0x80,0x7B, + 0x98,0x27,0x36,0x26,0x6F,0xC5,0x1A,0x8B, + 0x4F,0x6C,0x30,0xFF,0xFF,0x27,0x36,0x80, + 0xD1,0x87,0x20,0xB0,0xFD,0xFF,0x0F,0x41, + 0x60,0x1C,0xA0,0x0F,0x41,0x80,0x9B,0xD3, + 0x09,0xEE,0xC4,0x07,0xB6,0x63,0x10,0x60, + 0x6D,0xE8,0x3E,0x06,0x81,0xF9,0xFF,0x3F, + 0x5A,0x98,0xA3,0xE0,0xC2,0x8E,0x7C,0x28, + 0x29,0xA7,0x3E,0xB4,0x0C,0x20,0x69,0x38, + 0xC9,0x01,0x9D,0xD3,0x3D,0x70,0x92,0x75, + 0xEA,0x40,0x8F,0xC7,0xA0,0xAF,0x1C,0xBE, + 0x12,0xF0,0x23,0x07,0x93,0x00,0xAA,0x41, + 0xFA,0xCC,0x07,0x9C,0x8E,0x1C,0xE0,0x38, + 0x26,0x05,0xC6,0xDE,0x0E,0xDE,0x22,0x3D, + 0x89,0xA7,0xA1,0xE3,0x0C,0x51,0x38,0x26, + 0x39,0x18,0x44,0x7A,0x95,0x62,0x03,0x7C, + 0xAB,0xF1,0xD9,0xC8,0x07,0x10,0x78,0xE3, + 0xF6,0xD8,0x61,0xFF,0xFF,0x0F,0x75,0xC0, + 0x01,0xE2,0xA4,0xF8,0x21,0xC3,0x98,0x67, + 0xC5,0x0F,0x75,0x80,0xF5,0x18,0x27,0x3A, + 0x94,0xF0,0x43,0x1D,0x20,0xE8,0xFF,0x7F, + 0xA8,0x03,0x86,0x38,0x6F,0x24,0xD1,0x1E, + 0xEA,0x98,0xE8,0x43,0x1D,0x40,0xC8,0xFF, + 0xFF,0xA1,0x0E,0x18,0x9E,0x87,0x00,0xAE, + 0x9C,0xEF,0xC0,0x7C,0x22,0x02,0xEF,0xFF, + 0xFF,0x7C,0x07,0xB8,0x1B,0x2D,0xCC,0x51, + 0x70,0x41,0xAF,0x0E,0x03,0x51,0x09,0x30, + 0x28,0x02,0xC7,0x5F,0x9B,0x60,0x1C,0xEA, + 0x7C,0x87,0x3E,0x2F,0x78,0xD8,0x4F,0x05, + 0x9E,0xC4,0xA9,0xFA,0x5A,0x70,0x14,0x4F, + 0x00,0x3E,0xE1,0x01,0xFF,0xA1,0xC1,0x9A, + 0x44,0xF1,0x43,0x03,0xF5,0x11,0xE4,0xFF, + 0x7F,0x68,0xC0,0x28,0xEA,0xF9,0x06,0x7D, + 0xCC,0xF2,0xD9,0x20,0xE6,0x0B,0x48,0x84, + 0x07,0x10,0x5F,0x1F,0xD8,0x71,0xD2,0x67, + 0xA0,0x40,0x51,0xDE,0x37,0xF8,0x09,0x07, + 0x5C,0x83,0xF3,0x09,0x07,0xBC,0x87,0x23, + 0x1F,0x4B,0xC0,0x77,0xD0,0x84,0x73,0x81, + 0xF1,0x8D,0x8D,0x9D,0x06,0xC0,0x76,0x00, + 0x06,0xDF,0x69,0x00,0x1C,0xC7,0x24,0x7E, + 0x3A,0x04,0x13,0xCC,0xC1,0xBC,0x34,0xFB, + 0xFF,0xEF,0xFD,0x94,0x43,0xCF,0x86,0x80, + 0x75,0x49,0x07,0x43,0x94,0x88,0xB3,0x21, + 0x20,0xFD,0xFF,0x7F,0x36,0xC4,0x20,0xC4, + 0x09,0xFC,0x12,0xD1,0xDC,0xD9,0x90,0xAE, + 0xD8,0x67,0x43,0x80,0xE1,0xFF,0xFF,0x23, + 0x00,0xF6,0x7C,0x04,0x38,0x3D,0x64,0x83, + 0xE7,0x14,0x08,0xE3,0xE4,0x03,0x38,0xFE, + 0xFF,0x8F,0x15,0xE6,0x18,0x78,0xEA,0x97, + 0x9B,0x8F,0x03,0x54,0xD4,0x2B,0xC2,0x30, + 0x94,0xC5,0x87,0x05,0x1F,0x11,0xF8,0x61, + 0xC1,0x23,0xA8,0x78,0x9C,0xF4,0x74,0xE3, + 0x33,0x21,0x3B,0x24,0x38,0xFC,0x20,0xE9, + 0x41,0x13,0x3C,0xE7,0x23,0x78,0xB7,0x1E, + 0x38,0xA7,0x02,0xC0,0x4D,0xAE,0x27,0xA3, + 0x4E,0x17,0x0E,0x70,0x8E,0x92,0x8D,0x63, + 0x08,0xE5,0x70,0xCC,0xB7,0x87,0xA6,0xC9, + 0x4E,0x56,0x30,0x63,0x41,0xEA,0x24,0xE0, + 0x01,0x38,0x10,0x8C,0xB4,0x93,0x68,0x34, + 0x86,0xB3,0x5A,0x18,0xC1,0x19,0xC4,0xC7, + 0x11,0xE7,0x3A,0x19,0xA1,0x3F,0x07,0x3E, + 0x15,0x61,0x82,0xDC,0x4B,0xE8,0xBC,0x7D, + 0x37,0xE0,0x57,0x61,0x8F,0xC5,0xFF,0x7F, + 0x60,0xDF,0x4E,0xC0,0x31,0x17,0xAB,0x01, + 0x45,0x0D,0xC0,0x68,0x98,0x53,0xC0,0x53, + 0x09,0xB8,0x82,0xCD,0x0D,0x7D,0x61,0xB1, + 0xD6,0xA9,0xE8,0x14,0xF4,0x3E,0x70,0x70, + 0xC0,0x63,0xF6,0x1E,0x1C,0x2C,0x34,0x0F, + 0x0E,0x6C,0xD9,0x06,0x87,0x56,0x72,0x17, + 0x21,0x87,0x0F,0xFC,0xEC,0x80,0x03,0xA0, + 0x67,0x07,0x0B,0xC9,0xB3,0x03,0x9B,0xBE, + 0xB3,0x08,0x28,0x70,0xFE,0xFF,0x11,0xDE, + 0x3B,0x7C,0x6E,0x79,0xF6,0x60,0x63,0x78, + 0x74,0x31,0x9A,0xD1,0xB9,0xA6,0xDB,0x04, + 0x4A,0xC5,0x6D,0x82,0x82,0xF8,0x06,0xE0, + 0x84,0x34,0xBA,0x75,0xE2,0x66,0x62,0xFC, + 0x47,0x0C,0x1F,0x11,0x0E,0xE9,0x6C,0x4D, + 0x30,0x0F,0xA4,0x9E,0x81,0xBE,0xB3,0xE1, + 0x67,0x1F,0xF2,0xC1,0xC5,0xD3,0xF0,0xF5, + 0x86,0xDC,0x3B,0xE8,0xB4,0x7D,0x66,0xC0, + 0x1C,0x74,0x7D,0x9D,0x7A,0x83,0x27,0x57, + 0x09,0xEA,0xE1,0x02,0x42,0x2F,0x34,0xBE, + 0xDC,0x25,0x78,0xE0,0xF4,0xE9,0xEE,0xBD, + 0x84,0x9D,0xF1,0x12,0xBC,0xE0,0x25,0x98, + 0x77,0x10,0xA8,0x51,0x79,0x10,0x98,0xAB, + 0x3C,0xCB,0x37,0x06,0x54,0xB2,0x8B,0x16, + 0x3D,0xC3,0xBC,0xC3,0xF8,0x92,0xE0,0xEB, + 0x87,0xCF,0x2D,0x5E,0xC0,0xEB,0x16,0x0C, + 0x82,0x67,0xA0,0x57,0x17,0xDF,0xD9,0x0D, + 0xFC,0x2A,0xF0,0x46,0x13,0x22,0x98,0x61, + 0x0F,0xFF,0xDD,0xDD,0xA8,0xBE,0xE9,0x18, + 0xEB,0x75,0xC4,0x23,0xE5,0xC7,0x96,0x03, + 0x8A,0xF4,0xF2,0xE6,0x09,0xF8,0x2C,0xE3, + 0x53,0xDD,0x49,0xF9,0x7A,0x68,0xF4,0x57, + 0x08,0x1F,0x7E,0x8C,0xEC,0x73,0x0E,0x3B, + 0xDF,0xB1,0x41,0x71,0xC4,0x07,0x86,0x97, + 0x1A,0x4F,0x85,0x9D,0xBB,0x60,0x1C,0x1C, + 0xD8,0xB1,0x08,0x73,0x7C,0x05,0xD7,0xC9, + 0xE6,0xFF,0xFF,0xE4,0x00,0x6E,0x78,0xCC, + 0xC1,0xD7,0xE7,0x0D,0xDF,0x0C,0x3C,0x2E, + 0x7E,0xE4,0xF0,0x49,0xE3,0xA5,0xD3,0xD8, + 0xA7,0xE9,0xA3,0xD1,0xCB,0x9B,0x4F,0x2F, + 0x18,0x58,0x5F,0x1A,0x38,0xAC,0xD1,0xC2, + 0x3E,0x06,0x9C,0xB9,0x2F,0x44,0xB8,0xC3, + 0x23,0x58,0x00,0xF1,0xB7,0x92,0x47,0x0E, + 0x4F,0xC0,0x80,0x4C,0xD3,0xBA,0x74,0x20, + 0xE2,0xA7,0x3C,0x2B,0x5F,0x99,0x2E,0x43, + 0x0C,0xE3,0xA9,0xF2,0xF1,0xC3,0xB3,0xF1, + 0x51,0xC0,0xC7,0x28,0xCF,0xFC,0x8C,0x22, + 0xBD,0x32,0x10,0x50,0x9D,0x88,0xB8,0x42, + 0x18,0x89,0xA1,0xD1,0x9D,0x83,0xC7,0x1F, + 0x22,0x05,0x31,0xA0,0x6F,0x2E,0xC0,0xF4, + 0x4C,0x04,0x5C,0xFE,0xFF,0x37,0x17,0x80, + 0xFF,0xFF,0xFF,0x9B,0x0B,0xE0,0xE6,0xFE, + 0xE0,0x9B,0x0B,0x70,0x8D,0xB4,0x2A,0x7A, + 0x61,0x77,0x08,0x18,0xD4,0x9D,0x1D,0x70, + 0x78,0x2B,0x78,0x67,0x87,0xF5,0xFF,0xBF, + 0xB3,0xC3,0xC3,0x8C,0x13,0xE5,0x85,0x21, + 0xC6,0x3B,0x3B,0x0B,0xF0,0x26,0xD0,0x51, + 0xC6,0x77,0x76,0x80,0x1F,0x67,0xD8,0x77, + 0x69,0xF0,0x5E,0x75,0x81,0xF5,0xFF,0xFF, + 0xAA,0x0B,0x3C,0x04,0xDF,0xA7,0x41,0x3E, + 0x5E,0x30,0x8C,0x83,0x2B,0x27,0xA1,0xC7, + 0x02,0x6B,0x85,0x41,0xDD,0xA9,0xC1,0xA5, + 0x09,0x5C,0x17,0x5F,0x1F,0x6A,0x7C,0xA4, + 0xC5,0x9F,0x2F,0x70,0x01,0x86,0x4C,0x4F, + 0x65,0x30,0xAE,0x29,0x3E,0x95,0x61,0xEE, + 0x0E,0x1E,0x90,0x8F,0x18,0xC0,0x67,0x15, + 0x1E,0x18,0xEE,0xB4,0xE0,0x9B,0x92,0x41, + 0xCF,0x31,0xA8,0x8F,0x3C,0x27,0xEF,0x7B, + 0xC2,0xE3,0x84,0xA3,0x9E,0x83,0xE8,0xD8, + 0xC0,0x71,0xDC,0xC0,0xFD,0xFF,0xC7,0x06, + 0xEF,0x70,0x83,0x3B,0xE8,0xF8,0x62,0x70, + 0x5C,0x18,0xB8,0xE7,0x02,0x0F,0xC3,0x37, + 0x1D,0x8F,0x08,0x33,0xFE,0xD7,0x3F,0x23, + 0x04,0xC4,0x5F,0x8C,0xD8,0x80,0xC1,0x78, + 0x6B,0xF3,0xF5,0x0D,0x37,0x60,0x5F,0x1D, + 0x7C,0xC1,0xF0,0x09,0xCC,0xE8,0x2F,0x30, + 0x4F,0x62,0x3E,0x36,0x90,0x0B,0x1C,0x1D, + 0x30,0x38,0x00,0x3D,0x60,0xF8,0x87,0x8B, + 0x77,0x39,0x30,0x5C,0x05,0x7D,0x5C,0xF0, + 0xB1,0xC7,0x8A,0xEE,0x72,0xE8,0x9B,0x9C, + 0x61,0xE2,0x18,0xE2,0x0D,0x8C,0xDD,0x25, + 0xC8,0x61,0x0E,0xEA,0x5D,0xC2,0x73,0xE0, + 0x67,0x0B,0x9F,0xE0,0x7C,0xF3,0x09,0x71, + 0xAA,0x8F,0x56,0xEF,0x01,0x3E,0x7A,0xBC, + 0x77,0xF9,0xEC,0xC4,0x2E,0x02,0x3E,0x72, + 0x19,0xC7,0xD3,0xF4,0x15,0xD0,0x43,0x36, + 0xD8,0xAB,0x86,0x4F,0x60,0x3E,0xBA,0xE1, + 0x8E,0x51,0x9E,0x89,0xA7,0xEF,0x3B,0x08, + 0x3B,0x92,0x1C,0x75,0xA8,0x6B,0x7A,0x44, + 0xF9,0xFF,0x9F,0xD0,0x81,0xF8,0xD6,0x06, + 0xCE,0x68,0xF7,0x0F,0xF4,0x36,0x3D,0x32, + 0xCC,0xD1,0x00,0xD6,0x25,0x04,0x5C,0x77, + 0x0C,0x5F,0x42,0x80,0x4F,0xD0,0x4B,0x04, + 0xFA,0x9A,0xE1,0xD1,0x3D,0x02,0x60,0xAE, + 0x18,0xEC,0x58,0xE0,0xC3,0x86,0xAF,0x01, + 0xEC,0x5E,0xE0,0x30,0xF7,0x08,0x50,0x81, + 0x7A,0x78,0xF0,0xD5,0xDE,0x23,0x40,0x71, + 0xB2,0xF4,0xA1,0xC1,0x03,0xB5,0xAA,0x33, + 0x26,0x94,0x23,0x26,0x3F,0x9B,0xF9,0x26, + 0x81,0xB9,0x5D,0xFA,0x26,0x01,0x37,0xCF, + 0x2C,0x50,0x49,0x20,0xF4,0xFF,0xBF,0x49, + 0xC0,0x85,0xE9,0xF2,0x32,0x43,0xE7,0x7F, + 0xE0,0xBE,0xD5,0x79,0x84,0x3E,0x44,0x30, + 0x94,0xF7,0x3C,0x9F,0xC2,0xF8,0x19,0xC2, + 0x07,0x4C,0x76,0xA6,0xE0,0x67,0x4D,0xDC, + 0x1D,0xC0,0x28,0x6F,0x9E,0x9E,0x00,0x3B, + 0x7F,0x1A,0xF9,0xDD,0xE0,0x5D,0xC0,0xD3, + 0xF7,0xBD,0x88,0x9F,0x28,0xC0,0x17,0xEC, + 0x4E,0x07,0x05,0xFA,0x84,0x3C,0x22,0xA3, + 0xFA,0x88,0xC0,0x2F,0x49,0x60,0x3C,0x92, + 0xF8,0x40,0x01,0x84,0xEE,0x05,0xA8,0xD3, + 0x07,0x47,0x3D,0xE3,0x17,0x54,0x63,0xBE, + 0x5B,0x3D,0xC2,0x79,0x72,0x98,0xCB,0x01, + 0x8B,0x73,0x4D,0x02,0xD5,0x71,0x97,0x8F, + 0x0E,0xEE,0xB5,0x15,0xFB,0xFF,0x27,0x38, + 0xB8,0x77,0x96,0x77,0x3E,0x43,0x79,0x90, + 0xE0,0xBB,0xB6,0x82,0xE3,0xAA,0x06,0xE3, + 0xD8,0xC2,0x2F,0x79,0x80,0x9D,0x61,0x71, + 0xC1,0x7F,0x0F,0x03,0x51,0x89,0x30,0x28, + 0x02,0xCB,0xBB,0xB7,0x52,0xF8,0x43,0x06, + 0xE3,0x4D,0x81,0x4F,0x1A,0x3B,0x6A,0xE0, + 0xFB,0xFF,0x1F,0x35,0xD8,0x86,0x8A,0xBB, + 0x29,0x82,0x75,0xAA,0x98,0x21,0xF0,0x60, + 0x0F,0x00,0x9F,0xAF,0x7C,0x06,0x50,0x14, + 0x18,0xD4,0xA1,0x1D,0xCE,0x6D,0x18,0x70, + 0x30,0x62,0xDC,0xA5,0x10,0xEE,0x94,0xDF, + 0x51,0x62,0x3F,0x97,0xB3,0xE9,0xE2,0xAE, + 0xE6,0x3E,0x9D,0xB0,0x0B,0x32,0x8C,0xB3, + 0xC0,0x23,0xC0,0xAB,0x39,0xBF,0x20,0x3F, + 0x17,0xBF,0x10,0x3C,0x26,0x85,0x78,0x53, + 0x7A,0x25,0x36,0xC6,0x93,0x71,0x73,0xB7, + 0x62,0x72,0xDE,0x79,0x41,0x36,0xC6,0xD1, + 0x44,0x8C,0x72,0x6E,0x0F,0x03,0x91,0x5F, + 0x90,0x7D,0x3F,0x79,0x21,0x88,0x18,0xCD, + 0x10,0x41,0x9F,0x97,0x8D,0x15,0x28,0xDE, + 0x0B,0x32,0x13,0xF8,0x56,0xD0,0xC1,0xC5, + 0x17,0x64,0xEC,0xFF,0xFF,0x82,0x0C,0x30, + 0xE2,0x64,0x04,0xF8,0x3C,0x71,0xE0,0xCE, + 0x35,0x30,0xFE,0xFF,0x97,0x6A,0xD8,0x27, + 0x1B,0xC0,0xD9,0xD0,0x7D,0xB2,0x01,0xF7, + 0x68,0xE1,0x1D,0x4D,0x10,0x27,0x1B,0x0A, + 0xE4,0xE0,0xEB,0xA2,0x70,0x3C,0xF4,0x49, + 0x84,0x1E,0x9D,0x7C,0x94,0xC4,0x9D,0x19, + 0x3C,0x91,0x77,0x16,0x8F,0xE2,0x65,0xD0, + 0xF7,0x82,0x13,0x79,0x7D,0xB0,0x9C,0x63, + 0x24,0xA8,0x46,0xE2,0xE3,0x03,0xFC,0xEB, + 0x8B,0x8F,0x91,0xF0,0xF9,0xFC,0xC3,0xF2, + 0x60,0x0C,0xF9,0xFF,0x7F,0x8A,0xC4,0x80, + 0x3C,0xBB,0x3C,0x86,0xF0,0x0B,0x24,0xDC, + 0xD3,0xCC,0x01,0x60,0x64,0x5D,0x1E,0xD1, + 0x67,0x47,0x8E,0x11,0xD7,0x17,0x45,0x5F, + 0x81,0x7D,0x10,0x38,0x9F,0xE7,0x44,0xB0, + 0x8E,0x9A,0x1F,0x6D,0xF8,0xF8,0x39,0xF8, + 0x5B,0xC1,0x03,0xA5,0x8F,0x45,0x21,0x1E, + 0x91,0xF8,0x39,0x11,0x5C,0x26,0xCE,0x89, + 0x40,0xE2,0xD0,0x0B,0xE3,0xB4,0x80,0x1B, + 0x88,0xCF,0x94,0xD8,0x29,0x9F,0x08,0x3B, + 0x97,0x60,0x46,0x07,0xAE,0xCB,0xBD,0x47, + 0x07,0xFE,0x93,0x00,0x1E,0xEB,0xFF,0xFF, + 0x78,0x07,0xBE,0x93,0xBA,0xEF,0x26,0xBE, + 0xC8,0xF8,0x50,0xF4,0x7C,0x07,0xF8,0x0F, + 0x77,0xB8,0x43,0xC5,0x39,0xDF,0x01,0xD2, + 0xFE,0xFF,0xE7,0x3B,0x60,0x79,0xB6,0x7E, + 0xBE,0x03,0xBB,0xC8,0xF3,0x1D,0x40,0xAC, + 0xFF,0xFF,0xF9,0x0E,0xB0,0x73,0x46,0xC3, + 0x9D,0xEF,0xC0,0x76,0xB4,0x01,0xCC,0x4D, + 0xE3,0xD1,0x06,0xDC,0xC3,0x85,0x3D,0x0C, + 0xAE,0xD0,0xA6,0x4F,0x8D,0x46,0xAD,0x1A, + 0x94,0xA9,0x51,0xE6,0xFF,0xDF,0xA0,0x56, + 0x9F,0x4A,0x8D,0x19,0xCB,0x0E,0xA5,0x80, + 0x8F,0x0A,0x8D,0xCD,0xF2,0x28,0x04,0x62, + 0x31,0xAF,0x06,0x81,0x38,0x2C,0x08,0x8D, + 0xF4,0xCA,0x11,0x88,0x25,0x3F,0xFB,0x05, + 0x62,0xB9,0x6F,0x06,0x81,0x38,0xE0,0x1B, + 0x4C,0xE0,0xE4,0x61,0x25,0x70,0xF2,0x6E, + 0x10,0x88,0x23,0x83,0x50,0xA1,0x3A,0x40, + 0x58,0x4C,0x10,0x1A,0xCA,0x07,0x08,0x93, + 0xFE,0x48,0x10,0x20,0x31,0x02,0xC2,0xC2, + 0xBD,0xBF,0x04,0x62,0x69,0xEF,0x09,0x81, + 0x58,0x88,0x15,0x10,0x16,0x17,0x84,0x86, + 0xD3,0x02,0xC2,0x24,0x99,0x01,0x61,0x81, + 0x40,0xA8,0x7C,0x35,0x20,0x4C,0xA4,0x1B, + 0x40,0xBA,0x7A,0x81,0x38,0x88,0x1E,0x10, + 0x26,0xC3,0x0F,0x08,0x0B,0x0D,0x42,0xA3, + 0x3D,0x30,0x04,0x48,0x0C,0x81,0xB0,0xF8, + 0x8E,0x40,0x98,0xF8,0x57,0x91,0x40,0x9C, + 0xDF,0x12,0xC4,0x4D,0x69,0x88,0x35,0x01, + 0x31,0x0D,0x9E,0x80,0x98,0x22,0x10,0x01, + 0x39,0xF6,0xD3,0x43,0x40,0xD6,0x60,0x0A, + 0x88,0x45,0x07,0x11,0x90,0x85,0xA8,0x02, + 0x62,0x79,0x5D,0x01,0xB1,0xF0,0x20,0x02, + 0x72,0xE6,0x97,0x9F,0x80,0xAC,0xE0,0xA5, + 0xF3,0x10,0xC0,0xDE,0x10,0x81,0x48,0x72, + 0x10,0x01,0x39,0xB0,0x2F,0x20,0x16,0x1F, + 0x44,0x40,0xCE,0xFA,0x28,0x14,0x90,0x83, + 0x83,0x68,0x10,0xE4,0x6B,0x26,0x20,0xA7, + 0x07,0x11,0x10,0xF9,0x04,0x05,0x21,0x6A, + 0xBD,0x81,0x30,0x3D,0x8F,0x42,0x0D,0x85, + 0x80,0x50,0xE5,0xEA,0xCE,0x31,0x2C,0x07, + 0x08,0xCD,0x05,0x22,0x30,0xAB,0x70,0x07, + 0xC4,0x54,0x81,0x08,0xC8,0x09,0x80,0xC8, + 0xFF,0x9F,0x60,0x2A,0x10,0x9A,0x12,0x8C, + 0xEA,0x92,0x07,0xC4,0x12,0x80,0xD0,0x54, + 0x20,0x34,0x25,0x88,0x00,0xAD,0xCA,0x1E, + 0x10,0x53,0x0A,0x42,0x95,0x83,0xD0,0x74, + 0x20,0x54,0xB6,0xBE,0xC3,0x02,0x05,0x11, + 0x90,0xA3,0x83,0x50,0xE1,0xFE,0x40,0x98, + 0xDE,0x97,0x86,0x00,0x9D,0x0E,0x44,0x40, + 0x4E,0x0C,0x42,0x15,0x7C,0x32,0x82,0x10, + 0xB1,0x20,0x54,0xC1,0x27,0x23,0x28,0xD1, + 0xF2,0xB2,0x13,0x90,0xF5,0x81,0x50,0xBD, + 0x20,0x02,0x73,0x36,0x20,0x9A,0x17,0x84, + 0xE6,0x07,0xA3,0x5A,0x8D,0x02,0x31,0xFD, + 0x20,0x34,0x0F,0x88,0xC0,0xAC,0xE0,0xF9, + 0x71,0xC0,0x0C,0x84,0xAA,0x04,0x11,0x98, + 0x73,0x01,0xD1,0xAC,0x20,0x34,0x3B,0x18, + 0xD5,0xFE,0x0F,0xD1,0x00,0x08,0x08,0xCD, + 0x07,0xA2,0xC3,0x00,0x79,0x96,0x09,0xC8, + 0x1A,0x41,0xA8,0x66,0x10,0x81,0x39,0x27, + 0x10,0xCD,0x0E,0x42,0x95,0xFD,0x4D,0x82, + 0x91,0x8C,0x0F,0xD0,0x40,0x24,0x37,0x08, + 0xD5,0xF1,0x0C,0x0A,0x46,0x74,0x83,0x08, + 0xC8,0x59,0x40,0x68,0x36,0x30,0x9A,0x4C, + 0xED,0x91,0x80,0xBA,0x05,0x61,0xE9,0x41, + 0x68,0x3A,0xBB,0x83,0xA7,0x20,0x54,0x81, + 0x5E,0x30,0xA6,0x19,0x44,0x87,0x05,0x02, + 0x42,0x73,0x81,0x51,0x1D,0xAF,0x96,0x40, + 0x44,0x1B,0x08,0xD5,0x0A,0xA2,0x81,0x93, + 0x1F,0x53,0x10,0x92,0x14,0x84,0xFC,0xFF, + 0x07,0xAA,0xC7,0x9C,0x40,0xAC,0xFA,0x5B, + 0x25,0x50,0x27,0x01,0xA1,0xC9,0x40,0x74, + 0x7C,0x20,0x0F,0xB8,0x83,0x64,0x20,0x54, + 0x29,0x88,0xC0,0xAC,0xF4,0x63,0xA4,0x23, + 0x05,0x51,0x7D,0xBC,0xA0,0x20,0x34,0xD1, + 0x3B,0x2C,0x08,0x7B,0xB8,0x69,0xA8,0xE4, + 0x59,0xA5,0xA1,0x12,0x10,0x9A,0x0D,0x44, + 0xC7,0x04,0xF2,0xAA,0x79,0x4C,0x60,0x20, + 0x54,0x2F,0x08,0xCD,0x01,0x42,0x13,0x83, + 0x08,0xD4,0xA9,0xBF,0x37,0x1A,0x2A,0xF9, + 0x5B,0x09,0xC4,0xCA,0x5E,0x69,0x02,0xB1, + 0xDE,0xA7,0x4E,0x20,0xE6,0x1D,0x98,0xA9, + 0x05,0xA1,0xEA,0x41,0x04,0xE6,0xB4,0x40, + 0x54,0x81,0x78,0x10,0xA6,0x08,0x44,0x60, + 0x4E,0x02,0x44,0xD3,0x81,0xD0,0xEC,0x60, + 0x54,0xE7,0xA3,0x4D,0x40,0xD6,0x0E,0x42, + 0xB3,0x80,0x08,0xCC,0x59,0x1E,0x69,0x02, + 0xB1,0x92,0x2F,0x9D,0x0E,0x24,0x04,0x84, + 0x26,0xD3,0x7F,0x68,0xA1,0x05,0x80,0x99, + 0x84,0x04,0x20,0x4C,0x16,0x88,0x0E,0x27, + 0xD6,0x08,0x22,0x40,0xC7,0x01,0xA3,0xD1, + 0x40,0x68,0x5C,0x40,0x9A,0x1D,0x90,0x2A, + 0x6D,0x00,0xC6,0x54,0x83,0xD0,0x24,0x20, + 0x02,0x74,0x2C,0x10,0x01,0x5A,0x74,0x04, + 0x30,0x16,0x01,0x84,0x46,0x05,0xA1,0xC9, + 0x2A,0x80,0xB2,0x9C,0x20,0x1A,0x20,0xC9, + 0x30,0x60,0x0A,0x42,0x33,0x81,0xD0,0x8C, + 0x20,0x54,0x7C,0x07,0x10,0x16,0x04,0x84, + 0x86,0x03,0xD1,0x00,0xFE,0xFF,0x8F,0x0C, + 0x02,0xD1,0x00,0x9C,0x23,0xC4,0x61,0x85, + 0x82,0xD0,0xF4,0x20,0x34,0x6C,0x09,0x50, + 0x16,0x1D,0x44,0xC7,0x23,0x92,0x02,0x8C, + 0x05,0x02,0xA1,0x31,0x41,0x68,0x6C,0x10, + 0x1A,0x29,0x06,0x28,0x13,0x54,0xE3,0x50, + 0x44,0x7B,0x80,0x31,0x99,0x20,0x54,0x36, + 0x88,0xC0,0x1C,0x14,0x88,0x86,0x07,0xA1, + 0x62,0x82,0x00,0x52,0x10,0x01,0x12,0x20, + 0x1A,0x1E,0x84,0x8A,0x29,0x32,0x74,0x0A, + 0x42,0x55,0x24,0x39,0x9A,0x50,0x10,0x1D, + 0x4D,0x08,0x08,0xCD,0x07,0x46,0x75,0x35, + 0x39,0x6E,0x50,0x10,0xAA,0x1D,0x84,0x06, + 0x05,0xA1,0x39,0xA2,0x80,0xB2,0xEC,0x20, + 0x02,0xB2,0x9E,0x2A,0x87,0x0A,0x0A,0x22, + 0x30,0xA7,0x02,0xA2,0x49,0x41,0xA8,0x8E, + 0x2C,0x47,0x0A,0x9A,0x06,0x84,0x25,0x06, + 0xA1,0xC9,0xDA,0x80,0xB0,0x0C,0x75,0x0E, + 0x24,0x14,0x84,0xE6,0x04,0xA1,0x4A,0xF2, + 0x0C,0x8F,0x82,0xE8,0x38,0x42,0x80,0x68, + 0x7A,0x10,0xAA,0xA6,0xCF,0x00,0x28,0x88, + 0x06,0x40,0x40,0x68,0x4E,0x30,0xAA,0xA8, + 0xD1,0xD1,0x84,0x82,0x50,0xDD,0x2F,0x4E, + 0x81,0xF8,0xFF,0x0F, + }) // END MBUF + +} //end DefinitionBlock + diff --git a/tools/acpiexec/Makefile b/tools/acpiexec/Makefile index f21adcb..c9cf8a4 100644 --- a/tools/acpiexec/Makefile +++ b/tools/acpiexec/Makefile @@ -20,8 +20,10 @@ SRCS= aetables.c aehandlers.c aeexec.c aemain.c \ ../../disassembler/dmutils.c \ ../../disassembler/dmwalk.c \ ../../events/evevent.c \ - ../../events/evgpeblk.c \ ../../events/evgpe.c \ + ../../events/evgpeblk.c \ + ../../events/evgpeinit.c \ + ../../events/evgpeutil.c \ ../../events/evmisc.c \ ../../events/evregion.c \ ../../events/evrgnini.c \ diff --git a/tools/acpiexec/aeexec.c b/tools/acpiexec/aeexec.c index 9aec80d..2e8790a 100644 --- a/tools/acpiexec/aeexec.c +++ b/tools/acpiexec/aeexec.c @@ -235,7 +235,6 @@ AfInstallGpeBlock ( if (ACPI_SUCCESS (Status)) { Status = AcpiInstallGpeBlock (Handle2, &BlockAddress, 7, 8); - Status = AcpiInstallGpeBlock (Handle2, &BlockAddress, 2, 0); AcpiInstallGpeHandler (Handle2, 8, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL); AcpiEnableGpe (Handle2, 8, ACPI_GPE_TYPE_RUNTIME); diff --git a/tools/acpiexec/aetables.c b/tools/acpiexec/aetables.c index 4c3734a..e1f61c6 100644 --- a/tools/acpiexec/aetables.c +++ b/tools/acpiexec/aetables.c @@ -198,6 +198,34 @@ unsigned char Oem1Code[] = 0x31,0x00,0x70,0x01,0x5F,0x58,0x54,0x32, /* 00000030 "1.p._XT2" */ }; +/* ASL source for this table is at the end of this file */ + +unsigned char OemxCode[] = +{ + 0x4F,0x45,0x4D,0x58,0xB0,0x00,0x00,0x00, /* 00000000 "OEMX...." */ + 0x02,0x54,0x4D,0x79,0x4F,0x45,0x4D,0x00, /* 00000008 ".TMyOEM." */ + 0x54,0x65,0x73,0x74,0x00,0x00,0x00,0x00, /* 00000010 "Test...." */ + 0x32,0x04,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "2...INTL" */ + 0x31,0x03,0x10,0x20,0x14,0x1D,0x5F,0x49, /* 00000020 "1.. .._I" */ + 0x4E,0x49,0x00,0x70,0x0D,0x54,0x61,0x62, /* 00000028 "NI.p.Tab" */ + 0x6C,0x65,0x20,0x4F,0x45,0x4D,0x58,0x20, /* 00000030 "le OEMX " */ + 0x72,0x75,0x6E,0x6E,0x69,0x6E,0x67,0x00, /* 00000038 "running." */ + 0x5B,0x31,0x10,0x22,0x5C,0x5F,0x47,0x50, /* 00000040 "[1."\_GP" */ + 0x45,0x14,0x06,0x5F,0x45,0x30,0x37,0x00, /* 00000048 "E.._E07." */ + 0x14,0x06,0x5F,0x45,0x32,0x32,0x00,0x14, /* 00000050 ".._E22.." */ + 0x06,0x5F,0x4C,0x33,0x31,0x00,0x14,0x06, /* 00000058 "._L31..." */ + 0x5F,0x4C,0x36,0x36,0x00,0x5B,0x82,0x10, /* 00000060 "_L66.[.." */ + 0x4F,0x45,0x4D,0x31,0x08,0x5F,0x50,0x52, /* 00000068 "OEM1._PR" */ + 0x57,0x12,0x05,0x02,0x0A,0x07,0x00,0x5B, /* 00000070 "W......[" */ + 0x82,0x10,0x4F,0x45,0x4D,0x32,0x08,0x5F, /* 00000078 "..OEM2._" */ + 0x50,0x52,0x57,0x12,0x05,0x02,0x0A,0x66, /* 00000080 "PRW....f" */ + 0x00,0x10,0x26,0x5C,0x47,0x50,0x45,0x32, /* 00000088 "..&\GPE2" */ + 0x14,0x06,0x5F,0x4C,0x30,0x31,0x00,0x14, /* 00000090 ".._L01.." */ + 0x06,0x5F,0x45,0x30,0x37,0x00,0x08,0x5F, /* 00000098 "._E07.._" */ + 0x50,0x52,0x57,0x12,0x0C,0x02,0x12,0x08, /* 000000A0 "PRW....." */ + 0x02,0x5C,0x47,0x50,0x45,0x32,0x01,0x00 /* 000000A8 ".\GPE2.." */ +}; + /* * Example installable control method * @@ -242,7 +270,7 @@ ACPI_TABLE_HEADER LocalTEST; ACPI_TABLE_HEADER LocalBADTABLE; ACPI_TABLE_RSDT *LocalRSDT; -#define BASE_RSDT_TABLES 6 +#define BASE_RSDT_TABLES 7 #define BASE_RSDT_SIZE (sizeof (ACPI_TABLE_RSDT) + ((BASE_RSDT_TABLES -1) * sizeof (UINT32))) #define ACPI_MAX_INIT_TABLES (32) @@ -349,6 +377,10 @@ AeBuildLocalTables ( LocalRSDT->TableOffsetEntry[5] = ACPI_PTR_TO_PHYSADDR (&Oem1Code); + /* Install the OEMx table to test LoadTable */ + + LocalRSDT->TableOffsetEntry[6] = ACPI_PTR_TO_PHYSADDR (&OemxCode); + /* * Install the user tables. The DSDT must be installed in the FADT. * All other tables are installed directly into the RSDT. @@ -583,3 +615,110 @@ AeLocalGetRootPointer ( } +#if 0 +/****************************************************************************** + * + * DESCRIPTION: ASL tables that are used in RSDT/XSDT, also used to test + * Load/LoadTable operators. + * + *****************************************************************************/ + +DefinitionBlock ("", "OEMX", 2, "MyOEM", "Test", 0x00000432) +{ + External (GPE2, DeviceObj) + + Method (_INI) + { + Store ("Table OEMX running", Debug) + } + + Scope (\_GPE) + { + Method (_E07) {} + Method (_E22) {} + Method (_L31) {} + Method (_L66) {} + } + + Device (OEM1) + { + Name (_PRW, Package(){7,0}) + } + Device (OEM2) + { + Name (_PRW, Package(){0x66,0}) + } + + Scope (\GPE2) + { + Method (_L01) {} + Method (_E07) {} + + Name (_PRW, Package() {Package() {\GPE2, 1}, 0}) + } +} + +/* Parent gr.asl file */ + +DefinitionBlock ("", "DSDT", 2, "Intel", "Many", 0x00000001) +{ + Name (BUF1, Buffer() + { + 0x4F,0x45,0x4D,0x58,0xB0,0x00,0x00,0x00, /* 00000000 "OEMX...." */ + 0x02,0x54,0x4D,0x79,0x4F,0x45,0x4D,0x00, /* 00000008 ".TMyOEM." */ + 0x54,0x65,0x73,0x74,0x00,0x00,0x00,0x00, /* 00000010 "Test...." */ + 0x32,0x04,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "2...INTL" */ + 0x31,0x03,0x10,0x20,0x14,0x1D,0x5F,0x49, /* 00000020 "1.. .._I" */ + 0x4E,0x49,0x00,0x70,0x0D,0x54,0x61,0x62, /* 00000028 "NI.p.Tab" */ + 0x6C,0x65,0x20,0x4F,0x45,0x4D,0x58,0x20, /* 00000030 "le OEMX " */ + 0x72,0x75,0x6E,0x6E,0x69,0x6E,0x67,0x00, /* 00000038 "running." */ + 0x5B,0x31,0x10,0x22,0x5C,0x5F,0x47,0x50, /* 00000040 "[1."\_GP" */ + 0x45,0x14,0x06,0x5F,0x45,0x30,0x37,0x00, /* 00000048 "E.._E07." */ + 0x14,0x06,0x5F,0x45,0x32,0x32,0x00,0x14, /* 00000050 ".._E22.." */ + 0x06,0x5F,0x4C,0x33,0x31,0x00,0x14,0x06, /* 00000058 "._L31..." */ + 0x5F,0x4C,0x36,0x36,0x00,0x5B,0x82,0x10, /* 00000060 "_L66.[.." */ + 0x4F,0x45,0x4D,0x31,0x08,0x5F,0x50,0x52, /* 00000068 "OEM1._PR" */ + 0x57,0x12,0x05,0x02,0x0A,0x07,0x00,0x5B, /* 00000070 "W......[" */ + 0x82,0x10,0x4F,0x45,0x4D,0x32,0x08,0x5F, /* 00000078 "..OEM2._" */ + 0x50,0x52,0x57,0x12,0x05,0x02,0x0A,0x66, /* 00000080 "PRW....f" */ + 0x00,0x10,0x26,0x5C,0x47,0x50,0x45,0x32, /* 00000088 "..&\GPE2" */ + 0x14,0x06,0x5F,0x4C,0x30,0x31,0x00,0x14, /* 00000090 ".._L01.." */ + 0x06,0x5F,0x45,0x30,0x37,0x00,0x08,0x5F, /* 00000098 "._E07.._" */ + 0x50,0x52,0x57,0x12,0x0C,0x02,0x12,0x08, /* 000000A0 "PRW....." */ + 0x02,0x5C,0x47,0x50,0x45,0x32,0x01,0x00 /* 000000A8 ".\GPE2.." */ + }) + + Name (HNDL, 0) + Method (LD) + { + Load (BUF1, HNDL) + Store ("Load operator, handle:", Debug) + Store (HNDL, Debug) + } + + Method (MAIN, 0, NotSerialized) + { + Store ("Loading OEMX table", Debug) + Store (LoadTable ("OEMX", "MyOEM", "Test"), Debug) + } + + Scope (\_GPE) + { + Method (_L08) {} + Method (_E08) {} + Method (_L0B) {} + } + + Device (DEV0) + { + Name (_PRW, Package() {0x11, 0}) + } + + Device (\GPE2) + { + Method (_L00) {} + } +} + +#endif + diff --git a/tools/acpisrc/astable.c b/tools/acpisrc/astable.c index 51c7f3d..5a96f06 100644 --- a/tools/acpisrc/astable.c +++ b/tools/acpisrc/astable.c @@ -310,7 +310,6 @@ ACPI_TYPED_IDENTIFIER_TABLE AcpiIdentifiers[] = { {"ACPI_INTEGER_OVERLAY", SRC_TYPE_STRUCT}, {"ACPI_INTEGRITY_INFO", SRC_TYPE_STRUCT}, {"ACPI_INTERFACE_INFO", SRC_TYPE_STRUCT}, - {"ACPI_INTERNAL_RSDT", SRC_TYPE_STRUCT}, {"ACPI_INTERPRETER_MODE", SRC_TYPE_SIMPLE}, {"ACPI_IO_ADDRESS", SRC_TYPE_SIMPLE}, {"ACPI_IO_ATTRIBUTE", SRC_TYPE_STRUCT}, diff --git a/utilities/utcopy.c b/utilities/utcopy.c index fe44083..c1fccae 100644 --- a/utilities/utcopy.c +++ b/utilities/utcopy.c @@ -797,6 +797,7 @@ AcpiUtCopySimpleObject ( UINT16 ReferenceCount; ACPI_OPERAND_OBJECT *NextObject; ACPI_STATUS Status; + ACPI_SIZE CopySize; /* Save fields from destination that we don't want to overwrite */ @@ -804,10 +805,18 @@ AcpiUtCopySimpleObject ( ReferenceCount = DestDesc->Common.ReferenceCount; NextObject = DestDesc->Common.NextObject; - /* Copy the entire source object over the destination object*/ + /* + * Copy the entire source object over the destination object. + * Note: Source can be either an operand object or namespace node. + */ + CopySize = sizeof (ACPI_OPERAND_OBJECT); + if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED) + { + CopySize = sizeof (ACPI_NAMESPACE_NODE); + } - ACPI_MEMCPY ((char *) DestDesc, (char *) SourceDesc, - sizeof (ACPI_OPERAND_OBJECT)); + ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc), + ACPI_CAST_PTR (char, SourceDesc), CopySize); /* Restore the saved fields */ @@ -841,8 +850,7 @@ AcpiUtCopySimpleObject ( /* Copy the actual buffer data */ ACPI_MEMCPY (DestDesc->Buffer.Pointer, - SourceDesc->Buffer.Pointer, - SourceDesc->Buffer.Length); + SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length); } break; @@ -864,7 +872,7 @@ AcpiUtCopySimpleObject ( /* Copy the actual string data */ ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer, - (ACPI_SIZE) SourceDesc->String.Length + 1); + (ACPI_SIZE) SourceDesc->String.Length + 1); } break; diff --git a/utilities/utglobal.c b/utilities/utglobal.c index 986dbeb..34af1f5 100644 --- a/utilities/utglobal.c +++ b/utilities/utglobal.c @@ -625,7 +625,7 @@ AcpiUtGetNodeName ( static const char *AcpiGbl_DescTypeNames[] = { - /* 00 */ "Invalid", + /* 00 */ "Not a Descriptor", /* 01 */ "Cached", /* 02 */ "State-Generic", /* 03 */ "State-Update", @@ -656,7 +656,7 @@ AcpiUtGetDescriptorName ( if (ACPI_GET_DESCRIPTOR_TYPE (Object) > ACPI_DESC_TYPE_MAX) { - return (ACPI_CAST_PTR (char, AcpiGbl_BadType)); + return ("Not a Descriptor"); } return (ACPI_CAST_PTR (char, diff --git a/utilities/uttrack.c b/utilities/uttrack.c index 37fdba1..ac45e9a 100644 --- a/utilities/uttrack.c +++ b/utilities/uttrack.c @@ -644,6 +644,7 @@ AcpiUtDumpAllocations ( ACPI_DEBUG_MEM_BLOCK *Element; ACPI_DESCRIPTOR *Descriptor; UINT32 NumOutstanding = 0; + UINT8 DescriptorType; ACPI_FUNCTION_TRACE (UtDumpAllocations); @@ -663,43 +664,86 @@ AcpiUtDumpAllocations ( if ((Element->Component & Component) && ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module)))) { - /* Ignore allocated objects that are in a cache */ - Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace); - if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED) + + if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR)) { - AcpiOsPrintf ("%p Len %04X %9.9s-%d [%s] ", + AcpiOsPrintf ("%p Length 0x%04X %9.9s-%d " + "[Not a Descriptor - too small]\n", Descriptor, Element->Size, Element->Module, - Element->Line, AcpiUtGetDescriptorName (Descriptor)); - - /* Most of the elements will be Operand objects. */ + Element->Line); + } + else + { + /* Ignore allocated objects that are in a cache */ - switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) + if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED) { - case ACPI_DESC_TYPE_OPERAND: - AcpiOsPrintf ("%12.12s R%hd", - AcpiUtGetTypeName (Descriptor->Object.Common.Type), - Descriptor->Object.Common.ReferenceCount); - break; - - case ACPI_DESC_TYPE_PARSER: - AcpiOsPrintf ("AmlOpcode %04hX", - Descriptor->Op.Asl.AmlOpcode); - break; - - case ACPI_DESC_TYPE_NAMED: - AcpiOsPrintf ("%4.4s", - AcpiUtGetNodeName (&Descriptor->Node)); - break; - - default: - break; + AcpiOsPrintf ("%p Length 0x%04X %9.9s-%d [%s] ", + Descriptor, Element->Size, Element->Module, + Element->Line, AcpiUtGetDescriptorName (Descriptor)); + + /* Validate the descriptor type using Type field and length */ + + DescriptorType = 0; /* Not a valid descriptor type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) + { + case ACPI_DESC_TYPE_OPERAND: + if (Element->Size == sizeof (ACPI_DESC_TYPE_OPERAND)) + { + DescriptorType = ACPI_DESC_TYPE_OPERAND; + } + break; + + case ACPI_DESC_TYPE_PARSER: + if (Element->Size == sizeof (ACPI_DESC_TYPE_PARSER)) + { + DescriptorType = ACPI_DESC_TYPE_PARSER; + } + break; + + case ACPI_DESC_TYPE_NAMED: + if (Element->Size == sizeof (ACPI_DESC_TYPE_NAMED)) + { + DescriptorType = ACPI_DESC_TYPE_NAMED; + } + break; + + default: + break; + } + + /* Display additional info for the major descriptor types */ + + switch (DescriptorType) + { + case ACPI_DESC_TYPE_OPERAND: + AcpiOsPrintf ("%12.12s RefCount 0x%04X\n", + AcpiUtGetTypeName (Descriptor->Object.Common.Type), + Descriptor->Object.Common.ReferenceCount); + break; + + case ACPI_DESC_TYPE_PARSER: + AcpiOsPrintf ("AmlOpcode 0x%04hX\n", + Descriptor->Op.Asl.AmlOpcode); + break; + + case ACPI_DESC_TYPE_NAMED: + AcpiOsPrintf ("%4.4s\n", + AcpiUtGetNodeName (&Descriptor->Node)); + break; + + default: + AcpiOsPrintf ( "\n"); + break; + } } - - AcpiOsPrintf ( "\n"); - NumOutstanding++; } + + NumOutstanding++; } + Element = Element->Next; } @@ -709,13 +753,11 @@ AcpiUtDumpAllocations ( if (!NumOutstanding) { - ACPI_INFO ((AE_INFO, - "No outstanding allocations")); + ACPI_INFO ((AE_INFO, "No outstanding allocations")); } else { - ACPI_ERROR ((AE_INFO, - "%d(0x%X) Outstanding allocations", + ACPI_ERROR ((AE_INFO, "%d(0x%X) Outstanding allocations", NumOutstanding, NumOutstanding)); } -- cgit v1.1 From c28c8b4fa8609196c4f255f1331dbe009fba337c Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 28 Apr 2010 22:23:29 +0000 Subject: Don't assume that "resource" property is in metadata. Reported by: Mikolaj Golub MFC after: 3 days --- sbin/hastd/metadata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbin/hastd/metadata.c b/sbin/hastd/metadata.c index 9bca66b..7a138e8 100644 --- a/sbin/hastd/metadata.c +++ b/sbin/hastd/metadata.c @@ -117,7 +117,7 @@ metadata_read(struct hast_resource *res, bool openrw) } str = nv_get_string(nv, "resource"); - if (strcmp(str, res->hr_name) != 0) { + if (str != NULL && strcmp(str, res->hr_name) != 0) { pjdlog_error("Provider %s is not part of resource %s.", res->hr_localpath, res->hr_name); nv_free(nv); -- cgit v1.1 From 166a203d5e0b13f7fa327cfc93e8869e75e6399b Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 28 Apr 2010 22:26:30 +0000 Subject: Use WEXITSTATUS() to obtain real exit code. MFC after: 3 days --- sbin/hastd/hastd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c index 957885d..50bc9ff 100644 --- a/sbin/hastd/hastd.c +++ b/sbin/hastd/hastd.c @@ -294,9 +294,10 @@ listen_accept(void) "Waiting for worker process (pid=%u) failed", (unsigned int)res->hr_workerpid); /* See above. */ - } else if (status != 0) { + } else if (WEXITSTATUS(status) != 0) { pjdlog_error("Worker process (pid=%u) exited ungracefully: status=%d.", - (unsigned int)res->hr_workerpid, status); + (unsigned int)res->hr_workerpid, + WEXITSTATUS(status)); /* See above. */ } else { pjdlog_debug(1, -- cgit v1.1 From 9112a6190b5b7cda3b136f493f0fe2e83f186143 Mon Sep 17 00:00:00 2001 From: dougb Date: Wed, 28 Apr 2010 22:29:17 +0000 Subject: In the case where named_chroot_autoupdate is NOT set, but named_chrootdir IS set, named-checkconf fails because it cannot find the conf file. Fix this by making checkconf a variable that includes "-t $named_chrootdir" as needed. Notice of the bug and suggested direction for the fix from [1]. Using required_files for named.conf is overkill ever since I added the named-checkconf call, so rather than update the logic to handle the case described above, remove it. This also handles the case where named_chroot_autoupdate IS set but the symlink doesn't exist yet. PR: conf/145904 Submitted by: J R Matthews --- etc/rc.d/named | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/etc/rc.d/named b/etc/rc.d/named index 346b6fc..81db646 100755 --- a/etc/rc.d/named +++ b/etc/rc.d/named @@ -192,6 +192,13 @@ named_prestart() $confgen_command fi + local checkconf + + checkconf="${command%/named}/named-checkconf" + if ! checkyesno named_chroot_autoupdate && [ -n "$named_chrootdir" ]; then + checkconf="$checkconf -t $named_chrootdir" + fi + # Create a forwarder configuration based on /etc/resolv.conf if checkyesno named_auto_forward; then if [ ! -s /etc/resolv.conf ]; then @@ -201,7 +208,7 @@ named_prestart() [ -s "${named_confdir}/auto_forward.conf" ] && create_file ${named_confdir}/auto_forward.conf - ${command%/named}/named-checkconf $named_conf || + $checkconf $named_conf || err 3 'named-checkconf for $named_conf failed' return fi @@ -263,8 +270,7 @@ named_prestart() create_file ${named_confdir}/auto_forward.conf fi - ${command%/named}/named-checkconf $named_conf || - err 3 'named-checkconf for $named_conf failed' + $checkconf $named_conf || err 3 'named-checkconf for $named_conf failed' } load_rc_config $name @@ -272,7 +278,7 @@ load_rc_config $name # Updating the following variables requires that rc.conf be loaded first # required_dirs="$named_chrootdir" # if it is set, it must exist -required_files="${named_conf:=/etc/namedb/named.conf}" + pidfile="${named_pidfile:-/var/run/named/pid}" named_confdir="${named_chrootdir}${named_conf%/*}" -- cgit v1.1 From 0b8041abddf4130f04938e6ee94d4b703d62cea5 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 28 Apr 2010 22:39:47 +0000 Subject: Mark temporary issues as such. MFC after: 3 days --- sbin/hastd/primary.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c index 0915154..73f722b 100644 --- a/sbin/hastd/primary.c +++ b/sbin/hastd/primary.c @@ -480,7 +480,7 @@ init_remote(struct hast_resource *res, struct proto_conn **inp, /* Prepare outgoing connection with remote node. */ if (proto_client(res->hr_remoteaddr, &out) < 0) { - primary_exit(EX_OSERR, "Unable to create connection to %s", + primary_exit(EX_TEMPFAIL, "Unable to create connection to %s", res->hr_remoteaddr); } /* Try to connect, but accept failure. */ @@ -739,7 +739,7 @@ hastd_primary(struct hast_resource *res) pid = fork(); if (pid < 0) { KEEP_ERRNO((void)pidfile_remove(pfh)); - primary_exit(EX_OSERR, "Unable to fork"); + primary_exit(EX_TEMPFAIL, "Unable to fork"); } if (pid > 0) { -- cgit v1.1 From b9745c56c32f05ef97dad10290a195b6c8bbeaa1 Mon Sep 17 00:00:00 2001 From: pjd Date: Wed, 28 Apr 2010 22:41:06 +0000 Subject: Restart worker thread only if the problem was temporary. In case of persistent problem we don't want to loop forever. MFC after: 3 days --- sbin/hastd/hastd.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c index 50bc9ff..7b2a8e2 100644 --- a/sbin/hastd/hastd.c +++ b/sbin/hastd/hastd.c @@ -140,9 +140,15 @@ child_exit(void) proto_close(res->hr_ctrl); res->hr_workerpid = 0; if (res->hr_role == HAST_ROLE_PRIMARY) { - sleep(1); - pjdlog_info("Restarting worker process."); - hastd_primary(res); + if (WEXITSTATUS(status) == EX_TEMPFAIL) { + sleep(1); + pjdlog_info("Restarting worker process."); + hastd_primary(res); + } else { + res->hr_role = HAST_ROLE_INIT; + pjdlog_info("Changing resource role back to %s.", + role2str(res->hr_role)); + } } pjdlog_prefix_set("%s", ""); } -- cgit v1.1 From e2e8a8241277c6ae0d4908670d9baf2b2c538602 Mon Sep 17 00:00:00 2001 From: rmacklem Date: Wed, 28 Apr 2010 23:05:42 +0000 Subject: Delete a diagnostic statement that is no longer useful from the experimental NFS client. MFC after: 1 week --- sys/fs/nfsclient/nfs_clrpcops.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c index a84a301..5d00102 100644 --- a/sys/fs/nfsclient/nfs_clrpcops.c +++ b/sys/fs/nfsclient/nfs_clrpcops.c @@ -1399,10 +1399,6 @@ nfsrpc_write(vnode_t vp, struct uio *uiop, int *iomode, u_char *verfp, else error = nfsrpc_writerpc(vp, uiop, iomode, verfp, newcred, &stateid, p, nap, attrflagp, stuff); -if (error == NFSERR_BADSTATEID) { -printf("st=0x%x 0x%x 0x%x\n",stateid.other[0],stateid.other[1],stateid.other[2]); -nfscl_dumpstate(nmp, 1, 1, 0, 0); -} if (error == NFSERR_STALESTATEID) nfscl_initiate_recovery(nmp->nm_clp); if (lckp != NULL) -- cgit v1.1 From a101ef6559ba33feff4e60757b06a186082bc97d Mon Sep 17 00:00:00 2001 From: rmacklem Date: Wed, 28 Apr 2010 23:16:21 +0000 Subject: For the experimental NFS client, it should always flush dirty buffers before closing the NFSv4 opens, as the comment states. This patch deletes the call to nfscl_mustflush() which would return 0 for the case where a delegation still exists, which was incorrect and could cause crashes during recovery from an expired lease. MFC after: 1 week --- sys/fs/nfsclient/nfs_clnode.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/fs/nfsclient/nfs_clnode.c b/sys/fs/nfsclient/nfs_clnode.c index c133742..e36431f 100644 --- a/sys/fs/nfsclient/nfs_clnode.c +++ b/sys/fs/nfsclient/nfs_clnode.c @@ -198,8 +198,7 @@ ncl_inactive(struct vop_inactive_args *ap) * must be flushed before the close, so that the stateid is * available for the writes. */ - if (nfscl_mustflush(vp)) - (void) ncl_flush(vp, MNT_WAIT, NULL, ap->a_td, 1, 0); + (void) ncl_flush(vp, MNT_WAIT, NULL, ap->a_td, 1, 0); (void) nfsrpc_close(vp, 1, ap->a_td); } -- cgit v1.1 From 06a2ddb54d82ea81b21f69d0d0944d15949d6be3 Mon Sep 17 00:00:00 2001 From: sobomax Date: Thu, 29 Apr 2010 06:16:00 +0000 Subject: On certain chipsets AT keyboard controller isn't present and is emulated by BIOS using SMI interrupt. On those chipsets reading from the status port may be thousand times slower than usually. Sometimes this emilation is not working properly resulting in commands timing out and since we assume that inb() operation takes very little time to complete we need to adjust number of retries to keep waiting time within a designed limits (100ms). Measure time it takes to make read_status() call and adjust number of retries accordingly. To keep it simple, use TSC to measure inb() performance and keep it to amd64-only, since TSC may not available on older CPUs. Also enable detection of the AT controller absence on amd64. Reviewed by: jhb MFC after: 1 month --- sys/dev/atkbdc/atkbdc.c | 76 ++++++++++++++++++++++++++++++++++++-------- sys/dev/atkbdc/atkbdc_ebus.c | 1 + sys/dev/atkbdc/atkbdc_isa.c | 7 ++-- sys/dev/atkbdc/atkbdcreg.h | 1 + 4 files changed, 69 insertions(+), 16 deletions(-) diff --git a/sys/dev/atkbdc/atkbdc.c b/sys/dev/atkbdc/atkbdc.c index df1f28e..f8e856a 100644 --- a/sys/dev/atkbdc/atkbdc.c +++ b/sys/dev/atkbdc/atkbdc.c @@ -44,6 +44,10 @@ __FBSDID("$FreeBSD$"); #include #include +#if defined(__amd64__) +#include +#endif + #include #ifdef __sparc64__ @@ -153,7 +157,7 @@ atkbdc_configure(void) bus_space_tag_t tag; bus_space_handle_t h0; bus_space_handle_t h1; -#if defined(__i386__) +#if defined(__i386__) || defined(__amd64__) volatile int i; register_t flags; #endif @@ -222,7 +226,7 @@ atkbdc_configure(void) #endif #endif -#if defined(__i386__) +#if defined(__i386__) || defined(__amd64__) /* * Check if we really have AT keyboard controller. Poll status * register until we get "all clear" indication. If no such @@ -248,6 +252,11 @@ static int atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, bus_space_handle_t h0, bus_space_handle_t h1) { +#if defined(__amd64__) + u_int64_t tscval[3], read_delay; + register_t flags; +#endif + if (sc->ioh0 == 0) { /* XXX */ sc->command_byte = -1; sc->command_mask = 0; @@ -264,6 +273,33 @@ atkbdc_setup(atkbdc_softc_t *sc, bus_space_tag_t tag, bus_space_handle_t h0, sc->iot = tag; sc->ioh0 = h0; sc->ioh1 = h1; + +#if defined(__amd64__) + /* + * On certain chipsets AT keyboard controller isn't present and is + * emulated by BIOS using SMI interrupt. On those chipsets reading + * from the status port may be thousand times slower than usually. + * Sometimes this emilation is not working properly resulting in + * commands timing our and since we assume that inb() operation + * takes very little time to complete we need to adjust number of + * retries to keep waiting time within a designed limits (100ms). + * Measure time it takes to make read_status() call and adjust + * number of retries accordingly. + */ + flags = intr_disable(); + tscval[0] = rdtsc(); + read_status(sc); + tscval[1] = rdtsc(); + DELAY(1000); + tscval[2] = rdtsc(); + intr_restore(flags); + read_delay = tscval[1] - tscval[0]; + read_delay /= (tscval[2] - tscval[1]) / 1000; + sc->retry = 100000 / ((KBDD_DELAYTIME * 2) + read_delay); +#else + sc->retry = 5000; +#endif + return 0; } @@ -380,10 +416,12 @@ removeq(kqueue *q) static int wait_while_controller_busy(struct atkbdc_softc *kbdc) { - /* CPU will stay inside the loop for 100msec at most */ - int retry = 5000; + int retry; int f; + /* CPU will stay inside the loop for 100msec at most */ + retry = kbdc->retry; + while ((f = read_status(kbdc)) & KBDS_INPUT_BUFFER_FULL) { if ((f & KBDS_BUFFER_FULL) == KBDS_KBD_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); @@ -406,10 +444,12 @@ wait_while_controller_busy(struct atkbdc_softc *kbdc) static int wait_for_data(struct atkbdc_softc *kbdc) { - /* CPU will stay inside the loop for 200msec at most */ - int retry = 10000; + int retry; int f; + /* CPU will stay inside the loop for 200msec at most */ + retry = kbdc->retry * 2; + while ((f = read_status(kbdc) & KBDS_ANY_BUFFER_FULL) == 0) { DELAY(KBDC_DELAYTIME); if (--retry < 0) @@ -423,10 +463,12 @@ wait_for_data(struct atkbdc_softc *kbdc) static int wait_for_kbd_data(struct atkbdc_softc *kbdc) { - /* CPU will stay inside the loop for 200msec at most */ - int retry = 10000; + int retry; int f; + /* CPU will stay inside the loop for 200msec at most */ + retry = kbdc->retry * 2; + while ((f = read_status(kbdc) & KBDS_BUFFER_FULL) != KBDS_KBD_BUFFER_FULL) { if (f == KBDS_AUX_BUFFER_FULL) { @@ -448,11 +490,13 @@ wait_for_kbd_data(struct atkbdc_softc *kbdc) static int wait_for_kbd_ack(struct atkbdc_softc *kbdc) { - /* CPU will stay inside the loop for 200msec at most */ - int retry = 10000; + int retry; int f; int b; + /* CPU will stay inside the loop for 200msec at most */ + retry = kbdc->retry * 2; + while (retry-- > 0) { if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); @@ -475,10 +519,12 @@ wait_for_kbd_ack(struct atkbdc_softc *kbdc) static int wait_for_aux_data(struct atkbdc_softc *kbdc) { - /* CPU will stay inside the loop for 200msec at most */ - int retry = 10000; + int retry; int f; + /* CPU will stay inside the loop for 200msec at most */ + retry = kbdc->retry * 2; + while ((f = read_status(kbdc) & KBDS_BUFFER_FULL) != KBDS_AUX_BUFFER_FULL) { if (f == KBDS_KBD_BUFFER_FULL) { @@ -500,11 +546,13 @@ wait_for_aux_data(struct atkbdc_softc *kbdc) static int wait_for_aux_ack(struct atkbdc_softc *kbdc) { - /* CPU will stay inside the loop for 200msec at most */ - int retry = 10000; + int retry; int f; int b; + /* CPU will stay inside the loop for 200msec at most */ + retry = kbdc->retry * 2; + while (retry-- > 0) { if ((f = read_status(kbdc)) & KBDS_ANY_BUFFER_FULL) { DELAY(KBDD_DELAYTIME); diff --git a/sys/dev/atkbdc/atkbdc_ebus.c b/sys/dev/atkbdc/atkbdc_ebus.c index 639203d..0dcb0a7 100644 --- a/sys/dev/atkbdc/atkbdc_ebus.c +++ b/sys/dev/atkbdc/atkbdc_ebus.c @@ -202,6 +202,7 @@ atkbdc_ebus_attach(device_t dev) "cannot determine command/data port resource\n"); return (ENXIO); } + sc->retry = 5000; sc->port0 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start, 1, RF_ACTIVE); if (sc->port0 == NULL) { diff --git a/sys/dev/atkbdc/atkbdc_isa.c b/sys/dev/atkbdc/atkbdc_isa.c index 975d299..10e172f 100644 --- a/sys/dev/atkbdc/atkbdc_isa.c +++ b/sys/dev/atkbdc/atkbdc_isa.c @@ -94,7 +94,7 @@ atkbdc_isa_probe(device_t dev) u_long count; int error; int rid; -#if defined(__i386__) +#if defined(__i386__) || defined(__amd64__) bus_space_tag_t tag; bus_space_handle_t ioh1; volatile int i; @@ -141,7 +141,7 @@ atkbdc_isa_probe(device_t dev) return ENXIO; } -#if defined(__i386__) +#if defined(__i386__) || defined(__amd64__) /* * Check if we really have AT keyboard controller. Poll status * register until we get "all clear" indication. If no such @@ -161,6 +161,8 @@ atkbdc_isa_probe(device_t dev) if (i == 65535) { bus_release_resource(dev, SYS_RES_IOPORT, 0, port0); bus_release_resource(dev, SYS_RES_IOPORT, 1, port1); + if (bootverbose) + device_printf(dev, "AT keyboard controller not found\n"); return ENXIO; } #endif @@ -201,6 +203,7 @@ atkbdc_isa_attach(device_t dev) } rid = 0; + sc->retry = 5000; sc->port0 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (sc->port0 == NULL) diff --git a/sys/dev/atkbdc/atkbdcreg.h b/sys/dev/atkbdc/atkbdcreg.h index 0715d9e..7ea26a6 100644 --- a/sys/dev/atkbdc/atkbdcreg.h +++ b/sys/dev/atkbdc/atkbdcreg.h @@ -200,6 +200,7 @@ typedef struct atkbdc_softc { int lock; /* FIXME: XXX not quite a semaphore... */ kqueue kbd; /* keyboard data queue */ kqueue aux; /* auxiliary data queue */ + int retry; } atkbdc_softc_t; enum kbdc_device_ivar { -- cgit v1.1 From 294bb61f0d99a150aa80918b52496cba2462c3cd Mon Sep 17 00:00:00 2001 From: nyan Date: Thu, 29 Apr 2010 06:22:07 +0000 Subject: MFi386: revision 206553 - Change printf() calls to uprintf() for sigreturn(). - Normalize the messages to include both pid and thread name. --- sys/pc98/pc98/machdep.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c index f470b5e..e0482e2 100644 --- a/sys/pc98/pc98/machdep.c +++ b/sys/pc98/pc98/machdep.c @@ -874,7 +874,8 @@ freebsd4_sigreturn(td, uap) * one less debugger trap, so allowing it is fairly harmless. */ if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { - printf("freebsd4_sigreturn: eflags = 0x%x\n", eflags); + uprintf("pid %d (%s): freebsd4_sigreturn eflags = 0x%x\n", + td->td_proc->p_pid, td->td_name, eflags); return (EINVAL); } @@ -885,7 +886,8 @@ freebsd4_sigreturn(td, uap) */ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { - printf("freebsd4_sigreturn: cs = 0x%x\n", cs); + uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n", + td->td_proc->p_pid, td->td_name, cs); ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; @@ -986,7 +988,8 @@ sigreturn(td, uap) * one less debugger trap, so allowing it is fairly harmless. */ if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { - printf("sigreturn: eflags = 0x%x\n", eflags); + uprintf("pid %d (%s): sigreturn eflags = 0x%x\n", + td->td_proc->p_pid, td->td_name, eflags); return (EINVAL); } @@ -997,7 +1000,8 @@ sigreturn(td, uap) */ cs = ucp->uc_mcontext.mc_cs; if (!CS_SECURE(cs)) { - printf("sigreturn: cs = 0x%x\n", cs); + uprintf("pid %d (%s): sigreturn cs = 0x%x\n", + td->td_proc->p_pid, td->td_name, cs); ksiginfo_init_trap(&ksi); ksi.ksi_signo = SIGBUS; ksi.ksi_code = BUS_OBJERR; -- cgit v1.1 From cbff4850b6fa646c25141877a2e0455c70564852 Mon Sep 17 00:00:00 2001 From: avg Date: Thu, 29 Apr 2010 09:02:21 +0000 Subject: kern_ntptime: abstract time error check into a function ... to avoid code duplication MFC after: 1 week --- sys/kern/kern_ntptime.c | 50 ++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c index 2d87740..9a4630f8 100644 --- a/sys/kern/kern_ntptime.c +++ b/sys/kern/kern_ntptime.c @@ -198,22 +198,11 @@ static long pps_errcnt; /* calibration errors */ static void ntp_init(void); static void hardupdate(long offset); static void ntp_gettime1(struct ntptimeval *ntvp); +static int ntp_is_time_error(void); -static void -ntp_gettime1(struct ntptimeval *ntvp) +static int +ntp_is_time_error(void) { - struct timespec atv; /* nanosecond time */ - - GIANT_REQUIRED; - - nanotime(&atv); - ntvp->time.tv_sec = atv.tv_sec; - ntvp->time.tv_nsec = atv.tv_nsec; - ntvp->maxerror = time_maxerror; - ntvp->esterror = time_esterror; - ntvp->tai = time_tai; - ntvp->time_state = time_state; - /* * Status word error decode. If any of these conditions occur, * an error is returned, instead of the status word. Most @@ -243,6 +232,27 @@ ntp_gettime1(struct ntptimeval *ntvp) */ (time_status & STA_PPSFREQ && time_status & (STA_PPSWANDER | STA_PPSERROR))) + return (1); + + return (0); +} + +static void +ntp_gettime1(struct ntptimeval *ntvp) +{ + struct timespec atv; /* nanosecond time */ + + GIANT_REQUIRED; + + nanotime(&atv); + ntvp->time.tv_sec = atv.tv_sec; + ntvp->time.tv_nsec = atv.tv_nsec; + ntvp->maxerror = time_maxerror; + ntvp->esterror = time_esterror; + ntvp->tai = time_tai; + ntvp->time_state = time_state; + + if (ntp_is_time_error()) ntvp->time_state = TIME_ERROR; } @@ -446,17 +456,11 @@ ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap) * Status word error decode. See comments in * ntp_gettime() routine. */ - if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || - (time_status & (STA_PPSFREQ | STA_PPSTIME) && - !(time_status & STA_PPSSIGNAL)) || - (time_status & STA_PPSTIME && - time_status & STA_PPSJITTER) || - (time_status & STA_PPSFREQ && - time_status & (STA_PPSWANDER | STA_PPSERROR))) { + if (ntp_is_time_error()) td->td_retval[0] = TIME_ERROR; - } else { + else td->td_retval[0] = time_state; - } + done2: mtx_unlock(&Giant); return (error); -- cgit v1.1 From cce2a4186b6b7e9dda2efd1770167b6c7b146c33 Mon Sep 17 00:00:00 2001 From: avg Date: Thu, 29 Apr 2010 09:02:46 +0000 Subject: periodically save system time to hardware time-of-day clock This is done in kern_ntptime, perhaps not the best place. This is done using resettodr(). Some features: - make save period configurable via tunable and sysctl - period of zero disables saving, setting a non-zero period re-enables it or reschedules it - do saving only if system clock is ntp-synchronized - save on shutdown Discussed with: des, Peter Jeremy X-Maybe: save time near seconds boundary for better precision MFC after: 2 weeks --- sys/kern/kern_ntptime.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c index 9a4630f8..54c4b06b 100644 --- a/sys/kern/kern_ntptime.c +++ b/sys/kern/kern_ntptime.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -976,3 +977,67 @@ kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta) return (0); } +static struct callout resettodr_callout; +static int resettodr_period = 1800; + +static void +periodic_resettodr(void *arg __unused) +{ + + if (!ntp_is_time_error()) { + mtx_lock(&Giant); + resettodr(); + mtx_unlock(&Giant); + } + if (resettodr_period > 0) + callout_schedule(&resettodr_callout, resettodr_period * hz); +} + +static void +shutdown_resettodr(void *arg __unused, int howto __unused) +{ + + callout_drain(&resettodr_callout); + if (resettodr_period > 0 && !ntp_is_time_error()) { + mtx_lock(&Giant); + resettodr(); + mtx_unlock(&Giant); + } +} + +static int +sysctl_resettodr_period(SYSCTL_HANDLER_ARGS) +{ + int error; + + error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); + if (error || !req->newptr) + return (error); + if (resettodr_period == 0) + callout_stop(&resettodr_callout); + else + callout_reset(&resettodr_callout, resettodr_period * hz, + periodic_resettodr, NULL); + return (0); +} + +SYSCTL_PROC(_machdep, OID_AUTO, rtc_save_period, CTLTYPE_INT|CTLFLAG_RW, + &resettodr_period, 1800, sysctl_resettodr_period, "I", + "Save system time to RTC with this period (in seconds)"); +TUNABLE_INT("machdep.rtc_save_period", &resettodr_period); + +static void +start_periodic_resettodr(void *arg __unused) +{ + + EVENTHANDLER_REGISTER(shutdown_pre_sync, shutdown_resettodr, NULL, + SHUTDOWN_PRI_FIRST); + callout_init(&resettodr_callout, 1); + if (resettodr_period == 0) + return; + callout_reset(&resettodr_callout, resettodr_period * hz, + periodic_resettodr, NULL); +} + +SYSINIT(periodic_resettodr, SI_SUB_RUN_SCHEDULER, SI_ORDER_ANY - 1, + start_periodic_resettodr, NULL); -- cgit v1.1 From 2cfe78bdd9305ff8118386d0320e1f54d1b6ffd8 Mon Sep 17 00:00:00 2001 From: avg Date: Thu, 29 Apr 2010 09:18:36 +0000 Subject: kern_ntptime: drop a comment that became stale after r207359 MFC after: 1 week X-MFC after: r207359 --- sys/kern/kern_ntptime.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c index 54c4b06b..c427ac4 100644 --- a/sys/kern/kern_ntptime.c +++ b/sys/kern/kern_ntptime.c @@ -453,10 +453,6 @@ ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap) if (error) goto done2; - /* - * Status word error decode. See comments in - * ntp_gettime() routine. - */ if (ntp_is_time_error()) td->td_retval[0] = TIME_ERROR; else -- cgit v1.1 From a22b32df4a05865bd0f88df37448d94c80df9a3e Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 29 Apr 2010 09:55:51 +0000 Subject: Remove caddr_t casts. Requested by: bde MFC after: 10 days --- sys/kern/kern_proc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 5601ecf..49a3097 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1084,11 +1084,9 @@ sysctl_out_proc_copyout(struct kinfo_proc *ki, struct sysctl_req *req) if (req->flags & SCTL_MASK32) { freebsd32_kinfo_proc_out(ki, &ki32); - error = SYSCTL_OUT(req, (caddr_t)&ki32, - sizeof(struct kinfo_proc32)); + error = SYSCTL_OUT(req, &ki32, sizeof(struct kinfo_proc32)); } else - error = SYSCTL_OUT(req, (caddr_t)ki, - sizeof(struct kinfo_proc)); + error = SYSCTL_OUT(req, ki, sizeof(struct kinfo_proc)); return (error); } #else @@ -1096,7 +1094,7 @@ static int sysctl_out_proc_copyout(struct kinfo_proc *ki, struct sysctl_req *req) { - return (SYSCTL_OUT(req, (caddr_t)ki, sizeof(struct kinfo_proc))); + return (SYSCTL_OUT(req, ki, sizeof(struct kinfo_proc))); } #endif -- cgit v1.1 From b1ef5079faea187e8c41cce0863d90d4d7527cb7 Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 29 Apr 2010 09:57:25 +0000 Subject: In swap pager, do not free the non-requested pages from the run if they are wired. Kstack pages are wired, this change prepares swap pager for handling of long runs of kstack pages. Noted and reviewed by: alc Tested by: pho MFC after: 2 weeks --- sys/vm/swap_pager.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index f1d89d5..f47719b 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -378,6 +378,14 @@ static void swp_pager_meta_free(vm_object_t, vm_pindex_t, daddr_t); static void swp_pager_meta_free_all(vm_object_t); static daddr_t swp_pager_meta_ctl(vm_object_t, vm_pindex_t, int); +static void +swp_pager_free_nrpage(vm_page_t m) +{ + + if (m->wire_count == 0) + vm_page_free(m); +} + /* * SWP_SIZECHECK() - update swap_pager_full indication * @@ -1131,9 +1139,9 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage) vm_page_lock_queues(); for (k = 0; k < i; ++k) - vm_page_free(m[k]); + swp_pager_free_nrpage(m[k]); for (k = j; k < count; ++k) - vm_page_free(m[k]); + swp_pager_free_nrpage(m[k]); vm_page_unlock_queues(); } @@ -1529,7 +1537,7 @@ swp_pager_async_iodone(struct buf *bp) */ m->valid = 0; if (i != bp->b_pager.pg_reqpage) - vm_page_free(m); + swp_pager_free_nrpage(m); else vm_page_flash(m); /* -- cgit v1.1 From 8ec6fa6b8c48d5e5aec45bcce7e5e93e531bb971 Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 29 Apr 2010 09:59:16 +0000 Subject: When doing kstack swapin, read as much pages in one run as possible. Suggested and reviewed by: alc (previous version) Tested by: pho MFC after: 2 weeks --- sys/vm/vm_glue.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index dbd5065d8..4eeaa4d 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -538,23 +538,37 @@ static void vm_thread_swapin(struct thread *td) { vm_object_t ksobj; - vm_page_t m, ma[KSTACK_MAX_PAGES]; - int i, pages, rv; + vm_page_t ma[KSTACK_MAX_PAGES]; + int i, j, k, pages, rv; pages = td->td_kstack_pages; ksobj = td->td_kstack_obj; VM_OBJECT_LOCK(ksobj); - for (i = 0; i < pages; i++) { - m = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY | + for (i = 0; i < pages; i++) + ma[i] = vm_page_grab(ksobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY | VM_ALLOC_WIRED); - if (m->valid != VM_PAGE_BITS_ALL) { - rv = vm_pager_get_pages(ksobj, &m, 1, 0); + for (i = 0; i < pages; i++) { + if (ma[i]->valid != VM_PAGE_BITS_ALL) { + KASSERT(ma[i]->oflags & VPO_BUSY, + ("lost busy 1")); + vm_object_pip_add(ksobj, 1); + for (j = i + 1; j < pages; j++) { + KASSERT(ma[j]->valid == VM_PAGE_BITS_ALL || + (ma[j]->oflags & VPO_BUSY), + ("lost busy 2")); + if (ma[j]->valid == VM_PAGE_BITS_ALL) + break; + } + rv = vm_pager_get_pages(ksobj, ma + i, j - i, 0); if (rv != VM_PAGER_OK) - panic("vm_thread_swapin: cannot get kstack for proc: %d", td->td_proc->p_pid); - m = vm_page_lookup(ksobj, i); - } - ma[i] = m; - vm_page_wakeup(m); + panic("vm_thread_swapin: cannot get kstack for proc: %d", + td->td_proc->p_pid); + vm_object_pip_wakeup(ksobj); + for (k = i; k < j; k++) + ma[k] = vm_page_lookup(ksobj, k); + vm_page_wakeup(ma[i]); + } else if (ma[i]->oflags & VPO_BUSY) + vm_page_wakeup(ma[i]); } VM_OBJECT_UNLOCK(ksobj); pmap_qenter(td->td_kstack, ma, pages); -- cgit v1.1 From 043deeb56455e1129861bf93ec57f03b90200344 Mon Sep 17 00:00:00 2001 From: avg Date: Thu, 29 Apr 2010 10:04:00 +0000 Subject: ffs_vfsops: restore alphabetic order of options in ffs_opts The order was not correct only for nfsv4acls. ("no" prefix is ignored) MFC after: 1 week --- sys/ufs/ffs/ffs_vfsops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index e403368..2963514 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -126,8 +126,8 @@ static struct buf_ops ffs_ops = { static const char *ffs_opts[] = { "acls", "async", "noatime", "noclusterr", "noclusterw", "noexec", "export", "force", "from", "multilabel", - "snapshot", "nosuid", "suiddir", "nosymfollow", "sync", - "union", "nfsv4acls", NULL }; + "nfsv4acls", "snapshot", "nosuid", "suiddir", "nosymfollow", "sync", + "union", NULL }; static int ffs_mount(struct mount *mp) -- cgit v1.1 From 0a90ef17283bc848eee90c3bdd5bec3fcc1bc879 Mon Sep 17 00:00:00 2001 From: bz Date: Thu, 29 Apr 2010 11:52:42 +0000 Subject: MFP4: @176978-176982, 176984, 176990-176994, 177441 "Whitspace" churn after the VIMAGE/VNET whirls. Remove the need for some "init" functions within the network stack, like pim6_init(), icmp_init() or significantly shorten others like ip6_init() and nd6_init(), using static initialization again where possible and formerly missed. Move (most) variables back to the place they used to be before the container structs and VIMAGE_GLOABLS (before r185088) and try to reduce the diff to stable/7 and earlier as good as possible, to help out-of-tree consumers to update from 6.x or 7.x to 8 or 9. This also removes some header file pollution for putatively static global variables. Revert VIMAGE specific changes in ipfilter::ip_auth.c, that are no longer needed. Reviewed by: jhb Discussed with: rwatson Sponsored by: The FreeBSD Foundation Sponsored by: CK Software GmbH MFC after: 6 days --- sys/contrib/ipfilter/netinet/ip_auth.c | 5 -- sys/net/if.c | 6 +- sys/net/if_gif.c | 20 ------ sys/net/if_gif.h | 4 -- sys/net/route.c | 12 ++-- sys/netinet/icmp6.h | 1 - sys/netinet/if_ether.c | 10 ++- sys/netinet/in.c | 11 ++-- sys/netinet/in_gif.c | 2 + sys/netinet/in_proto.c | 1 - sys/netinet/in_rmx.c | 21 +++---- sys/netinet/ip_icmp.c | 59 ++++++------------ sys/netinet/ip_icmp.h | 1 - sys/netinet/ip_input.c | 72 ++++++++++------------ sys/netinet/ip_var.h | 13 ++-- sys/netinet/tcp_hostcache.c | 4 +- sys/netinet/tcp_input.c | 39 +++++++----- sys/netinet/tcp_output.c | 21 ++++--- sys/netinet/tcp_reass.c | 21 +++---- sys/netinet/tcp_sack.c | 17 +++--- sys/netinet/tcp_subr.c | 90 +++++++-------------------- sys/netinet/tcp_syncache.c | 19 +++--- sys/netinet/tcp_timewait.c | 8 +-- sys/netinet/tcp_var.h | 56 ++--------------- sys/netinet/udp_usrreq.c | 7 +-- sys/netinet/udp_var.h | 10 ++- sys/netinet6/frag6.c | 5 +- sys/netinet6/icmp6.c | 21 ++----- sys/netinet6/in6_gif.c | 9 +++ sys/netinet6/in6_ifattach.c | 11 +++- sys/netinet6/in6_proto.c | 84 ++++++++++++++++---------- sys/netinet6/in6_rmx.c | 23 +++---- sys/netinet6/in6_src.c | 7 +-- sys/netinet6/in6_var.h | 9 ++- sys/netinet6/ip6_input.c | 107 ++++----------------------------- sys/netinet6/ip6_mroute.c | 19 +----- sys/netinet6/ip6_var.h | 53 ++++++++-------- sys/netinet6/nd6.c | 77 +++++++----------------- sys/netinet6/nd6.h | 9 ++- sys/netinet6/nd6_nbr.c | 8 +-- sys/netinet6/nd6_rtr.c | 12 ++-- sys/netinet6/raw_ip6.c | 4 +- sys/netinet6/scope6.c | 12 ++-- sys/netipsec/ah_var.h | 5 +- sys/netipsec/esp_var.h | 3 +- sys/netipsec/ipcomp_var.h | 3 +- sys/netipsec/ipip_var.h | 3 +- sys/netipsec/ipsec.c | 1 + sys/netipsec/ipsec.h | 44 +++++++------- sys/netipsec/ipsec6.h | 11 ++-- sys/netipsec/key.c | 21 ++++--- sys/netipsec/xform_esp.c | 3 +- 52 files changed, 412 insertions(+), 682 deletions(-) diff --git a/sys/contrib/ipfilter/netinet/ip_auth.c b/sys/contrib/ipfilter/netinet/ip_auth.c index 19a12f4..42d29d4 100644 --- a/sys/contrib/ipfilter/netinet/ip_auth.c +++ b/sys/contrib/ipfilter/netinet/ip_auth.c @@ -70,11 +70,6 @@ struct file; #include #include #include -#if !defined(_KERNEL) && defined(__FreeBSD_version) && \ - __FreeBSD_version >= 800049 -# define V_ip_do_randomid ip_do_randomid -# define V_ip_id ip_id -#endif #if !defined(_KERNEL) && !defined(__osf__) && !defined(__sgi) # define KERNEL # define _KERNEL diff --git a/sys/net/if.c b/sys/net/if.c index 98c8afa..1acfb24 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -163,9 +163,11 @@ static void if_detach_internal(struct ifnet *, int); extern void nd6_setmtu(struct ifnet *); #endif +VNET_DEFINE(int, if_index); +int ifqmaxlen = IFQ_MAXLEN; VNET_DEFINE(struct ifnethead, ifnet); /* depend on static init XXX */ VNET_DEFINE(struct ifgrouphead, ifg_head); -VNET_DEFINE(int, if_index); + static VNET_DEFINE(int, if_indexlim) = 8; /* Table of ifnet by index. */ @@ -174,8 +176,6 @@ static VNET_DEFINE(struct ifindex_entry *, ifindex_table); #define V_if_indexlim VNET(if_indexlim) #define V_ifindex_table VNET(ifindex_table) -int ifqmaxlen = IFQ_MAXLEN; - /* * The global network interface list (V_ifnet) and related state (such as * if_index, if_indexlim, and ifindex_table) are protected by an sxlock and diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 22ef6ab..ae0ff4e 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -94,20 +94,9 @@ */ static struct mtx gif_mtx; static MALLOC_DEFINE(M_GIF, "gif", "Generic Tunnel Interface"); - static VNET_DEFINE(LIST_HEAD(, gif_softc), gif_softc_list); - #define V_gif_softc_list VNET(gif_softc_list) -#ifdef INET -VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL; -#define V_ip_gif_ttl VNET(ip_gif_ttl) -#endif -#ifdef INET6 -VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM; -#define V_ip6_gif_hlim VNET(ip6_gif_hlim) -#endif - void (*ng_gif_input_p)(struct ifnet *ifp, struct mbuf **mp, int af); void (*ng_gif_input_orphan_p)(struct ifnet *ifp, struct mbuf *m, int af); void (*ng_gif_attach_p)(struct ifnet *ifp); @@ -135,19 +124,11 @@ SYSCTL_NODE(_net_link, IFT_GIF, gif, CTLFLAG_RW, 0, */ #define MAX_GIF_NEST 1 #endif - static VNET_DEFINE(int, max_gif_nesting) = MAX_GIF_NEST; #define V_max_gif_nesting VNET(max_gif_nesting) - SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, max_nesting, CTLFLAG_RW, &VNET_NAME(max_gif_nesting), 0, "Max nested tunnels"); -#ifdef INET6 -SYSCTL_DECL(_net_inet6_ip6); -SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW, - &VNET_NAME(ip6_gif_hlim), 0, ""); -#endif - /* * By default, we disallow creation of multiple tunnels between the same * pair of addresses. Some applications require this functionality so @@ -159,7 +140,6 @@ static VNET_DEFINE(int, parallel_tunnels) = 1; static VNET_DEFINE(int, parallel_tunnels) = 0; #endif #define V_parallel_tunnels VNET(parallel_tunnels) - SYSCTL_VNET_INT(_net_link_gif, OID_AUTO, parallel_tunnels, CTLFLAG_RW, &VNET_NAME(parallel_tunnels), 0, "Allow parallel tunnels?"); diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h index 18b7831..5d0db6d 100644 --- a/sys/net/if_gif.h +++ b/sys/net/if_gif.h @@ -118,10 +118,6 @@ int gif_ioctl(struct ifnet *, u_long, caddr_t); int gif_set_tunnel(struct ifnet *, struct sockaddr *, struct sockaddr *); void gif_delete_tunnel(struct ifnet *); int gif_encapcheck(const struct mbuf *, int, int, void *); - -VNET_DECLARE(int, ip_gif_ttl); -#define V_ip_gif_ttl VNET(ip_gif_ttl) - #endif /* _KERNEL */ #define GIFGOPTS _IOWR('i', 150, struct ifreq) diff --git a/sys/net/route.c b/sys/net/route.c index e500ed1..b45361e 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -88,15 +88,14 @@ SYSCTL_INT(_net, OID_AUTO, add_addr_allfibs, CTLFLAG_RW, &rt_add_addr_allfibs, 0, ""); TUNABLE_INT("net.add_addr_allfibs", &rt_add_addr_allfibs); -VNET_DEFINE(struct radix_node_head *, rt_tables); -static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */ -VNET_DEFINE(int, rttrash); /* routes not in table but not freed */ VNET_DEFINE(struct rtstat, rtstat); +#define V_rtstat VNET(rtstat) +VNET_DEFINE(struct radix_node_head *, rt_tables); #define V_rt_tables VNET(rt_tables) -#define V_rtzone VNET(rtzone) + +VNET_DEFINE(int, rttrash); /* routes not in table but not freed */ #define V_rttrash VNET(rttrash) -#define V_rtstat VNET(rtstat) /* compare two sockaddr structures */ @@ -114,6 +113,9 @@ VNET_DEFINE(struct rtstat, rtstat); */ #define RNTORT(p) ((struct rtentry *)(p)) +static VNET_DEFINE(uma_zone_t, rtzone); /* Routing table UMA zone. */ +#define V_rtzone VNET(rtzone) + #if 0 /* default fib for tunnels to use */ u_int tunnel_fib = 0; diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h index c3a8ac7..5faae7c 100644 --- a/sys/netinet/icmp6.h +++ b/sys/netinet/icmp6.h @@ -652,7 +652,6 @@ struct rtentry; struct rttimer; struct in6_multi; # endif -void icmp6_init(void); void icmp6_paramerror(struct mbuf *, int); void icmp6_error(struct mbuf *, int, int, int); void icmp6_error2(struct mbuf *, int, int, int, struct ifnet *); diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 25fba9f..08a162f 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -82,16 +82,15 @@ SYSCTL_DECL(_net_link_ether); SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, ""); -VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for - * local traffic */ - /* timer values */ static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20 * minutes */ +static VNET_DEFINE(int, arp_maxtries) = 5; +VNET_DEFINE(int, useloopback) = 1; /* use loopback interface for + * local traffic */ +static VNET_DEFINE(int, arp_proxyall) = 0; static VNET_DEFINE(int, arpt_down) = 20; /* keep incomplete entries for * 20 seconds */ -static VNET_DEFINE(int, arp_maxtries) = 5; -static VNET_DEFINE(int, arp_proxyall); static VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */ #define V_arpt_keep VNET(arpt_keep) @@ -103,7 +102,6 @@ static VNET_DEFINE(struct arpstat, arpstat); /* ARP statistics, see if_arp.h */ SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, &VNET_NAME(arpt_keep), 0, "ARP entry lifetime in seconds"); - SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, maxtries, CTLFLAG_RW, &VNET_NAME(arp_maxtries), 0, "ARP resolution attempts before returning error"); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 0a0fe47..96bfa0e 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -77,20 +77,19 @@ static int in_ifinit(struct ifnet *, static void in_purgemaddrs(struct ifnet *); static VNET_DEFINE(int, subnetsarelocal); -static VNET_DEFINE(int, sameprefixcarponly); -VNET_DECLARE(struct inpcbinfo, ripcbinfo); - #define V_subnetsarelocal VNET(subnetsarelocal) -#define V_sameprefixcarponly VNET(sameprefixcarponly) -#define V_ripcbinfo VNET(ripcbinfo) - SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, subnets_are_local, CTLFLAG_RW, &VNET_NAME(subnetsarelocal), 0, "Treat all subnets as directly connected"); +static VNET_DEFINE(int, sameprefixcarponly); +#define V_sameprefixcarponly VNET(sameprefixcarponly) SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW, &VNET_NAME(sameprefixcarponly), 0, "Refuse to create same prefixes on different interfaces"); +VNET_DECLARE(struct inpcbinfo, ripcbinfo); +#define V_ripcbinfo VNET(ripcbinfo) + /* * Return 1 if an internet address is for a ``local'' host * (one to which we have a connection). If subnetsarelocal diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c index 44b9961..6c60390 100644 --- a/sys/netinet/in_gif.c +++ b/sys/netinet/in_gif.c @@ -85,6 +85,8 @@ struct protosw in_gif_protosw = { .pr_usrreqs = &rip_usrreqs }; +VNET_DEFINE(int, ip_gif_ttl) = GIF_TTL; +#define V_ip_gif_ttl VNET(ip_gif_ttl) SYSCTL_VNET_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW, &VNET_NAME(ip_gif_ttl), 0, ""); diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c index d9cab84..6d72fbe 100644 --- a/sys/netinet/in_proto.c +++ b/sys/netinet/in_proto.c @@ -208,7 +208,6 @@ struct protosw inetsw[] = { .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, .pr_input = icmp_input, .pr_ctloutput = rip_ctloutput, - .pr_init = icmp_init, .pr_usrreqs = &rip_usrreqs }, { diff --git a/sys/netinet/in_rmx.c b/sys/netinet/in_rmx.c index 6516277..5b8e0f6 100644 --- a/sys/netinet/in_rmx.c +++ b/sys/netinet/in_rmx.c @@ -131,22 +131,22 @@ in_matroute(void *v_arg, struct radix_node_head *head) return rn; } -static VNET_DEFINE(int, rtq_reallyold); -static VNET_DEFINE(int, rtq_minreallyold); -static VNET_DEFINE(int, rtq_toomany); - +static VNET_DEFINE(int, rtq_reallyold) = 60*60; /* one hour is "really old" */ #define V_rtq_reallyold VNET(rtq_reallyold) -#define V_rtq_minreallyold VNET(rtq_minreallyold) -#define V_rtq_toomany VNET(rtq_toomany) - SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTEXPIRE, rtexpire, CTLFLAG_RW, &VNET_NAME(rtq_reallyold), 0, "Default expiration time on dynamically learned routes"); +/* never automatically crank down to less */ +static VNET_DEFINE(int, rtq_minreallyold) = 10; +#define V_rtq_minreallyold VNET(rtq_minreallyold) SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW, &VNET_NAME(rtq_minreallyold), 0, "Minimum time to attempt to hold onto dynamically learned routes"); +/* 128 cached routes is "too many" */ +static VNET_DEFINE(int, rtq_toomany) = 128; +#define V_rtq_toomany VNET(rtq_toomany) SYSCTL_VNET_INT(_net_inet_ip, IPCTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW, &VNET_NAME(rtq_toomany), 0, "Upper limit on dynamically learned routes"); @@ -239,7 +239,7 @@ in_rtqkill(struct radix_node *rn, void *rock) } #define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */ -static VNET_DEFINE(int, rtq_timeout); +static VNET_DEFINE(int, rtq_timeout) = RTQ_TIMEOUT; static VNET_DEFINE(struct callout, rtq_timer); #define V_rtq_timeout VNET(rtq_timeout) @@ -362,11 +362,6 @@ in_inithead(void **head, int off) if (off == 0) /* XXX MRT see above */ return 1; /* only do the rest for a real routing table */ - V_rtq_reallyold = 60*60; /* one hour is "really old" */ - V_rtq_minreallyold = 10; /* never automatically crank down to less */ - V_rtq_toomany = 128; /* 128 cached routes is "too many" */ - V_rtq_timeout = RTQ_TIMEOUT; - rnh = *head; rnh->rnh_addaddr = in_addroute; rnh->rnh_matchaddr = in_matroute; diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c index b13bc7c..8dc08d9 100644 --- a/sys/netinet/ip_icmp.c +++ b/sys/netinet/ip_icmp.c @@ -75,65 +75,60 @@ __FBSDID("$FreeBSD$"); * routines to turnaround packets back to the originator, and * host table maintenance routines. */ - VNET_DEFINE(struct icmpstat, icmpstat); -static VNET_DEFINE(int, icmpmaskrepl); -static VNET_DEFINE(u_int, icmpmaskfake); -static VNET_DEFINE(int, drop_redirect); -static VNET_DEFINE(int, log_redirect); -static VNET_DEFINE(int, icmplim); -static VNET_DEFINE(int, icmplim_output); -static VNET_DEFINE(char, reply_src[IFNAMSIZ]); -static VNET_DEFINE(int, icmp_rfi); -static VNET_DEFINE(int, icmp_quotelen); -static VNET_DEFINE(int, icmpbmcastecho); - -#define V_icmpmaskrepl VNET(icmpmaskrepl) -#define V_icmpmaskfake VNET(icmpmaskfake) -#define V_drop_redirect VNET(drop_redirect) -#define V_log_redirect VNET(log_redirect) -#define V_icmplim VNET(icmplim) -#define V_icmplim_output VNET(icmplim_output) -#define V_reply_src VNET(reply_src) -#define V_icmp_rfi VNET(icmp_rfi) -#define V_icmp_quotelen VNET(icmp_quotelen) -#define V_icmpbmcastecho VNET(icmpbmcastecho) - SYSCTL_VNET_STRUCT(_net_inet_icmp, ICMPCTL_STATS, stats, CTLFLAG_RW, &VNET_NAME(icmpstat), icmpstat, ""); +static VNET_DEFINE(int, icmpmaskrepl) = 0; +#define V_icmpmaskrepl VNET(icmpmaskrepl) SYSCTL_VNET_INT(_net_inet_icmp, ICMPCTL_MASKREPL, maskrepl, CTLFLAG_RW, &VNET_NAME(icmpmaskrepl), 0, "Reply to ICMP Address Mask Request packets."); +static VNET_DEFINE(u_int, icmpmaskfake) = 0; +#define V_icmpmaskfake VNET(icmpmaskfake) SYSCTL_VNET_UINT(_net_inet_icmp, OID_AUTO, maskfake, CTLFLAG_RW, &VNET_NAME(icmpmaskfake), 0, "Fake reply to ICMP Address Mask Request packets."); +static VNET_DEFINE(int, drop_redirect) = 0; +#define V_drop_redirect VNET(drop_redirect) SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, drop_redirect, CTLFLAG_RW, &VNET_NAME(drop_redirect), 0, "Ignore ICMP redirects"); +static VNET_DEFINE(int, log_redirect) = 0; +#define V_log_redirect VNET(log_redirect) SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, log_redirect, CTLFLAG_RW, &VNET_NAME(log_redirect), 0, "Log ICMP redirects to the console"); +static VNET_DEFINE(int, icmplim) = 200; +#define V_icmplim VNET(icmplim) SYSCTL_VNET_INT(_net_inet_icmp, ICMPCTL_ICMPLIM, icmplim, CTLFLAG_RW, &VNET_NAME(icmplim), 0, "Maximum number of ICMP responses per second"); +static VNET_DEFINE(int, icmplim_output) = 1; +#define V_icmplim_output VNET(icmplim_output) SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, icmplim_output, CTLFLAG_RW, &VNET_NAME(icmplim_output), 0, "Enable rate limiting of ICMP responses"); +static VNET_DEFINE(char, reply_src[IFNAMSIZ]); +#define V_reply_src VNET(reply_src) SYSCTL_VNET_STRING(_net_inet_icmp, OID_AUTO, reply_src, CTLFLAG_RW, &VNET_NAME(reply_src), IFNAMSIZ, "icmp reply source for non-local packets."); +static VNET_DEFINE(int, icmp_rfi) = 0; +#define V_icmp_rfi VNET(icmp_rfi) SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, reply_from_interface, CTLFLAG_RW, &VNET_NAME(icmp_rfi), 0, "ICMP reply from incoming interface for non-local packets"); +static VNET_DEFINE(int, icmp_quotelen) = 8; +#define V_icmp_quotelen VNET(icmp_quotelen) SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, quotelen, CTLFLAG_RW, &VNET_NAME(icmp_quotelen), 0, "Number of bytes from original packet to quote in ICMP reply"); @@ -141,7 +136,8 @@ SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, quotelen, CTLFLAG_RW, /* * ICMP broadcast echo sysctl */ - +static VNET_DEFINE(int, icmpbmcastecho) = 0; +#define V_icmpbmcastecho VNET(icmpbmcastecho) SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, bmcastecho, CTLFLAG_RW, &VNET_NAME(icmpbmcastecho), 0, ""); @@ -156,21 +152,6 @@ static void icmp_send(struct mbuf *, struct mbuf *); extern struct protosw inetsw[]; -void -icmp_init(void) -{ - - V_icmpmaskrepl = 0; - V_icmpmaskfake = 0; - V_drop_redirect = 0; - V_log_redirect = 0; - V_icmplim = 200; - V_icmplim_output = 1; - V_icmp_rfi = 0; - V_icmp_quotelen = 8; - V_icmpbmcastecho = 0; -} - /* * Kernel module interface for updating icmpstat. The argument is an index * into icmpstat treated as an array of u_long. While this encodes the diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h index e4ee7f7..9cabdb5 100644 --- a/sys/netinet/ip_icmp.h +++ b/sys/netinet/ip_icmp.h @@ -208,7 +208,6 @@ struct icmp { #ifdef _KERNEL void icmp_error(struct mbuf *, int, int, uint32_t, int); void icmp_input(struct mbuf *, int); -void icmp_init(void); int ip_next_mtu(int, int); #endif diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index fdef645..a17907c 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -89,66 +89,40 @@ __FBSDID("$FreeBSD$"); CTASSERT(sizeof(struct ip) == 20); #endif -static VNET_DEFINE(int, ipsendredirects) = 1; /* XXX */ -static VNET_DEFINE(int, ip_checkinterface); -static VNET_DEFINE(int, ip_keepfaith); -static VNET_DEFINE(int, ip_sendsourcequench); - -#define V_ipsendredirects VNET(ipsendredirects) -#define V_ip_checkinterface VNET(ip_checkinterface) -#define V_ip_keepfaith VNET(ip_keepfaith) -#define V_ip_sendsourcequench VNET(ip_sendsourcequench) - -VNET_DEFINE(int, ip_defttl) = IPDEFTTL; -VNET_DEFINE(int, ip_do_randomid); -VNET_DEFINE(int, ipforwarding); - -VNET_DEFINE(struct in_ifaddrhead, in_ifaddrhead); /* first inet address */ -VNET_DEFINE(struct in_ifaddrhashhead *, in_ifaddrhashtbl); /* inet addr hash table */ -VNET_DEFINE(u_long, in_ifaddrhmask); /* mask for hash table */ -VNET_DEFINE(struct ipstat, ipstat); - -static VNET_DEFINE(int, ip_rsvp_on); -VNET_DEFINE(struct socket *, ip_rsvpd); -VNET_DEFINE(int, rsvp_on); - -#define V_ip_rsvp_on VNET(ip_rsvp_on) - -static VNET_DEFINE(TAILQ_HEAD(ipqhead, ipq), ipq[IPREASS_NHASH]); -static VNET_DEFINE(int, maxnipq); /* Administrative limit on # reass queues. */ -static VNET_DEFINE(int, maxfragsperpacket); -static VNET_DEFINE(int, nipq); /* Total # of reass queues */ - -#define V_ipq VNET(ipq) -#define V_maxnipq VNET(maxnipq) -#define V_maxfragsperpacket VNET(maxfragsperpacket) -#define V_nipq VNET(nipq) - -VNET_DEFINE(int, ipstealth); - struct rwlock in_ifaddr_lock; RW_SYSINIT(in_ifaddr_lock, &in_ifaddr_lock, "in_ifaddr_lock"); +VNET_DEFINE(int, rsvp_on); + +VNET_DEFINE(int, ipforwarding); SYSCTL_VNET_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW, &VNET_NAME(ipforwarding), 0, "Enable IP forwarding between interfaces"); +static VNET_DEFINE(int, ipsendredirects) = 1; /* XXX */ +#define V_ipsendredirects VNET(ipsendredirects) SYSCTL_VNET_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW, &VNET_NAME(ipsendredirects), 0, "Enable sending IP redirects"); +VNET_DEFINE(int, ip_defttl) = IPDEFTTL; SYSCTL_VNET_INT(_net_inet_ip, IPCTL_DEFTTL, ttl, CTLFLAG_RW, &VNET_NAME(ip_defttl), 0, "Maximum TTL on IP packets"); +static VNET_DEFINE(int, ip_keepfaith); +#define V_ip_keepfaith VNET(ip_keepfaith) SYSCTL_VNET_INT(_net_inet_ip, IPCTL_KEEPFAITH, keepfaith, CTLFLAG_RW, &VNET_NAME(ip_keepfaith), 0, "Enable packet capture for FAITH IPv4->IPv6 translater daemon"); +static VNET_DEFINE(int, ip_sendsourcequench); +#define V_ip_sendsourcequench VNET(ip_sendsourcequench) SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, sendsourcequench, CTLFLAG_RW, &VNET_NAME(ip_sendsourcequench), 0, "Enable the transmission of source quench packets"); +VNET_DEFINE(int, ip_do_randomid); SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, random_id, CTLFLAG_RW, &VNET_NAME(ip_do_randomid), 0, "Assign random ip_id values"); @@ -166,6 +140,8 @@ SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, random_id, CTLFLAG_RW, * to the loopback interface instead of the interface where the * packets for those addresses are received. */ +static VNET_DEFINE(int, ip_checkinterface); +#define V_ip_checkinterface VNET(ip_checkinterface) SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_RW, &VNET_NAME(ip_checkinterface), 0, "Verify packet arrives on correct interface"); @@ -182,16 +158,22 @@ static struct netisr_handler ip_nh = { extern struct domain inetdomain; extern struct protosw inetsw[]; u_char ip_protox[IPPROTO_MAX]; +VNET_DEFINE(struct in_ifaddrhead, in_ifaddrhead); /* first inet address */ +VNET_DEFINE(struct in_ifaddrhashhead *, in_ifaddrhashtbl); /* inet addr hash table */ +VNET_DEFINE(u_long, in_ifaddrhmask); /* mask for hash table */ +VNET_DEFINE(struct ipstat, ipstat); SYSCTL_VNET_STRUCT(_net_inet_ip, IPCTL_STATS, stats, CTLFLAG_RW, &VNET_NAME(ipstat), ipstat, "IP statistics (struct ipstat, netinet/ip_var.h)"); static VNET_DEFINE(uma_zone_t, ipq_zone); -#define V_ipq_zone VNET(ipq_zone) - +static VNET_DEFINE(TAILQ_HEAD(ipqhead, ipq), ipq[IPREASS_NHASH]); static struct mtx ipqlock; +#define V_ipq_zone VNET(ipq_zone) +#define V_ipq VNET(ipq) + #define IPQ_LOCK() mtx_lock(&ipqlock) #define IPQ_UNLOCK() mtx_unlock(&ipqlock) #define IPQ_LOCK_INIT() mtx_init(&ipqlock, "ipqlock", NULL, MTX_DEF) @@ -201,10 +183,16 @@ static void maxnipq_update(void); static void ipq_zone_change(void *); static void ip_drain_locked(void); +static VNET_DEFINE(int, maxnipq); /* Administrative limit on # reass queues. */ +static VNET_DEFINE(int, nipq); /* Total # of reass queues */ +#define V_maxnipq VNET(maxnipq) +#define V_nipq VNET(nipq) SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, fragpackets, CTLFLAG_RD, &VNET_NAME(nipq), 0, "Current number of IPv4 fragment reassembly queue entries"); +static VNET_DEFINE(int, maxfragsperpacket); +#define V_maxfragsperpacket VNET(maxfragsperpacket) SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, maxfragsperpacket, CTLFLAG_RW, &VNET_NAME(maxfragsperpacket), 0, "Maximum number of IPv4 fragments allowed per packet"); @@ -217,6 +205,7 @@ SYSCTL_INT(_net_inet_ip, IPCTL_DEFMTU, mtu, CTLFLAG_RW, #endif #ifdef IPSTEALTH +VNET_DEFINE(int, ipstealth); SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, stealth, CTLFLAG_RW, &VNET_NAME(ipstealth), 0, "IP stealth mode, no TTL decrementation on forwarding"); @@ -1740,6 +1729,11 @@ makedummy: * locking. This code remains in ip_input.c as ip_mroute.c is optionally * compiled. */ +static VNET_DEFINE(int, ip_rsvp_on); +VNET_DEFINE(struct socket *, ip_rsvpd); + +#define V_ip_rsvp_on VNET(ip_rsvp_on) + int ip_rsvp_init(struct socket *so) { diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 389ad6e..4415001 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -181,9 +181,13 @@ VNET_DECLARE(int, ipforwarding); /* ip forwarding */ #ifdef IPSTEALTH VNET_DECLARE(int, ipstealth); /* stealth forwarding */ #endif -VNET_DECLARE(int, rsvp_on); +extern u_char ip_protox[]; VNET_DECLARE(struct socket *, ip_rsvpd); /* reservation protocol daemon*/ VNET_DECLARE(struct socket *, ip_mrouter); /* multicast routing daemon */ +extern int (*legal_vif_num)(int); +extern u_long (*ip_mcast_src)(int); +VNET_DECLARE(int, rsvp_on); +extern struct pr_usrreqs rip_usrreqs; #define V_ipstat VNET(ipstat) #define V_ip_id VNET(ip_id) @@ -192,14 +196,9 @@ VNET_DECLARE(struct socket *, ip_mrouter); /* multicast routing daemon */ #ifdef IPSTEALTH #define V_ipstealth VNET(ipstealth) #endif -#define V_rsvp_on VNET(rsvp_on) #define V_ip_rsvpd VNET(ip_rsvpd) #define V_ip_mrouter VNET(ip_mrouter) - -extern u_char ip_protox[]; -extern int (*legal_vif_num)(int); -extern u_long (*ip_mcast_src)(int); -extern struct pr_usrreqs rip_usrreqs; +#define V_rsvp_on VNET(rsvp_on) void inp_freemoptions(struct ip_moptions *); int inp_getmoptions(struct inpcb *, struct sockopt *); diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c index a0c4012..d20adb7 100644 --- a/sys/netinet/tcp_hostcache.c +++ b/sys/netinet/tcp_hostcache.c @@ -107,9 +107,9 @@ __FBSDID("$FreeBSD$"); #define TCP_HOSTCACHE_PRUNE 5*60 /* every 5 minutes */ static VNET_DEFINE(struct tcp_hostcache, tcp_hostcache); -static VNET_DEFINE(struct callout, tcp_hc_callout); - #define V_tcp_hostcache VNET(tcp_hostcache) + +static VNET_DEFINE(struct callout, tcp_hc_callout); #define V_tcp_hc_callout VNET(tcp_hc_callout) static struct hc_metrics *tcp_hc_lookup(struct in_conninfo *); diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 0254cff..cbba9cd 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -99,20 +99,6 @@ __FBSDID("$FreeBSD$"); static const int tcprexmtthresh = 3; VNET_DEFINE(struct tcpstat, tcpstat); -VNET_DEFINE(int, blackhole); -VNET_DEFINE(int, tcp_delack_enabled); -VNET_DEFINE(int, drop_synfin); -VNET_DEFINE(int, tcp_do_rfc3042); -VNET_DEFINE(int, tcp_do_rfc3390); -VNET_DEFINE(int, tcp_do_ecn); -VNET_DEFINE(int, tcp_ecn_maxretries); -VNET_DEFINE(int, tcp_insecure_rst); -VNET_DEFINE(int, tcp_do_autorcvbuf); -VNET_DEFINE(int, tcp_autorcvbuf_inc); -VNET_DEFINE(int, tcp_autorcvbuf_max); -VNET_DEFINE(int, tcp_do_rfc3465); -VNET_DEFINE(int, tcp_abc_l_var); - SYSCTL_VNET_STRUCT(_net_inet_tcp, TCPCTL_STATS, stats, CTLFLAG_RW, &VNET_NAME(tcpstat), tcpstat, "TCP statistics (struct tcpstat, netinet/tcp_var.h)"); @@ -122,56 +108,79 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_RW, &tcp_log_in_vain, 0, "Log all incoming TCP segments to closed ports"); +VNET_DEFINE(int, blackhole) = 0; +#define V_blackhole VNET(blackhole) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, blackhole, CTLFLAG_RW, &VNET_NAME(blackhole), 0, "Do not send RST on segments to closed ports"); +VNET_DEFINE(int, tcp_delack_enabled) = 1; SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, delayed_ack, CTLFLAG_RW, &VNET_NAME(tcp_delack_enabled), 0, "Delay ACK to try and piggyback it onto a data packet"); +VNET_DEFINE(int, drop_synfin) = 0; +#define V_drop_synfin VNET(drop_synfin) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, drop_synfin, CTLFLAG_RW, &VNET_NAME(drop_synfin), 0, "Drop TCP packets with SYN+FIN set"); +VNET_DEFINE(int, tcp_do_rfc3042) = 1; +#define V_tcp_do_rfc3042 VNET(tcp_do_rfc3042) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3042, CTLFLAG_RW, &VNET_NAME(tcp_do_rfc3042), 0, "Enable RFC 3042 (Limited Transmit)"); +VNET_DEFINE(int, tcp_do_rfc3390) = 1; +#define V_tcp_do_rfc3390 VNET(tcp_do_rfc3390) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3390, CTLFLAG_RW, &VNET_NAME(tcp_do_rfc3390), 0, "Enable RFC 3390 (Increasing TCP's Initial Congestion Window)"); +VNET_DEFINE(int, tcp_do_rfc3465) = 1; +#define V_tcp_do_rfc3465 VNET(tcp_do_rfc3465) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, rfc3465, CTLFLAG_RW, &VNET_NAME(tcp_do_rfc3465), 0, "Enable RFC 3465 (Appropriate Byte Counting)"); +VNET_DEFINE(int, tcp_abc_l_var) = 2; +#define V_tcp_abc_l_var VNET(tcp_abc_l_var) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, abc_l_var, CTLFLAG_RW, &VNET_NAME(tcp_abc_l_var), 2, "Cap the max cwnd increment during slow-start to this number of segments"); SYSCTL_NODE(_net_inet_tcp, OID_AUTO, ecn, CTLFLAG_RW, 0, "TCP ECN"); +VNET_DEFINE(int, tcp_do_ecn) = 0; SYSCTL_VNET_INT(_net_inet_tcp_ecn, OID_AUTO, enable, CTLFLAG_RW, &VNET_NAME(tcp_do_ecn), 0, "TCP ECN support"); +VNET_DEFINE(int, tcp_ecn_maxretries) = 1; SYSCTL_VNET_INT(_net_inet_tcp_ecn, OID_AUTO, maxretries, CTLFLAG_RW, &VNET_NAME(tcp_ecn_maxretries), 0, "Max retries before giving up on ECN"); +VNET_DEFINE(int, tcp_insecure_rst) = 0; +#define V_tcp_insecure_rst VNET(tcp_insecure_rst) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, insecure_rst, CTLFLAG_RW, &VNET_NAME(tcp_insecure_rst), 0, "Follow the old (insecure) criteria for accepting RST packets"); +VNET_DEFINE(int, tcp_do_autorcvbuf) = 1; +#define V_tcp_do_autorcvbuf VNET(tcp_do_autorcvbuf) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_RW, &VNET_NAME(tcp_do_autorcvbuf), 0, "Enable automatic receive buffer sizing"); +VNET_DEFINE(int, tcp_autorcvbuf_inc) = 16*1024; +#define V_tcp_autorcvbuf_inc VNET(tcp_autorcvbuf_inc) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_inc, CTLFLAG_RW, &VNET_NAME(tcp_autorcvbuf_inc), 0, "Incrementor step size of automatic receive buffer"); +VNET_DEFINE(int, tcp_autorcvbuf_max) = 256*1024; +#define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_RW, &VNET_NAME(tcp_autorcvbuf_max), 0, "Max size of automatic receive buffer"); @@ -181,8 +190,8 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, read_locking, CTLFLAG_RW, &tcp_read_locking, 0, "Enable read locking strategy"); VNET_DEFINE(struct inpcbhead, tcb); -VNET_DEFINE(struct inpcbinfo, tcbinfo); #define tcb6 tcb /* for KAME src sync over BSD*'s */ +VNET_DEFINE(struct inpcbinfo, tcbinfo); static void tcp_dooptions(struct tcpopt *, u_char *, int, int); static void tcp_do_segment(struct mbuf *, struct tcphdr *, diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index f9d1b63..50973c4 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -87,43 +87,46 @@ __FBSDID("$FreeBSD$"); extern struct mbuf *m_copypack(); #endif -VNET_DEFINE(int, path_mtu_discovery); -VNET_DEFINE(int, ss_fltsz); -VNET_DEFINE(int, ss_fltsz_local); -VNET_DEFINE(int, tcp_do_newreno); -VNET_DEFINE(int, tcp_do_tso); -VNET_DEFINE(int, tcp_do_autosndbuf); -VNET_DEFINE(int, tcp_autosndbuf_inc); -VNET_DEFINE(int, tcp_autosndbuf_max); - +VNET_DEFINE(int, path_mtu_discovery) = 1; SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, path_mtu_discovery, CTLFLAG_RW, &VNET_NAME(path_mtu_discovery), 1, "Enable Path MTU Discovery"); +VNET_DEFINE(int, ss_fltsz) = 1; SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, slowstart_flightsize, CTLFLAG_RW, &VNET_NAME(ss_fltsz), 1, "Slow start flight size"); +VNET_DEFINE(int, ss_fltsz_local) = 4; SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, local_slowstart_flightsize, CTLFLAG_RW, &VNET_NAME(ss_fltsz_local), 1, "Slow start flight size for local networks"); +VNET_DEFINE(int, tcp_do_newreno) = 1; SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, newreno, CTLFLAG_RW, &VNET_NAME(tcp_do_newreno), 0, "Enable NewReno Algorithms"); +VNET_DEFINE(int, tcp_do_tso) = 1; +#define V_tcp_do_tso VNET(tcp_do_tso) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, tso, CTLFLAG_RW, &VNET_NAME(tcp_do_tso), 0, "Enable TCP Segmentation Offload"); +VNET_DEFINE(int, tcp_do_autosndbuf) = 1; +#define V_tcp_do_autosndbuf VNET(tcp_do_autosndbuf) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_auto, CTLFLAG_RW, &VNET_NAME(tcp_do_autosndbuf), 0, "Enable automatic send buffer sizing"); +VNET_DEFINE(int, tcp_autosndbuf_inc) = 8*1024; +#define V_tcp_autosndbuf_inc VNET(tcp_autosndbuf_inc) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_inc, CTLFLAG_RW, &VNET_NAME(tcp_autosndbuf_inc), 0, "Incrementor step size of automatic send buffer"); +VNET_DEFINE(int, tcp_autosndbuf_max) = 256*1024; +#define V_tcp_autosndbuf_max VNET(tcp_autosndbuf_max) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, sendbuf_max, CTLFLAG_RW, &VNET_NAME(tcp_autosndbuf_max), 0, "Max size of automatic send buffer"); diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index cd7eb1c..bfb53d3 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -74,30 +74,28 @@ __FBSDID("$FreeBSD$"); #include #endif /* TCPDEBUG */ -static VNET_DEFINE(int, tcp_reass_maxseg); -VNET_DEFINE(int, tcp_reass_qsize); -static VNET_DEFINE(int, tcp_reass_maxqlen); -static VNET_DEFINE(int, tcp_reass_overflows); - -#define V_tcp_reass_maxseg VNET(tcp_reass_maxseg) -#define V_tcp_reass_maxqlen VNET(tcp_reass_maxqlen) -#define V_tcp_reass_overflows VNET(tcp_reass_overflows) - SYSCTL_NODE(_net_inet_tcp, OID_AUTO, reass, CTLFLAG_RW, 0, "TCP Segment Reassembly Queue"); +static VNET_DEFINE(int, tcp_reass_maxseg) = 0; +#define V_tcp_reass_maxseg VNET(tcp_reass_maxseg) SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, maxsegments, CTLFLAG_RDTUN, &VNET_NAME(tcp_reass_maxseg), 0, "Global maximum number of TCP Segments in Reassembly Queue"); +VNET_DEFINE(int, tcp_reass_qsize) = 0; SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, cursegments, CTLFLAG_RD, &VNET_NAME(tcp_reass_qsize), 0, "Global number of TCP Segments currently in Reassembly Queue"); +static VNET_DEFINE(int, tcp_reass_maxqlen) = 48; +#define V_tcp_reass_maxqlen VNET(tcp_reass_maxqlen) SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, maxqlen, CTLFLAG_RW, &VNET_NAME(tcp_reass_maxqlen), 0, "Maximum number of TCP Segments per individual Reassembly Queue"); +static VNET_DEFINE(int, tcp_reass_overflows) = 0; +#define V_tcp_reass_overflows VNET(tcp_reass_overflows) SYSCTL_VNET_INT(_net_inet_tcp_reass, OID_AUTO, overflows, CTLFLAG_RD, &VNET_NAME(tcp_reass_overflows), 0, "Global number of TCP Segment Reassembly Queue Overflows"); @@ -117,11 +115,6 @@ void tcp_reass_init(void) { - V_tcp_reass_maxseg = 0; - V_tcp_reass_qsize = 0; - V_tcp_reass_maxqlen = 48; - V_tcp_reass_overflows = 0; - V_tcp_reass_maxseg = nmbclusters / 16; TUNABLE_INT_FETCH("net.inet.tcp.reass.maxsegments", &V_tcp_reass_maxseg); diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c index 06fb502..737c2b2 100644 --- a/sys/netinet/tcp_sack.c +++ b/sys/netinet/tcp_sack.c @@ -123,29 +123,28 @@ __FBSDID("$FreeBSD$"); #include VNET_DECLARE(struct uma_zone *, sack_hole_zone); -VNET_DEFINE(int, tcp_do_sack); -VNET_DEFINE(int, tcp_sack_maxholes); -VNET_DEFINE(int, tcp_sack_globalmaxholes); -VNET_DEFINE(int, tcp_sack_globalholes); - #define V_sack_hole_zone VNET(sack_hole_zone) -#define V_tcp_do_sack VNET(tcp_do_sack) -#define V_tcp_sack_maxholes VNET(tcp_sack_maxholes) -#define V_tcp_sack_globalmaxholes VNET(tcp_sack_globalmaxholes) -#define V_tcp_sack_globalholes VNET(tcp_sack_globalholes) SYSCTL_NODE(_net_inet_tcp, OID_AUTO, sack, CTLFLAG_RW, 0, "TCP SACK"); +VNET_DEFINE(int, tcp_do_sack) = 1; +#define V_tcp_do_sack VNET(tcp_do_sack) SYSCTL_VNET_INT(_net_inet_tcp_sack, OID_AUTO, enable, CTLFLAG_RW, &VNET_NAME(tcp_do_sack), 0, "Enable/Disable TCP SACK support"); +VNET_DEFINE(int, tcp_sack_maxholes) = 128; +#define V_tcp_sack_maxholes VNET(tcp_sack_maxholes) SYSCTL_VNET_INT(_net_inet_tcp_sack, OID_AUTO, maxholes, CTLFLAG_RW, &VNET_NAME(tcp_sack_maxholes), 0, "Maximum number of TCP SACK holes allowed per connection"); +VNET_DEFINE(int, tcp_sack_globalmaxholes) = 65536; +#define V_tcp_sack_globalmaxholes VNET(tcp_sack_globalmaxholes) SYSCTL_VNET_INT(_net_inet_tcp_sack, OID_AUTO, globalmaxholes, CTLFLAG_RW, &VNET_NAME(tcp_sack_globalmaxholes), 0, "Global maximum number of TCP SACK holes"); +VNET_DEFINE(int, tcp_sack_globalholes) = 0; +#define V_tcp_sack_globalholes VNET(tcp_sack_globalholes) SYSCTL_VNET_INT(_net_inet_tcp_sack, OID_AUTO, globalholes, CTLFLAG_RD, &VNET_NAME(tcp_sack_globalholes), 0, "Global number of TCP SACK holes currently allocated"); diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 9ec434c..43ed1e4 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -111,28 +111,10 @@ __FBSDID("$FreeBSD$"); #include -VNET_DEFINE(int, tcp_mssdflt); +VNET_DEFINE(int, tcp_mssdflt) = TCP_MSS; #ifdef INET6 -VNET_DEFINE(int, tcp_v6mssdflt); +VNET_DEFINE(int, tcp_v6mssdflt) = TCP6_MSS; #endif -VNET_DEFINE(int, tcp_minmss); -VNET_DEFINE(int, tcp_do_rfc1323); - -static VNET_DEFINE(int, icmp_may_rst); -static VNET_DEFINE(int, tcp_isn_reseed_interval); -static VNET_DEFINE(int, tcp_inflight_enable); -static VNET_DEFINE(int, tcp_inflight_rttthresh); -static VNET_DEFINE(int, tcp_inflight_min); -static VNET_DEFINE(int, tcp_inflight_max); -static VNET_DEFINE(int, tcp_inflight_stab); - -#define V_icmp_may_rst VNET(icmp_may_rst) -#define V_tcp_isn_reseed_interval VNET(tcp_isn_reseed_interval) -#define V_tcp_inflight_enable VNET(tcp_inflight_enable) -#define V_tcp_inflight_rttthresh VNET(tcp_inflight_rttthresh) -#define V_tcp_inflight_min VNET(tcp_inflight_min) -#define V_tcp_inflight_max VNET(tcp_inflight_max) -#define V_tcp_inflight_stab VNET(tcp_inflight_stab) static int sysctl_net_inet_tcp_mss_check(SYSCTL_HANDLER_ARGS) @@ -194,10 +176,12 @@ vnet_sysctl_msec_to_ticks(SYSCTL_HANDLER_ARGS) * with packet generation and sending. Set to zero to disable MINMSS * checking. This setting prevents us from sending too small packets. */ +VNET_DEFINE(int, tcp_minmss) = TCP_MINMSS; SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, minmss, CTLFLAG_RW, &VNET_NAME(tcp_minmss), 0, "Minmum TCP Maximum Segment Size"); +VNET_DEFINE(int, tcp_do_rfc1323) = 1; SYSCTL_VNET_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323, CTLFLAG_RW, &VNET_NAME(tcp_do_rfc1323), 0, "Enable rfc1323 (high performance TCP) extensions"); @@ -217,10 +201,14 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_tcpdrain, CTLFLAG_RW, &do_tcpdrain, 0, SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD, &VNET_NAME(tcbinfo.ipi_count), 0, "Number of active PCBs"); +static VNET_DEFINE(int, icmp_may_rst) = 1; +#define V_icmp_may_rst VNET(icmp_may_rst) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW, &VNET_NAME(icmp_may_rst), 0, "Certain ICMP unreachable messages may abort connections in SYN_SENT"); +static VNET_DEFINE(int, tcp_isn_reseed_interval) = 0; +#define V_tcp_isn_reseed_interval VNET(tcp_isn_reseed_interval) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW, &VNET_NAME(tcp_isn_reseed_interval), 0, "Seconds between reseeding of ISN secret"); @@ -233,6 +221,8 @@ SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW, SYSCTL_NODE(_net_inet_tcp, OID_AUTO, inflight, CTLFLAG_RW, 0, "TCP inflight data limiting"); +static VNET_DEFINE(int, tcp_inflight_enable) = 1; +#define V_tcp_inflight_enable VNET(tcp_inflight_enable) SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, enable, CTLFLAG_RW, &VNET_NAME(tcp_inflight_enable), 0, "Enable automatic TCP inflight data limiting"); @@ -242,19 +232,27 @@ SYSCTL_INT(_net_inet_tcp_inflight, OID_AUTO, debug, CTLFLAG_RW, &tcp_inflight_debug, 0, "Debug TCP inflight calculations"); +static VNET_DEFINE(int, tcp_inflight_rttthresh); +#define V_tcp_inflight_rttthresh VNET(tcp_inflight_rttthresh) SYSCTL_VNET_PROC(_net_inet_tcp_inflight, OID_AUTO, rttthresh, CTLTYPE_INT|CTLFLAG_RW, &VNET_NAME(tcp_inflight_rttthresh), 0, vnet_sysctl_msec_to_ticks, "I", "RTT threshold below which inflight will deactivate itself"); +static VNET_DEFINE(int, tcp_inflight_min) = 6144; +#define V_tcp_inflight_min VNET(tcp_inflight_min) SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, min, CTLFLAG_RW, &VNET_NAME(tcp_inflight_min), 0, "Lower-bound for TCP inflight window"); +static VNET_DEFINE(int, tcp_inflight_max) = TCP_MAXWIN << TCP_MAX_WINSHIFT; +#define V_tcp_inflight_max VNET(tcp_inflight_max) SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, max, CTLFLAG_RW, &VNET_NAME(tcp_inflight_max), 0, "Upper-bound for TCP inflight window"); +static VNET_DEFINE(int, tcp_inflight_stab) = 20; +#define V_tcp_inflight_stab VNET(tcp_inflight_stab) SYSCTL_VNET_INT(_net_inet_tcp_inflight, OID_AUTO, stab, CTLFLAG_RW, &VNET_NAME(tcp_inflight_stab), 0, "Inflight Algorithm Stabilization 20 = 2 packets"); @@ -329,53 +327,6 @@ tcp_init(void) { int hashsize; - V_blackhole = 0; - V_tcp_delack_enabled = 1; - V_drop_synfin = 0; - V_tcp_do_rfc3042 = 1; - V_tcp_do_rfc3390 = 1; - V_tcp_do_ecn = 0; - V_tcp_ecn_maxretries = 1; - V_tcp_insecure_rst = 0; - V_tcp_do_autorcvbuf = 1; - V_tcp_autorcvbuf_inc = 16*1024; - V_tcp_autorcvbuf_max = 256*1024; - V_tcp_do_rfc3465 = 1; - V_tcp_abc_l_var = 2; - - V_tcp_mssdflt = TCP_MSS; -#ifdef INET6 - V_tcp_v6mssdflt = TCP6_MSS; -#endif - V_tcp_minmss = TCP_MINMSS; - V_tcp_do_rfc1323 = 1; - V_icmp_may_rst = 1; - V_tcp_isn_reseed_interval = 0; - V_tcp_inflight_enable = 1; - V_tcp_inflight_min = 6144; - V_tcp_inflight_max = TCP_MAXWIN << TCP_MAX_WINSHIFT; - V_tcp_inflight_stab = 20; - - V_path_mtu_discovery = 1; - V_ss_fltsz = 1; - V_ss_fltsz_local = 4; - V_tcp_do_newreno = 1; - V_tcp_do_tso = 1; - V_tcp_do_autosndbuf = 1; - V_tcp_autosndbuf_inc = 8*1024; - V_tcp_autosndbuf_max = 256*1024; - - V_nolocaltimewait = 0; - - V_tcp_do_sack = 1; - V_tcp_sack_maxholes = 128; - V_tcp_sack_globalmaxholes = 65536; - V_tcp_sack_globalholes = 0; - - V_tcp_inflight_rttthresh = TCPTV_INFLIGHT_RTTTHRESH; - - TUNABLE_INT_FETCH("net.inet.tcp.sack.enable", &V_tcp_do_sack); - hashsize = TCBHASHSIZE; TUNABLE_INT_FETCH("net.inet.tcp.tcbhashsize", &hashsize); if (!powerof2(hashsize)) { @@ -385,16 +336,21 @@ tcp_init(void) in_pcbinfo_init(&V_tcbinfo, "tcp", &V_tcb, hashsize, hashsize, "tcp_inpcb", tcp_inpcb_init, NULL, UMA_ZONE_NOFREE); + V_tcp_inflight_rttthresh = TCPTV_INFLIGHT_RTTTHRESH; + /* * These have to be type stable for the benefit of the timers. */ V_tcpcb_zone = uma_zcreate("tcpcb", sizeof(struct tcpcb_mem), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); uma_zone_set_max(V_tcpcb_zone, maxsockets); + tcp_tw_init(); syncache_init(); tcp_hc_init(); tcp_reass_init(); + + TUNABLE_INT_FETCH("net.inet.tcp.sack.enable", &V_tcp_do_sack); V_sack_hole_zone = uma_zcreate("sackhole", sizeof(struct sackhole), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 4d9d487..c47493c 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -97,19 +97,14 @@ __FBSDID("$FreeBSD$"); #include -static VNET_DEFINE(struct tcp_syncache, tcp_syncache); -static VNET_DEFINE(int, tcp_syncookies); -static VNET_DEFINE(int, tcp_syncookiesonly); -VNET_DEFINE(int, tcp_sc_rst_sock_fail); - -#define V_tcp_syncache VNET(tcp_syncache) +static VNET_DEFINE(int, tcp_syncookies) = 1; #define V_tcp_syncookies VNET(tcp_syncookies) -#define V_tcp_syncookiesonly VNET(tcp_syncookiesonly) - SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_RW, &VNET_NAME(tcp_syncookies), 0, "Use TCP SYN cookies if the syncache overflows"); +static VNET_DEFINE(int, tcp_syncookiesonly) = 0; +#define V_tcp_syncookiesonly VNET(tcp_syncookiesonly) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_RW, &VNET_NAME(tcp_syncookiesonly), 0, "Use only TCP SYN cookies"); @@ -148,6 +143,9 @@ static struct syncache #define TCP_SYNCACHE_HASHSIZE 512 #define TCP_SYNCACHE_BUCKETLIMIT 30 +static VNET_DEFINE(struct tcp_syncache, tcp_syncache); +#define V_tcp_syncache VNET(tcp_syncache) + SYSCTL_NODE(_net_inet_tcp, OID_AUTO, syncache, CTLFLAG_RW, 0, "TCP SYN cache"); SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, bucketlimit, CTLFLAG_RDTUN, @@ -170,6 +168,7 @@ SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, rexmtlimit, CTLFLAG_RW, &VNET_NAME(tcp_syncache.rexmt_limit), 0, "Limit on SYN/ACK retransmissions"); +VNET_DEFINE(int, tcp_sc_rst_sock_fail) = 1; SYSCTL_VNET_INT(_net_inet_tcp_syncache, OID_AUTO, rst_on_sock_fail, CTLFLAG_RW, &VNET_NAME(tcp_sc_rst_sock_fail), 0, "Send reset on socket allocation failure"); @@ -224,10 +223,6 @@ syncache_init(void) { int i; - V_tcp_syncookies = 1; - V_tcp_syncookiesonly = 0; - V_tcp_sc_rst_sock_fail = 1; - V_tcp_syncache.cache_count = 0; V_tcp_syncache.hashsize = TCP_SYNCACHE_HASHSIZE; V_tcp_syncache.bucket_limit = TCP_SYNCACHE_BUCKETLIMIT; diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 6e5b013..42df4fe 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -92,6 +92,8 @@ __FBSDID("$FreeBSD$"); #include +static VNET_DEFINE(uma_zone_t, tcptw_zone); +#define V_tcptw_zone VNET(tcptw_zone) static int maxtcptw; /* @@ -100,11 +102,7 @@ static int maxtcptw; * queue pointers in each tcptw structure, are protected using the global * tcbinfo lock, which must be held over queue iteration and modification. */ -static VNET_DEFINE(uma_zone_t, tcptw_zone); static VNET_DEFINE(TAILQ_HEAD(, tcptw), twq_2msl); -VNET_DEFINE(int, nolocaltimewait); - -#define V_tcptw_zone VNET(tcptw_zone) #define V_twq_2msl VNET(twq_2msl) static void tcp_tw_2msl_reset(struct tcptw *, int); @@ -149,6 +147,8 @@ SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxtcptw, CTLTYPE_INT|CTLFLAG_RW, &maxtcptw, 0, sysctl_maxtcptw, "IU", "Maximum number of compressed TCP TIME_WAIT entries"); +VNET_DEFINE(int, nolocaltimewait) = 0; +#define V_nolocaltimewait VNET(nolocaltimewait) SYSCTL_VNET_INT(_net_inet_tcp, OID_AUTO, nolocaltimewait, CTLFLAG_RW, &VNET_NAME(nolocaltimewait), 0, "Do not create compressed TCP TIME_WAIT entries for local connections"); diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 3a59eee..5811439 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -42,12 +42,12 @@ * Kernel variables for tcp. */ VNET_DECLARE(int, tcp_do_rfc1323); +#define V_tcp_do_rfc1323 VNET(tcp_do_rfc1323) + VNET_DECLARE(int, tcp_reass_qsize); VNET_DECLARE(struct uma_zone *, tcp_reass_zone); -#define V_tcp_do_rfc1323 VNET(tcp_do_rfc1323) #define V_tcp_reass_qsize VNET(tcp_reass_qsize) #define V_tcp_reass_zone VNET(tcp_reass_zone) - #endif /* _KERNEL */ /* TCP segment queue entry */ @@ -558,11 +558,10 @@ SYSCTL_DECL(_net_inet_tcp_sack); MALLOC_DECLARE(M_TCPLOG); #endif -extern int tcp_log_in_vain; - VNET_DECLARE(struct inpcbhead, tcb); /* queue of active tcpcb's */ VNET_DECLARE(struct inpcbinfo, tcbinfo); VNET_DECLARE(struct tcpstat, tcpstat); /* tcp statistics */ +extern int tcp_log_in_vain; VNET_DECLARE(int, tcp_mssdflt); /* XXX */ VNET_DECLARE(int, tcp_minmss); VNET_DECLARE(int, tcp_delack_enabled); @@ -570,7 +569,6 @@ VNET_DECLARE(int, tcp_do_newreno); VNET_DECLARE(int, path_mtu_discovery); VNET_DECLARE(int, ss_fltsz); VNET_DECLARE(int, ss_fltsz_local); - #define V_tcb VNET(tcb) #define V_tcbinfo VNET(tcbinfo) #define V_tcpstat VNET(tcpstat) @@ -582,55 +580,13 @@ VNET_DECLARE(int, ss_fltsz_local); #define V_ss_fltsz VNET(ss_fltsz) #define V_ss_fltsz_local VNET(ss_fltsz_local) -VNET_DECLARE(int, blackhole); -VNET_DECLARE(int, drop_synfin); -VNET_DECLARE(int, tcp_do_rfc3042); -VNET_DECLARE(int, tcp_do_rfc3390); -VNET_DECLARE(int, tcp_insecure_rst); -VNET_DECLARE(int, tcp_do_autorcvbuf); -VNET_DECLARE(int, tcp_autorcvbuf_inc); -VNET_DECLARE(int, tcp_autorcvbuf_max); -VNET_DECLARE(int, tcp_do_rfc3465); -VNET_DECLARE(int, tcp_abc_l_var); - -#define V_blackhole VNET(blackhole) -#define V_drop_synfin VNET(drop_synfin) -#define V_tcp_do_rfc3042 VNET(tcp_do_rfc3042) -#define V_tcp_do_rfc3390 VNET(tcp_do_rfc3390) -#define V_tcp_insecure_rst VNET(tcp_insecure_rst) -#define V_tcp_do_autorcvbuf VNET(tcp_do_autorcvbuf) -#define V_tcp_autorcvbuf_inc VNET(tcp_autorcvbuf_inc) -#define V_tcp_autorcvbuf_max VNET(tcp_autorcvbuf_max) -#define V_tcp_do_rfc3465 VNET(tcp_do_rfc3465) -#define V_tcp_abc_l_var VNET(tcp_abc_l_var) - -VNET_DECLARE(int, tcp_do_tso); -VNET_DECLARE(int, tcp_do_autosndbuf); -VNET_DECLARE(int, tcp_autosndbuf_inc); -VNET_DECLARE(int, tcp_autosndbuf_max); - -#define V_tcp_do_tso VNET(tcp_do_tso) -#define V_tcp_do_autosndbuf VNET(tcp_do_autosndbuf) -#define V_tcp_autosndbuf_inc VNET(tcp_autosndbuf_inc) -#define V_tcp_autosndbuf_max VNET(tcp_autosndbuf_max) - -VNET_DECLARE(int, nolocaltimewait); - -#define V_nolocaltimewait VNET(nolocaltimewait) - VNET_DECLARE(int, tcp_do_sack); /* SACK enabled/disabled */ -VNET_DECLARE(int, tcp_sack_maxholes); -VNET_DECLARE(int, tcp_sack_globalmaxholes); -VNET_DECLARE(int, tcp_sack_globalholes); VNET_DECLARE(int, tcp_sc_rst_sock_fail); /* RST on sock alloc failure */ -VNET_DECLARE(int, tcp_do_ecn); /* TCP ECN enabled/disabled */ -VNET_DECLARE(int, tcp_ecn_maxretries); - #define V_tcp_do_sack VNET(tcp_do_sack) -#define V_tcp_sack_maxholes VNET(tcp_sack_maxholes) -#define V_tcp_sack_globalmaxholes VNET(tcp_sack_globalmaxholes) -#define V_tcp_sack_globalholes VNET(tcp_sack_globalholes) #define V_tcp_sc_rst_sock_fail VNET(tcp_sc_rst_sock_fail) + +VNET_DECLARE(int, tcp_do_ecn); /* TCP ECN enabled/disabled */ +VNET_DECLARE(int, tcp_ecn_maxretries); #define V_tcp_do_ecn VNET(tcp_do_ecn) #define V_tcp_ecn_maxretries VNET(tcp_ecn_maxretries) diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 0d8e04d..4541038 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -94,8 +94,6 @@ __FBSDID("$FreeBSD$"); * Per RFC 768, August, 1980. */ -VNET_DEFINE(int, udp_blackhole); - /* * BSD 4.2 defaulted the udp checksum to be off. Turning off udp checksums * removes the only data integrity mechanism for packets and malformed @@ -110,6 +108,7 @@ int udp_log_in_vain = 0; SYSCTL_INT(_net_inet_udp, OID_AUTO, log_in_vain, CTLFLAG_RW, &udp_log_in_vain, 0, "Log all incoming UDP packets"); +VNET_DEFINE(int, udp_blackhole) = 0; SYSCTL_VNET_INT(_net_inet_udp, OID_AUTO, blackhole, CTLFLAG_RW, &VNET_NAME(udp_blackhole), 0, "Do not send port unreachables for refused connects"); @@ -133,14 +132,13 @@ SYSCTL_ULONG(_net_inet_udp, UDPCTL_RECVSPACE, recvspace, CTLFLAG_RW, VNET_DEFINE(struct inpcbhead, udb); /* from udp_var.h */ VNET_DEFINE(struct inpcbinfo, udbinfo); static VNET_DEFINE(uma_zone_t, udpcb_zone); -VNET_DEFINE(struct udpstat, udpstat); /* from udp_var.h */ - #define V_udpcb_zone VNET(udpcb_zone) #ifndef UDBHASHSIZE #define UDBHASHSIZE 128 #endif +VNET_DEFINE(struct udpstat, udpstat); /* from udp_var.h */ SYSCTL_VNET_STRUCT(_net_inet_udp, UDPCTL_STATS, stats, CTLFLAG_RW, &VNET_NAME(udpstat), udpstat, "UDP statistics (struct udpstat, netinet/udp_var.h)"); @@ -179,7 +177,6 @@ void udp_init(void) { - V_udp_blackhole = 0; in_pcbinfo_init(&V_udbinfo, "udp", &V_udb, UDBHASHSIZE, UDBHASHSIZE, "udp_inpcb", udp_inpcb_init, NULL, UMA_ZONE_NOFREE); V_udpcb_zone = uma_zcreate("udpcb", sizeof(struct udpcb), diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h index b8d994c..aa7ee47 100644 --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -129,19 +129,17 @@ void kmod_udpstat_inc(int statnum); SYSCTL_DECL(_net_inet_udp); extern struct pr_usrreqs udp_usrreqs; - VNET_DECLARE(struct inpcbhead, udb); VNET_DECLARE(struct inpcbinfo, udbinfo); -VNET_DECLARE(struct udpstat, udpstat); -VNET_DECLARE(int, udp_blackhole); - #define V_udb VNET(udb) #define V_udbinfo VNET(udbinfo) -#define V_udpstat VNET(udpstat) -#define V_udp_blackhole VNET(udp_blackhole) extern u_long udp_sendspace; extern u_long udp_recvspace; +VNET_DECLARE(struct udpstat, udpstat); +VNET_DECLARE(int, udp_blackhole); +#define V_udpstat VNET(udpstat) +#define V_udp_blackhole VNET(udp_blackhole) extern int udp_log_in_vain; int udp_newudpcb(struct inpcb *); diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c index 8900f7d..1523133 100644 --- a/sys/netinet6/frag6.c +++ b/sys/netinet6/frag6.c @@ -106,16 +106,17 @@ void frag6_init(void) { - V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q; V_ip6_maxfragpackets = nmbclusters / 4; V_ip6_maxfrags = nmbclusters / 4; + V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q; if (!IS_DEFAULT_VNET(curvnet)) return; - IP6Q_LOCK_INIT(); EVENTHANDLER_REGISTER(nmbclusters_change, frag6_change, NULL, EVENTHANDLER_PRI_ANY); + + IP6Q_LOCK_INIT(); } /* diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index 57f8d32..87df9c3 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -113,23 +113,22 @@ __FBSDID("$FreeBSD$"); extern struct domain inet6domain; +VNET_DEFINE(struct icmp6stat, icmp6stat); + VNET_DECLARE(struct inpcbinfo, ripcbinfo); VNET_DECLARE(struct inpcbhead, ripcb); VNET_DECLARE(int, icmp6errppslim); +static VNET_DEFINE(int, icmp6errpps_count) = 0; +static VNET_DEFINE(struct timeval, icmp6errppslim_last); VNET_DECLARE(int, icmp6_nodeinfo); #define V_ripcbinfo VNET(ripcbinfo) #define V_ripcb VNET(ripcb) #define V_icmp6errppslim VNET(icmp6errppslim) +#define V_icmp6errpps_count VNET(icmp6errpps_count) +#define V_icmp6errppslim_last VNET(icmp6errppslim_last) #define V_icmp6_nodeinfo VNET(icmp6_nodeinfo) -VNET_DEFINE(struct icmp6stat, icmp6stat); -static VNET_DEFINE(int, icmp6errpps_count); -static VNET_DEFINE(struct timeval, icmp6errppslim_last); - -#define V_icmp6errpps_count VNET(icmp6errpps_count) -#define V_icmp6errppslim_last VNET(icmp6errppslim_last) - static void icmp6_errcount(struct icmp6errstat *, int, int); static int icmp6_rip6_input(struct mbuf **, int); static int icmp6_ratelimit(const struct in6_addr *, const int, const int); @@ -144,14 +143,6 @@ static int ni6_store_addrs __P((struct icmp6_nodeinfo *, struct icmp6_nodeinfo * struct ifnet *, int)); static int icmp6_notify_error(struct mbuf **, int, int, int); - -void -icmp6_init(void) -{ - - V_icmp6errpps_count = 0; -} - /* * Kernel module interface for updating icmp6stat. The argument is an index * into icmp6stat treated as an array of u_quad_t. While this encodes the diff --git a/sys/netinet6/in6_gif.c b/sys/netinet6/in6_gif.c index a481706..e786836 100644 --- a/sys/netinet6/in6_gif.c +++ b/sys/netinet6/in6_gif.c @@ -41,8 +41,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include #include @@ -69,6 +71,13 @@ __FBSDID("$FreeBSD$"); #include +VNET_DEFINE(int, ip6_gif_hlim) = GIF_HLIM; +#define V_ip6_gif_hlim VNET(ip6_gif_hlim) + +SYSCTL_DECL(_net_inet6_ip6); +SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM, gifhlim, CTLFLAG_RW, + &VNET_NAME(ip6_gif_hlim), 0, ""); + static int gif_validate6(const struct ip6_hdr *, struct gif_softc *, struct ifnet *); diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 5041ee2..363d7be 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -67,10 +67,15 @@ __FBSDID("$FreeBSD$"); #include #include -VNET_DEFINE(unsigned long, in6_maxmtu); -VNET_DEFINE(int, ip6_auto_linklocal); -VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch); +VNET_DEFINE(unsigned long, in6_maxmtu) = 0; + +#ifdef IP6_AUTO_LINKLOCAL +VNET_DEFINE(int, ip6_auto_linklocal) = IP6_AUTO_LINKLOCAL; +#else +VNET_DEFINE(int, ip6_auto_linklocal) = 1; /* enabled by default */ +#endif +VNET_DEFINE(struct callout, in6_tmpaddrtimer_ch); #define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch) VNET_DECLARE(struct inpcbinfo, ripcbinfo); diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index 3289e57..51f5187 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -234,7 +234,6 @@ struct ip6protosw inet6sw[] = { .pr_output = rip6_output, .pr_ctlinput = rip6_ctlinput, .pr_ctloutput = rip6_ctloutput, - .pr_init = icmp6_init, .pr_fasttimo = icmp6_fasttimo, .pr_slowtimo = icmp6_slowtimo, .pr_usrreqs = &rip6_usrreqs @@ -378,25 +377,44 @@ VNET_DOMAIN_SET(inet6); /* * Internet configuration info */ -VNET_DEFINE(int, ip6_forwarding); -VNET_DEFINE(int, ip6_sendredirects); -VNET_DEFINE(int, ip6_defhlim); -VNET_DEFINE(int, ip6_defmcasthlim); -VNET_DEFINE(int, ip6_accept_rtadv); -VNET_DEFINE(int, ip6_maxfragpackets); -VNET_DEFINE(int, ip6_maxfrags); -VNET_DEFINE(int, ip6_log_interval); -VNET_DEFINE(int, ip6_hdrnestlimit); -VNET_DEFINE(int, ip6_dad_count); -VNET_DEFINE(int, ip6_auto_flowlabel); -VNET_DEFINE(int, ip6_use_deprecated); -VNET_DEFINE(int, ip6_rr_prune); -VNET_DEFINE(int, ip6_mcast_pmtu); -VNET_DEFINE(int, ip6_v6only); -VNET_DEFINE(int, ip6_keepfaith); -VNET_DEFINE(time_t, ip6_log_time); -VNET_DEFINE(int, ip6stealth); -VNET_DEFINE(int, nd6_onlink_ns_rfc4861); +#ifndef IPV6FORWARDING +#ifdef GATEWAY6 +#define IPV6FORWARDING 1 /* forward IP6 packets not for us */ +#else +#define IPV6FORWARDING 0 /* don't forward IP6 packets not for us */ +#endif /* GATEWAY6 */ +#endif /* !IPV6FORWARDING */ + +#ifndef IPV6_SENDREDIRECTS +#define IPV6_SENDREDIRECTS 1 +#endif + +VNET_DEFINE(int, ip6_forwarding) = IPV6FORWARDING; /* act as router? */ +VNET_DEFINE(int, ip6_sendredirects) = IPV6_SENDREDIRECTS; +VNET_DEFINE(int, ip6_defhlim) = IPV6_DEFHLIM; +VNET_DEFINE(int, ip6_defmcasthlim) = IPV6_DEFAULT_MULTICAST_HOPS; +VNET_DEFINE(int, ip6_accept_rtadv) = 0; +VNET_DEFINE(int, ip6_maxfragpackets); /* initialized in frag6.c:frag6_init() */ +VNET_DEFINE(int, ip6_maxfrags); /* initialized in frag6.c:frag6_init() */ +VNET_DEFINE(int, ip6_log_interval) = 5; +VNET_DEFINE(int, ip6_hdrnestlimit) = 15;/* How many header options will we + * process? */ +VNET_DEFINE(int, ip6_dad_count) = 1; /* DupAddrDetectionTransmits */ +VNET_DEFINE(int, ip6_auto_flowlabel) = 1; +VNET_DEFINE(int, ip6_use_deprecated) = 1;/* allow deprecated addr + * (RFC2462 5.5.4) */ +VNET_DEFINE(int, ip6_rr_prune) = 5; /* router renumbering prefix + * walk list every 5 sec. */ +VNET_DEFINE(int, ip6_mcast_pmtu) = 0; /* enable pMTU discovery for multicast? */ +VNET_DEFINE(int, ip6_v6only) = 1; + +VNET_DEFINE(int, ip6_keepfaith) = 0; +VNET_DEFINE(time_t, ip6_log_time) = (time_t)0L; +#ifdef IPSTEALTH +VNET_DEFINE(int, ip6stealth) = 0; +#endif +VNET_DEFINE(int, nd6_onlink_ns_rfc4861) = 0;/* allow 'on-link' nd6 NS + * (RFC 4861) */ /* icmp6 */ /* @@ -404,26 +422,31 @@ VNET_DEFINE(int, nd6_onlink_ns_rfc4861); * XXX: what if we don't define INET? Should we define pmtu6_expire * or so? (jinmei@kame.net 19990310) */ -VNET_DEFINE(int, pmtu_expire); -VNET_DEFINE(int, pmtu_probe); +VNET_DEFINE(int, pmtu_expire) = 60*10; +VNET_DEFINE(int, pmtu_probe) = 60*2; /* raw IP6 parameters */ /* * Nominal space allocated to a raw ip socket. */ -VNET_DEFINE(u_long, rip6_sendspace); -VNET_DEFINE(u_long, rip6_recvspace); +#define RIPV6SNDQ 8192 +#define RIPV6RCVQ 8192 + +VNET_DEFINE(u_long, rip6_sendspace) = RIPV6SNDQ; +VNET_DEFINE(u_long, rip6_recvspace) = RIPV6RCVQ; /* ICMPV6 parameters */ -VNET_DEFINE(int, icmp6_rediraccept); -VNET_DEFINE(int, icmp6_redirtimeout); -VNET_DEFINE(int, icmp6errppslim); +VNET_DEFINE(int, icmp6_rediraccept) = 1;/* accept and process redirects */ +VNET_DEFINE(int, icmp6_redirtimeout) = 10 * 60; /* 10 minutes */ +VNET_DEFINE(int, icmp6errppslim) = 100; /* 100pps */ /* control how to respond to NI queries */ -VNET_DEFINE(int, icmp6_nodeinfo); +VNET_DEFINE(int, icmp6_nodeinfo) = + (ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK); /* UDP on IP6 parameters */ -VNET_DEFINE(int, udp6_sendspace); -VNET_DEFINE(int, udp6_recvspace); +VNET_DEFINE(int, udp6_sendspace) = 9216;/* really max datagram size */ +VNET_DEFINE(int, udp6_recvspace) = 40 * (1024 + sizeof(struct sockaddr_in6)); + /* 40 1K datagrams */ /* * sysctl related items. @@ -571,7 +594,6 @@ SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXNUDHINT, nd6_maxnudhint, CTLFLAG_RW, &VNET_NAME(nd6_maxnudhint), 0, ""); SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DEBUG, nd6_debug, CTLFLAG_RW, &VNET_NAME(nd6_debug), 0, ""); - SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_ONLINKNSRFC4861, nd6_onlink_ns_rfc4861, CTLFLAG_RW, &VNET_NAME(nd6_onlink_ns_rfc4861), 0, "Accept 'on-link' nd6 NS in compliance with RFC 4861."); diff --git a/sys/netinet6/in6_rmx.c b/sys/netinet6/in6_rmx.c index 1ae04c3..8927a17 100644 --- a/sys/netinet6/in6_rmx.c +++ b/sys/netinet6/in6_rmx.c @@ -204,20 +204,21 @@ in6_matroute(void *v_arg, struct radix_node_head *head) SYSCTL_DECL(_net_inet6_ip6); -static VNET_DEFINE(int, rtq_reallyold6); -static VNET_DEFINE(int, rtq_minreallyold6); -static VNET_DEFINE(int, rtq_toomany6); - +static VNET_DEFINE(int, rtq_reallyold6) = 60*60; + /* one hour is ``really old'' */ #define V_rtq_reallyold6 VNET(rtq_reallyold6) -#define V_rtq_minreallyold6 VNET(rtq_minreallyold6) -#define V_rtq_toomany6 VNET(rtq_toomany6) - SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTEXPIRE, rtexpire, CTLFLAG_RW, &VNET_NAME(rtq_reallyold6) , 0, ""); +static VNET_DEFINE(int, rtq_minreallyold6) = 10; + /* never automatically crank down to less */ +#define V_rtq_minreallyold6 VNET(rtq_minreallyold6) SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMINEXPIRE, rtminexpire, CTLFLAG_RW, &VNET_NAME(rtq_minreallyold6) , 0, ""); +static VNET_DEFINE(int, rtq_toomany6) = 128; + /* 128 cached routes is ``too many'' */ +#define V_rtq_toomany6 VNET(rtq_toomany6) SYSCTL_VNET_INT(_net_inet6_ip6, IPV6CTL_RTMAXCACHE, rtmaxcache, CTLFLAG_RW, &VNET_NAME(rtq_toomany6) , 0, ""); @@ -277,7 +278,7 @@ in6_rtqkill(struct radix_node *rn, void *rock) } #define RTQ_TIMEOUT 60*10 /* run no less than once every ten minutes */ -static VNET_DEFINE(int, rtq_timeout6); +static VNET_DEFINE(int, rtq_timeout6) = RTQ_TIMEOUT; static VNET_DEFINE(struct callout, rtq_timer6); #define V_rtq_timeout6 VNET(rtq_timeout6) @@ -346,7 +347,6 @@ struct mtuex_arg { struct radix_node_head *rnh; time_t nextstop; }; - static VNET_DEFINE(struct callout, rtq_mtutimer); #define V_rtq_mtutimer VNET(rtq_mtutimer) @@ -422,11 +422,6 @@ in6_inithead(void **head, int off) if (off == 0) /* See above */ return 1; /* only do the rest for the real thing */ - V_rtq_reallyold6 = 60*60; /* one hour is ``really old'' */ - V_rtq_minreallyold6 = 10; /* never automatically crank down to less */ - V_rtq_toomany6 = 128; /* 128 cached routes is ``too many'' */ - V_rtq_timeout6 = RTQ_TIMEOUT; - rnh = *head; KASSERT(rnh == rt_tables_get_rnh(0, AF_INET6), ("rnh?")); rnh->rnh_addaddr = in6_addroute; diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index e6c2cd8..49bc715 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -122,12 +122,11 @@ static struct sx addrsel_sxlock; #define ADDRSEL_XUNLOCK() sx_xunlock(&addrsel_sxlock) #define ADDR_LABEL_NOTAPP (-1) - static VNET_DEFINE(struct in6_addrpolicy, defaultaddrpolicy); -VNET_DEFINE(int, ip6_prefer_tempaddr); - #define V_defaultaddrpolicy VNET(defaultaddrpolicy) +VNET_DEFINE(int, ip6_prefer_tempaddr) = 0; + static int selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *, struct ip6_moptions *, struct route_in6 *, struct ifnet **, struct rtentry **, int)); @@ -952,8 +951,6 @@ void addrsel_policy_init(void) { - V_ip6_prefer_tempaddr = 0; - init_policy_queue(); /* initialize the "last resort" policy */ diff --git a/sys/netinet6/in6_var.h b/sys/netinet6/in6_var.h index d0a54e0..00342fd 100644 --- a/sys/netinet6/in6_var.h +++ b/sys/netinet6/in6_var.h @@ -487,12 +487,7 @@ struct in6_rrenumreq { #ifdef _KERNEL VNET_DECLARE(struct in6_ifaddrhead, in6_ifaddrhead); -VNET_DECLARE(struct icmp6stat, icmp6stat); -VNET_DECLARE(unsigned long, in6_maxmtu); - #define V_in6_ifaddrhead VNET(in6_ifaddrhead) -#define V_icmp6stat VNET(icmp6stat) -#define V_in6_maxmtu VNET(in6_maxmtu) extern struct rwlock in6_ifaddr_lock; #define IN6_IFADDR_LOCK_ASSERT( ) rw_assert(&in6_ifaddr_lock, RA_LOCKED) @@ -503,6 +498,8 @@ extern struct rwlock in6_ifaddr_lock; #define IN6_IFADDR_WLOCK_ASSERT() rw_assert(&in6_ifaddr_lock, RA_WLOCKED) #define IN6_IFADDR_WUNLOCK() rw_wunlock(&in6_ifaddr_lock) +VNET_DECLARE(struct icmp6stat, icmp6stat); +#define V_icmp6stat VNET(icmp6stat) #define in6_ifstat_inc(ifp, tag) \ do { \ if (ifp) \ @@ -511,6 +508,8 @@ do { \ extern struct in6_addr zeroin6_addr; extern u_char inet6ctlerrmap[]; +VNET_DECLARE(unsigned long, in6_maxmtu); +#define V_in6_maxmtu VNET(in6_maxmtu) #endif /* _KERNEL */ /* diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c index c244f37..42f9351 100644 --- a/sys/netinet6/ip6_input.c +++ b/sys/netinet6/ip6_input.c @@ -116,6 +116,7 @@ __FBSDID("$FreeBSD$"); extern struct domain inet6domain; u_char ip6_protox[IPPROTO_MAX]; +VNET_DEFINE(struct in6_ifaddrhead, in6_ifaddrhead); static struct netisr_handler ip6_nh = { .nh_name = "ip6", @@ -124,36 +125,16 @@ static struct netisr_handler ip6_nh = { .nh_policy = NETISR_POLICY_FLOW, }; -VNET_DEFINE(struct in6_ifaddrhead, in6_ifaddrhead); -VNET_DEFINE(struct ip6stat, ip6stat); - VNET_DECLARE(struct callout, in6_tmpaddrtimer_ch); -VNET_DECLARE(int, dad_init); -VNET_DECLARE(int, pmtu_expire); -VNET_DECLARE(int, pmtu_probe); -VNET_DECLARE(u_long, rip6_sendspace); -VNET_DECLARE(u_long, rip6_recvspace); -VNET_DECLARE(int, icmp6errppslim); -VNET_DECLARE(int, icmp6_nodeinfo); -VNET_DECLARE(int, udp6_sendspace); -VNET_DECLARE(int, udp6_recvspace); - #define V_in6_tmpaddrtimer_ch VNET(in6_tmpaddrtimer_ch) -#define V_dad_init VNET(dad_init) -#define V_pmtu_expire VNET(pmtu_expire) -#define V_pmtu_probe VNET(pmtu_probe) -#define V_rip6_sendspace VNET(rip6_sendspace) -#define V_rip6_recvspace VNET(rip6_recvspace) -#define V_icmp6errppslim VNET(icmp6errppslim) -#define V_icmp6_nodeinfo VNET(icmp6_nodeinfo) -#define V_udp6_sendspace VNET(udp6_sendspace) -#define V_udp6_recvspace VNET(udp6_recvspace) + +VNET_DEFINE(struct pfil_head, inet6_pfil_hook); + +VNET_DEFINE(struct ip6stat, ip6stat); struct rwlock in6_ifaddr_lock; RW_SYSINIT(in6_ifaddr_lock, &in6_ifaddr_lock, "in6_ifaddr_lock"); -VNET_DEFINE (struct pfil_head, inet6_pfil_hook); - static void ip6_init2(void *); static struct ip6aux *ip6_setdstifaddr(struct mbuf *, struct in6_ifaddr *); static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); @@ -171,82 +152,11 @@ ip6_init(void) struct ip6protosw *pr; int i; - V_in6_maxmtu = 0; -#ifdef IP6_AUTO_LINKLOCAL - V_ip6_auto_linklocal = IP6_AUTO_LINKLOCAL; -#else - V_ip6_auto_linklocal = 1; /* enabled by default */ -#endif TUNABLE_INT_FETCH("net.inet6.ip6.auto_linklocal", &V_ip6_auto_linklocal); -#ifndef IPV6FORWARDING -#ifdef GATEWAY6 -#define IPV6FORWARDING 1 /* forward IP6 packets not for us */ -#else -#define IPV6FORWARDING 0 /* don't forward IP6 packets not for us */ -#endif /* GATEWAY6 */ -#endif /* !IPV6FORWARDING */ - -#ifndef IPV6_SENDREDIRECTS -#define IPV6_SENDREDIRECTS 1 -#endif - - V_ip6_forwarding = IPV6FORWARDING; /* act as router? */ - V_ip6_sendredirects = IPV6_SENDREDIRECTS; - V_ip6_defhlim = IPV6_DEFHLIM; - V_ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS; - V_ip6_accept_rtadv = 0; - V_ip6_log_interval = 5; - V_ip6_hdrnestlimit = 15; /* How many header options will we process? */ - V_ip6_dad_count = 1; /* DupAddrDetectionTransmits */ - V_ip6_auto_flowlabel = 1; - V_ip6_use_deprecated = 1;/* allow deprecated addr (RFC2462 5.5.4) */ - V_ip6_rr_prune = 5; /* router renumbering prefix - * walk list every 5 sec. */ - V_ip6_mcast_pmtu = 0; /* enable pMTU discovery for multicast? */ - V_ip6_v6only = 1; - V_ip6_keepfaith = 0; - V_ip6_log_time = (time_t)0L; -#ifdef IPSTEALTH - V_ip6stealth = 0; -#endif - V_nd6_onlink_ns_rfc4861 = 0; /* allow 'on-link' nd6 NS (RFC 4861) */ - - V_pmtu_expire = 60*10; - V_pmtu_probe = 60*2; - - /* raw IP6 parameters */ - /* - * Nominal space allocated to a raw ip socket. - */ -#define RIPV6SNDQ 8192 -#define RIPV6RCVQ 8192 - V_rip6_sendspace = RIPV6SNDQ; - V_rip6_recvspace = RIPV6RCVQ; - - /* ICMPV6 parameters */ - V_icmp6_rediraccept = 1; /* accept and process redirects */ - V_icmp6_redirtimeout = 10 * 60; /* 10 minutes */ - V_icmp6errppslim = 100; /* 100pps */ - /* control how to respond to NI queries */ - V_icmp6_nodeinfo = (ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK); - - /* UDP on IP6 parameters */ - V_udp6_sendspace = 9216; /* really max datagram size */ - V_udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6)); - /* 40 1K datagrams */ - V_dad_init = 0; - TAILQ_INIT(&V_in6_ifaddrhead); - scope6_init(); - addrsel_policy_init(); - nd6_init(); - frag6_init(); - - V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR; - /* Initialize packet filter hooks. */ V_inet6_pfil_hook.ph_type = PFIL_TYPE_AF; V_inet6_pfil_hook.ph_af = AF_INET6; @@ -254,6 +164,13 @@ ip6_init(void) printf("%s: WARNING: unable to register pfil hook, " "error %d\n", __func__, i); + scope6_init(); + addrsel_policy_init(); + nd6_init(); + frag6_init(); + + V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR; + /* Skip global initialization stuff for non-default instances. */ if (!IS_DEFAULT_VNET(curvnet)) return; diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c index 5496062..0c1ff78 100644 --- a/sys/netinet6/ip6_mroute.c +++ b/sys/netinet6/ip6_mroute.c @@ -130,7 +130,6 @@ static MALLOC_DEFINE(M_MRTABLE6, "mf6c", "multicast forwarding cache entry"); static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *); static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *); -static void pim6_init(void); static int register_send(struct ip6_hdr *, struct mif6 *, struct mbuf *); static int set_pim6(int *); static int socket_send(struct socket *, struct mbuf *, @@ -148,12 +147,11 @@ static const struct ip6protosw in6_pim_protosw = { .pr_input = pim6_input, .pr_output = rip6_output, .pr_ctloutput = rip6_ctloutput, - .pr_init = pim6_init, .pr_usrreqs = &rip6_usrreqs }; static int pim6_encapcheck(const struct mbuf *, int, int, void *); -static VNET_DEFINE(int, ip6_mrouter_ver); +static VNET_DEFINE(int, ip6_mrouter_ver) = 0; #define V_ip6_mrouter_ver VNET(ip6_mrouter_ver) SYSCTL_DECL(_net_inet6); @@ -212,7 +210,7 @@ static struct mtx mif6_mtx; #define MIF6_LOCK_DESTROY() mtx_destroy(&mif6_mtx) #ifdef MRT6DEBUG -static VNET_DEFINE(u_int, mrt6debug); /* debug level */ +static VNET_DEFINE(u_int, mrt6debug) = 0; /* debug level */ #define V_mrt6debug VNET(mrt6debug) #define DEBUG_MFC 0x02 #define DEBUG_FORWARD 0x04 @@ -338,15 +336,6 @@ int X_ip6_mrouter_set(struct socket *, struct sockopt *); int X_ip6_mrouter_get(struct socket *, struct sockopt *); int X_mrt6_ioctl(u_long, caddr_t); -static void -pim6_init(void) -{ - -#ifdef MRT6DEBUG - V_mrt6debug = 0; /* debug level */ -#endif -} - /* * Handle MRT setsockopt commands to modify the multicast routing tables. */ @@ -533,11 +522,7 @@ static int ip6_mrouter_init(struct socket *so, int v, int cmd) { - V_ip6_mrouter_ver = 0; - #ifdef MRT6DEBUG - V_mrt6debug = 0; - if (V_mrt6debug) log(LOG_DEBUG, "ip6_mrouter_init: so_type = %d, pr_protocol = %d\n", diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index a0a0f3a..3e91a79 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -295,12 +295,20 @@ VNET_DECLARE(struct ip6stat, ip6stat); /* statistics */ VNET_DECLARE(int, ip6_defhlim); /* default hop limit */ VNET_DECLARE(int, ip6_defmcasthlim); /* default multicast hop limit */ VNET_DECLARE(int, ip6_forwarding); /* act as router? */ -VNET_DECLARE(int, ip6_gif_hlim); /* Hop limit for gif encap packet */ VNET_DECLARE(int, ip6_use_deprecated); /* allow deprecated addr as source */ VNET_DECLARE(int, ip6_rr_prune); /* router renumbering prefix * walk list every 5 sec. */ VNET_DECLARE(int, ip6_mcast_pmtu); /* enable pMTU discovery for multicast? */ VNET_DECLARE(int, ip6_v6only); +#define V_ip6stat VNET(ip6stat) +#define V_ip6_defhlim VNET(ip6_defhlim) +#define V_ip6_defmcasthlim VNET(ip6_defmcasthlim) +#define V_ip6_forwarding VNET(ip6_forwarding) +#define V_ip6_use_deprecated VNET(ip6_use_deprecated) +#define V_ip6_rr_prune VNET(ip6_rr_prune) +#define V_ip6_mcast_pmtu VNET(ip6_mcast_pmtu) +#define V_ip6_v6only VNET(ip6_v6only) + VNET_DECLARE(struct socket *, ip6_mrouter); /* multicast routing daemon */ VNET_DECLARE(int, ip6_sendredirects); /* send IP redirects when forwarding? */ VNET_DECLARE(int, ip6_maxfragpackets); /* Maximum packets in reassembly @@ -314,31 +322,6 @@ VNET_DECLARE(time_t, ip6_log_time); VNET_DECLARE(int, ip6_hdrnestlimit); /* upper limit of # of extension * headers */ VNET_DECLARE(int, ip6_dad_count); /* DupAddrDetectionTransmits */ - -VNET_DECLARE(int, ip6_auto_flowlabel); -VNET_DECLARE(int, ip6_auto_linklocal); - -VNET_DECLARE(int, ip6_use_tempaddr); /* Whether to use temporary addresses */ -VNET_DECLARE(int, ip6_prefer_tempaddr); /* Whether to prefer temporary - * addresses in the source address - * selection */ - -#ifdef IPSTEALTH -VNET_DECLARE(int, ip6stealth); -#endif - -VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope - * zone when unspecified */ - -#define V_ip6stat VNET(ip6stat) -#define V_ip6_defhlim VNET(ip6_defhlim) -#define V_ip6_defmcasthlim VNET(ip6_defmcasthlim) -#define V_ip6_forwarding VNET(ip6_forwarding) -#define V_ip6_gif_hlim VNET(ip6_gif_hlim) -#define V_ip6_use_deprecated VNET(ip6_use_deprecated) -#define V_ip6_rr_prune VNET(ip6_rr_prune) -#define V_ip6_mcast_pmtu VNET(ip6_mcast_pmtu) -#define V_ip6_v6only VNET(ip6_v6only) #define V_ip6_mrouter VNET(ip6_mrouter) #define V_ip6_sendredirects VNET(ip6_sendredirects) #define V_ip6_maxfragpackets VNET(ip6_maxfragpackets) @@ -349,17 +332,29 @@ VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope #define V_ip6_log_time VNET(ip6_log_time) #define V_ip6_hdrnestlimit VNET(ip6_hdrnestlimit) #define V_ip6_dad_count VNET(ip6_dad_count) + +VNET_DECLARE(int, ip6_auto_flowlabel); +VNET_DECLARE(int, ip6_auto_linklocal); #define V_ip6_auto_flowlabel VNET(ip6_auto_flowlabel) #define V_ip6_auto_linklocal VNET(ip6_auto_linklocal) + +VNET_DECLARE(int, ip6_use_tempaddr); /* Whether to use temporary addresses */ +VNET_DECLARE(int, ip6_prefer_tempaddr); /* Whether to prefer temporary + * addresses in the source address + * selection */ #define V_ip6_use_tempaddr VNET(ip6_use_tempaddr) #define V_ip6_prefer_tempaddr VNET(ip6_prefer_tempaddr) -#ifdef IPSTEALTH -#define V_ip6stealth VNET(ip6stealth) -#endif + +VNET_DECLARE(int, ip6_use_defzone); /* Whether to use the default scope + * zone when unspecified */ #define V_ip6_use_defzone VNET(ip6_use_defzone) VNET_DECLARE (struct pfil_head, inet6_pfil_hook); /* packet filter hooks */ #define V_inet6_pfil_hook VNET(inet6_pfil_hook) +#ifdef IPSTEALTH +VNET_DECLARE(int, ip6stealth); +#define V_ip6stealth VNET(ip6stealth) +#endif extern struct pr_usrreqs rip6_usrreqs; struct sockopt; diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index a0ef204..7a54226 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -82,21 +82,31 @@ __FBSDID("$FreeBSD$"); #define SIN6(s) ((struct sockaddr_in6 *)s) -VNET_DEFINE(int, nd6_prune); -VNET_DEFINE(int, nd6_delay); -VNET_DEFINE(int, nd6_umaxtries); -VNET_DEFINE(int, nd6_mmaxtries); -VNET_DEFINE(int, nd6_useloopback); -VNET_DEFINE(int, nd6_gctimer); +/* timer values */ +VNET_DEFINE(int, nd6_prune) = 1; /* walk list every 1 seconds */ +VNET_DEFINE(int, nd6_delay) = 5; /* delay first probe time 5 second */ +VNET_DEFINE(int, nd6_umaxtries) = 3; /* maximum unicast query */ +VNET_DEFINE(int, nd6_mmaxtries) = 3; /* maximum multicast query */ +VNET_DEFINE(int, nd6_useloopback) = 1; /* use loopback interface for + * local traffic */ +VNET_DEFINE(int, nd6_gctimer) = (60 * 60 * 24); /* 1 day: garbage + * collection timer */ /* preventing too many loops in ND option parsing */ -static VNET_DEFINE(int, nd6_maxndopt); -VNET_DEFINE(int, nd6_maxnudhint); -static VNET_DEFINE(int, nd6_maxqueuelen); +static VNET_DEFINE(int, nd6_maxndopt) = 10; /* max # of ND options allowed */ + +VNET_DEFINE(int, nd6_maxnudhint) = 0; /* max # of subsequent upper + * layer hints */ +static VNET_DEFINE(int, nd6_maxqueuelen) = 1; /* max pkts cached in unresolved + * ND entries */ #define V_nd6_maxndopt VNET(nd6_maxndopt) #define V_nd6_maxqueuelen VNET(nd6_maxqueuelen) -VNET_DEFINE(int, nd6_debug); +#ifdef ND6_DEBUG +VNET_DEFINE(int, nd6_debug) = 1; +#else +VNET_DEFINE(int, nd6_debug) = 0; +#endif /* for debugging? */ #if 0 @@ -106,7 +116,7 @@ static int nd6_inuse, nd6_allocated; VNET_DEFINE(struct nd_drhead, nd_defrouter); VNET_DEFINE(struct nd_prhead, nd_prefix); -VNET_DEFINE(int, nd6_recalc_reachtm_interval); +VNET_DEFINE(int, nd6_recalc_reachtm_interval) = ND6_RECALC_REACHTM_INTERVAL; #define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval) static struct sockaddr_in6 all1_sa; @@ -125,56 +135,13 @@ static VNET_DEFINE(struct callout, nd6_slowtimo_ch); VNET_DEFINE(struct callout, nd6_timer_ch); -VNET_DECLARE(int, dad_ignore_ns); -VNET_DECLARE(int, dad_maxtry); -#define V_dad_ignore_ns VNET(dad_ignore_ns) -#define V_dad_maxtry VNET(dad_maxtry) - void nd6_init(void) { int i; - V_nd6_prune = 1; /* walk list every 1 seconds */ - V_nd6_delay = 5; /* delay first probe time 5 second */ - V_nd6_umaxtries = 3; /* maximum unicast query */ - V_nd6_mmaxtries = 3; /* maximum multicast query */ - V_nd6_useloopback = 1; /* use loopback interface for local traffic */ - V_nd6_gctimer = (60 * 60 * 24); /* 1 day: garbage collection timer */ - - /* preventing too many loops in ND option parsing */ - V_nd6_maxndopt = 10; /* max # of ND options allowed */ - - V_nd6_maxnudhint = 0; /* max # of subsequent upper layer hints */ - V_nd6_maxqueuelen = 1; /* max pkts cached in unresolved ND entries */ - -#ifdef ND6_DEBUG - V_nd6_debug = 1; -#else - V_nd6_debug = 0; -#endif - - V_nd6_recalc_reachtm_interval = ND6_RECALC_REACHTM_INTERVAL; - - V_dad_ignore_ns = 0; /* ignore NS in DAD - specwise incorrect*/ - V_dad_maxtry = 15; /* max # of *tries* to transmit DAD packet */ - - /* - * XXX just to get this to compile KMM - */ -#ifdef notyet - V_llinfo_nd6.ln_next = &V_llinfo_nd6; - V_llinfo_nd6.ln_prev = &V_llinfo_nd6; -#endif LIST_INIT(&V_nd_prefix); - V_ip6_use_tempaddr = 0; - V_ip6_temp_preferred_lifetime = DEF_TEMP_PREFERRED_LIFETIME; - V_ip6_temp_valid_lifetime = DEF_TEMP_VALID_LIFETIME; - V_ip6_temp_regen_advance = TEMPADDR_REGEN_ADVANCE; - - V_ip6_desync_factor = 0; - all1_sa.sin6_family = AF_INET6; all1_sa.sin6_len = sizeof(struct sockaddr_in6); for (i = 0; i < sizeof(all1_sa.sin6_addr); i++) @@ -182,13 +149,13 @@ nd6_init(void) /* initialization of the default router list */ TAILQ_INIT(&V_nd_defrouter); + /* start timer */ callout_init(&V_nd6_slowtimo_ch, 0); callout_reset(&V_nd6_slowtimo_ch, ND6_SLOWTIMER_INTERVAL * hz, nd6_slowtimo, curvnet); } - #ifdef VIMAGE void nd6_destroy() diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index ff8faa2..abcfcb7 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -330,8 +330,6 @@ VNET_DECLARE(struct nd_drhead, nd_defrouter); VNET_DECLARE(struct nd_prhead, nd_prefix); VNET_DECLARE(int, nd6_debug); VNET_DECLARE(int, nd6_onlink_ns_rfc4861); -VNET_DECLARE(struct callout, nd6_timer_ch); - #define V_nd6_prune VNET(nd6_prune) #define V_nd6_delay VNET(nd6_delay) #define V_nd6_umaxtries VNET(nd6_umaxtries) @@ -343,6 +341,10 @@ VNET_DECLARE(struct callout, nd6_timer_ch); #define V_nd_prefix VNET(nd_prefix) #define V_nd6_debug VNET(nd6_debug) #define V_nd6_onlink_ns_rfc4861 VNET(nd6_onlink_ns_rfc4861) + +#define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0) + +VNET_DECLARE(struct callout, nd6_timer_ch); #define V_nd6_timer_ch VNET(nd6_timer_ch) /* nd6_rtr.c */ @@ -351,15 +353,12 @@ VNET_DECLARE(int, ip6_desync_factor); /* seconds */ VNET_DECLARE(u_int32_t, ip6_temp_preferred_lifetime); /* seconds */ VNET_DECLARE(u_int32_t, ip6_temp_valid_lifetime); /* seconds */ VNET_DECLARE(int, ip6_temp_regen_advance); /* seconds */ - #define V_nd6_defifindex VNET(nd6_defifindex) #define V_ip6_desync_factor VNET(ip6_desync_factor) #define V_ip6_temp_preferred_lifetime VNET(ip6_temp_preferred_lifetime) #define V_ip6_temp_valid_lifetime VNET(ip6_temp_valid_lifetime) #define V_ip6_temp_regen_advance VNET(ip6_temp_regen_advance) -#define nd6log(x) do { if (V_nd6_debug) log x; } while (/*CONSTCOND*/ 0) - union nd_opts { struct nd_opt_hdr *nd_opt_array[8]; /* max = target address list */ struct { diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c index f9061d3..a50925b 100644 --- a/sys/netinet6/nd6_nbr.c +++ b/sys/netinet6/nd6_nbr.c @@ -89,9 +89,8 @@ static void nd6_dad_ns_output(struct dadq *, struct ifaddr *); static void nd6_dad_ns_input(struct ifaddr *); static void nd6_dad_na_input(struct ifaddr *); -VNET_DEFINE(int, dad_ignore_ns); -VNET_DEFINE(int, dad_maxtry); - +VNET_DEFINE(int, dad_ignore_ns) = 0; /* ignore NS in DAD - specwise incorrect*/ +VNET_DEFINE(int, dad_maxtry) = 15; /* max # of *tries* to transmit DAD packet */ #define V_dad_ignore_ns VNET(dad_ignore_ns) #define V_dad_maxtry VNET(dad_maxtry) @@ -1124,9 +1123,8 @@ struct dadq { }; static VNET_DEFINE(TAILQ_HEAD(, dadq), dadq); +VNET_DEFINE(int, dad_init) = 0; #define V_dadq VNET(dadq) - -VNET_DEFINE(int, dad_init); #define V_dad_init VNET(dad_init) static struct dadq * diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c index 74f4954..19ec989 100644 --- a/sys/netinet6/nd6_rtr.c +++ b/sys/netinet6/nd6_rtr.c @@ -90,14 +90,16 @@ VNET_DECLARE(int, nd6_recalc_reachtm_interval); #define V_nd6_recalc_reachtm_interval VNET(nd6_recalc_reachtm_interval) static VNET_DEFINE(struct ifnet *, nd6_defifp); +VNET_DEFINE(int, nd6_defifindex); #define V_nd6_defifp VNET(nd6_defifp) -VNET_DEFINE(int, nd6_defifindex); -VNET_DEFINE(int, ip6_use_tempaddr); +VNET_DEFINE(int, ip6_use_tempaddr) = 0; + VNET_DEFINE(int, ip6_desync_factor); -VNET_DEFINE(u_int32_t, ip6_temp_preferred_lifetime); -VNET_DEFINE(u_int32_t, ip6_temp_valid_lifetime); -VNET_DEFINE(int, ip6_temp_regen_advance); +VNET_DEFINE(u_int32_t, ip6_temp_preferred_lifetime) = DEF_TEMP_PREFERRED_LIFETIME; +VNET_DEFINE(u_int32_t, ip6_temp_valid_lifetime) = DEF_TEMP_VALID_LIFETIME; + +VNET_DEFINE(int, ip6_temp_regen_advance) = TEMPADDR_REGEN_ADVANCE; /* RTPREF_MEDIUM has to be 0! */ #define RTPREF_HIGH 1 diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 6052b24..939aa6a 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -119,11 +119,11 @@ VNET_DECLARE(struct inpcbinfo, ripcbinfo); #define V_ripcb VNET(ripcb) #define V_ripcbinfo VNET(ripcbinfo) -VNET_DEFINE(struct rip6stat, rip6stat); - extern u_long rip_sendspace; extern u_long rip_recvspace; +VNET_DEFINE(struct rip6stat, rip6stat); + /* * Hooks for multicast routing. They all default to NULL, so leave them not * initialized and rely on BSS being set to 0. diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c index cced5e30..8189d87 100644 --- a/sys/netinet6/scope6.c +++ b/sys/netinet6/scope6.c @@ -50,6 +50,11 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef ENABLE_DEFAULT_SCOPE +VNET_DEFINE(int, ip6_use_defzone) = 1; +#else +VNET_DEFINE(int, ip6_use_defzone) = 0; +#endif /* * The scope6_lock protects the global sid default stored in @@ -62,8 +67,6 @@ static struct mtx scope6_lock; #define SCOPE6_LOCK_ASSERT() mtx_assert(&scope6_lock, MA_OWNED) static VNET_DEFINE(struct scope6_id, sid_default); -VNET_DEFINE(int, ip6_use_defzone); - #define V_sid_default VNET(sid_default) #define SID(ifp) \ @@ -73,11 +76,6 @@ void scope6_init(void) { -#ifdef ENABLE_DEFAULT_SCOPE - V_ip6_use_defzone = 1; -#else - V_ip6_use_defzone = 0; -#endif bzero(&V_sid_default, sizeof(V_sid_default)); if (!IS_DEFAULT_VNET(curvnet)) diff --git a/sys/netipsec/ah_var.h b/sys/netipsec/ah_var.h index b031a98..6145dba 100644 --- a/sys/netipsec/ah_var.h +++ b/sys/netipsec/ah_var.h @@ -72,10 +72,11 @@ struct ahstat { #ifdef _KERNEL VNET_DECLARE(int, ah_enable); -#define V_ah_enable VNET(ah_enable) VNET_DECLARE(int, ah_cleartos); -#define V_ah_cleartos VNET(ah_cleartos) VNET_DECLARE(struct ahstat, ahstat); + +#define V_ah_enable VNET(ah_enable) +#define V_ah_cleartos VNET(ah_cleartos) #define V_ahstat VNET(ahstat) #endif /* _KERNEL */ #endif /*_NETIPSEC_AH_VAR_H_*/ diff --git a/sys/netipsec/esp_var.h b/sys/netipsec/esp_var.h index dc1aad4..477dcbf 100644 --- a/sys/netipsec/esp_var.h +++ b/sys/netipsec/esp_var.h @@ -73,8 +73,9 @@ struct espstat { #ifdef _KERNEL VNET_DECLARE(int, esp_enable); -#define V_esp_enable VNET(esp_enable) VNET_DECLARE(struct espstat, espstat); + +#define V_esp_enable VNET(esp_enable) #define V_espstat VNET(espstat) #endif /* _KERNEL */ #endif /*_NETIPSEC_ESP_VAR_H_*/ diff --git a/sys/netipsec/ipcomp_var.h b/sys/netipsec/ipcomp_var.h index 78f1848..c99a3be 100644 --- a/sys/netipsec/ipcomp_var.h +++ b/sys/netipsec/ipcomp_var.h @@ -66,8 +66,9 @@ struct ipcompstat { #ifdef _KERNEL VNET_DECLARE(int, ipcomp_enable); -#define V_ipcomp_enable VNET(ipcomp_enable) VNET_DECLARE(struct ipcompstat, ipcompstat); + +#define V_ipcomp_enable VNET(ipcomp_enable) #define V_ipcompstat VNET(ipcompstat) #endif /* _KERNEL */ #endif /*_NETIPSEC_IPCOMP_VAR_H_*/ diff --git a/sys/netipsec/ipip_var.h b/sys/netipsec/ipip_var.h index a6e33e8..3c8c397 100644 --- a/sys/netipsec/ipip_var.h +++ b/sys/netipsec/ipip_var.h @@ -60,8 +60,9 @@ struct ipipstat #ifdef _KERNEL VNET_DECLARE(int, ipip_allow); -#define V_ipip_allow VNET(ipip_allow) VNET_DECLARE(struct ipipstat, ipipstat); + +#define V_ipip_allow VNET(ipip_allow) #define V_ipipstat VNET(ipipstat) #endif /* _KERNEL */ #endif /* _NETINET_IPIP_H_ */ diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c index 5ee4bbb..1f48dd6 100644 --- a/sys/netipsec/ipsec.c +++ b/sys/netipsec/ipsec.c @@ -102,6 +102,7 @@ VNET_DEFINE(int, ipsec_debug) = 1; #else VNET_DEFINE(int, ipsec_debug) = 0; #endif + /* NB: name changed so netstat doesn't use it. */ VNET_DEFINE(struct ipsecstat, ipsec4stat); VNET_DEFINE(int, ip4_ah_offsetmask) = 0; /* maybe IP_DF? */ diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h index 92539b9..090255a 100644 --- a/sys/netipsec/ipsec.h +++ b/sys/netipsec/ipsec.h @@ -334,39 +334,39 @@ struct ipsec_history { VNET_DECLARE(int, ipsec_debug); #define V_ipsec_debug VNET(ipsec_debug) + +#ifdef REGRESSION +VNET_DECLARE(int, ipsec_replay); +VNET_DECLARE(int, ipsec_integrity); + +#define V_ipsec_replay VNET(ipsec_replay) +#define V_ipsec_integrity VNET(ipsec_integrity) +#endif + VNET_DECLARE(struct ipsecstat, ipsec4stat); -#define V_ipsec4stat VNET(ipsec4stat) +VNET_DECLARE(struct secpolicy, ip4_def_policy); +VNET_DECLARE(int, ip4_esp_trans_deflev); +VNET_DECLARE(int, ip4_esp_net_deflev); +VNET_DECLARE(int, ip4_ah_trans_deflev); +VNET_DECLARE(int, ip4_ah_net_deflev); VNET_DECLARE(int, ip4_ah_offsetmask); -#define V_ip4_ah_offsetmask VNET(ip4_ah_offsetmask) VNET_DECLARE(int, ip4_ipsec_dfbit); -#define V_ip4_ipsec_dfbit VNET(ip4_ipsec_dfbit) -VNET_DECLARE(int, ip4_esp_trans_deflev); +VNET_DECLARE(int, ip4_ipsec_ecn); +VNET_DECLARE(int, ip4_esp_randpad); +VNET_DECLARE(int, crypto_support); + +#define V_ipsec4stat VNET(ipsec4stat) +#define V_ip4_def_policy VNET(ip4_def_policy) #define V_ip4_esp_trans_deflev VNET(ip4_esp_trans_deflev) -VNET_DECLARE(int, ip4_esp_net_deflev); #define V_ip4_esp_net_deflev VNET(ip4_esp_net_deflev) -VNET_DECLARE(int, ip4_ah_trans_deflev); #define V_ip4_ah_trans_deflev VNET(ip4_ah_trans_deflev) -VNET_DECLARE(int, ip4_ah_net_deflev); #define V_ip4_ah_net_deflev VNET(ip4_ah_net_deflev) -VNET_DECLARE(struct secpolicy, ip4_def_policy); -#define V_ip4_def_policy VNET(ip4_def_policy) -VNET_DECLARE(int, ip4_ipsec_ecn); +#define V_ip4_ah_offsetmask VNET(ip4_ah_offsetmask) +#define V_ip4_ipsec_dfbit VNET(ip4_ipsec_dfbit) #define V_ip4_ipsec_ecn VNET(ip4_ipsec_ecn) -VNET_DECLARE(int, ip4_esp_randpad); #define V_ip4_esp_randpad VNET(ip4_esp_randpad) - -VNET_DECLARE(int, crypto_support); #define V_crypto_support VNET(crypto_support) -extern int ip4_ah_cleartos; - -#ifdef REGRESSION -VNET_DECLARE(int, ipsec_replay); -#define V_ipsec_replay VNET(ipsec_replay) -VNET_DECLARE(int, ipsec_integrity); -#define V_ipsec_integrity VNET(ipsec_integrity) -#endif - #define ipseclog(x) do { if (V_ipsec_debug) log x; } while (0) /* for openbsd compatibility */ #define DPRINTF(x) do { if (V_ipsec_debug) printf x; } while (0) diff --git a/sys/netipsec/ipsec6.h b/sys/netipsec/ipsec6.h index 030113f..c004220 100644 --- a/sys/netipsec/ipsec6.h +++ b/sys/netipsec/ipsec6.h @@ -42,16 +42,17 @@ #ifdef _KERNEL VNET_DECLARE(struct ipsecstat, ipsec6stat); -#define V_ipsec6stat VNET(ipsec6stat) VNET_DECLARE(int, ip6_esp_trans_deflev); -#define V_ip6_esp_trans_deflev VNET(ip6_esp_trans_deflev) VNET_DECLARE(int, ip6_esp_net_deflev); -#define V_ip6_esp_net_deflev VNET(ip6_esp_net_deflev) VNET_DECLARE(int, ip6_ah_trans_deflev); -#define V_ip6_ah_trans_deflev VNET(ip6_ah_trans_deflev) VNET_DECLARE(int, ip6_ah_net_deflev); -#define V_ip6_ah_net_deflev VNET(ip6_ah_net_deflev) VNET_DECLARE(int, ip6_ipsec_ecn); + +#define V_ipsec6stat VNET(ipsec6stat) +#define V_ip6_esp_trans_deflev VNET(ip6_esp_trans_deflev) +#define V_ip6_esp_net_deflev VNET(ip6_esp_net_deflev) +#define V_ip6_ah_trans_deflev VNET(ip6_ah_trans_deflev) +#define V_ip6_ah_net_deflev VNET(ip6_ah_net_deflev) #define V_ip6_ipsec_ecn VNET(ip6_ipsec_ecn) struct inpcb; diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index 2b17fb0..5219768 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -114,27 +114,27 @@ VNET_DEFINE(u_int32_t, key_debug_level) = 0; static VNET_DEFINE(u_int, key_spi_trycnt) = 1000; -#define V_key_spi_trycnt VNET(key_spi_trycnt) static VNET_DEFINE(u_int32_t, key_spi_minval) = 0x100; -#define V_key_spi_minval VNET(key_spi_minval) static VNET_DEFINE(u_int32_t, key_spi_maxval) = 0x0fffffff; /* XXX */ -#define V_key_spi_maxval VNET(key_spi_maxval) static VNET_DEFINE(u_int32_t, policy_id) = 0; -#define V_policy_id VNET(policy_id) /*interval to initialize randseed,1(m)*/ static VNET_DEFINE(u_int, key_int_random) = 60; -#define V_key_int_random VNET(key_int_random) /* interval to expire acquiring, 30(s)*/ static VNET_DEFINE(u_int, key_larval_lifetime) = 30; -#define V_key_larval_lifetime VNET(key_larval_lifetime) /* counter for blocking SADB_ACQUIRE.*/ static VNET_DEFINE(int, key_blockacq_count) = 10; -#define V_key_blockacq_count VNET(key_blockacq_count) /* lifetime for blocking SADB_ACQUIRE.*/ static VNET_DEFINE(int, key_blockacq_lifetime) = 20; -#define V_key_blockacq_lifetime VNET(key_blockacq_lifetime) /* preferred old sa rather than new sa.*/ static VNET_DEFINE(int, key_preferred_oldsa) = 1; +#define V_key_spi_trycnt VNET(key_spi_trycnt) +#define V_key_spi_minval VNET(key_spi_minval) +#define V_key_spi_maxval VNET(key_spi_maxval) +#define V_policy_id VNET(policy_id) +#define V_key_int_random VNET(key_int_random) +#define V_key_larval_lifetime VNET(key_larval_lifetime) +#define V_key_blockacq_count VNET(key_blockacq_count) +#define V_key_blockacq_lifetime VNET(key_blockacq_lifetime) #define V_key_preferred_oldsa VNET(key_preferred_oldsa) static VNET_DEFINE(u_int32_t, acq_seq) = 0; @@ -270,10 +270,11 @@ static const int maxsize[] = { }; static VNET_DEFINE(int, ipsec_esp_keymin) = 256; -#define V_ipsec_esp_keymin VNET(ipsec_esp_keymin) static VNET_DEFINE(int, ipsec_esp_auth) = 0; -#define V_ipsec_esp_auth VNET(ipsec_esp_auth) static VNET_DEFINE(int, ipsec_ah_keymin) = 128; + +#define V_ipsec_esp_keymin VNET(ipsec_esp_keymin) +#define V_ipsec_esp_auth VNET(ipsec_esp_auth) #define V_ipsec_ah_keymin VNET(ipsec_ah_keymin) #ifdef SYSCTL_DECL diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c index dbacd77..6186b59 100644 --- a/sys/netipsec/xform_esp.c +++ b/sys/netipsec/xform_esp.c @@ -85,8 +85,7 @@ SYSCTL_VNET_INT(_net_inet_esp, OID_AUTO, SYSCTL_VNET_STRUCT(_net_inet_esp, IPSECCTL_STATS, stats, CTLFLAG_RD, &VNET_NAME(espstat), espstat, ""); -/* max iv length over all algorithms */ -static VNET_DEFINE(int, esp_max_ivlen) = 0; +static VNET_DEFINE(int, esp_max_ivlen); /* max iv length over all algorithms */ #define V_esp_max_ivlen VNET(esp_max_ivlen) static int esp_input_cb(struct cryptop *op); -- cgit v1.1 From 37a9ab0c6732ace50747a5e47b4eae9c67b72bba Mon Sep 17 00:00:00 2001 From: rpaulo Date: Thu, 29 Apr 2010 15:19:11 +0000 Subject: Decrement rxa_pad due to the addition of rxa_private. --- sys/net80211/ieee80211_ht.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/net80211/ieee80211_ht.h b/sys/net80211/ieee80211_ht.h index 21e7ff6..9cdc1ea 100644 --- a/sys/net80211/ieee80211_ht.h +++ b/sys/net80211/ieee80211_ht.h @@ -143,7 +143,7 @@ struct ieee80211_rx_ampdu { int rxa_nframes; /* frames since ADDBA */ struct mbuf *rxa_m[IEEE80211_AGGR_BAWMAX]; void *rxa_private; - uint64_t rxa_pad[4]; + uint64_t rxa_pad[3]; }; void ieee80211_ht_attach(struct ieee80211com *); -- cgit v1.1 From 0dcf2ac7ada163fca882dcaa5c89ddfcef286bf9 Mon Sep 17 00:00:00 2001 From: pjd Date: Thu, 29 Apr 2010 15:36:32 +0000 Subject: Fix a problem where hastd will stuck in recv(2) after sending request to secondary, which died between send(2) and recv(2). Do it by adding timeout to recv(2) for primary incoming and outgoing sockets and secondary outgoing socket. Reported by: Mikolaj Golub Tested by: Mikolaj Golub MFC after: 3 days --- sbin/hastd/hast.conf.5 | 7 +++++++ sbin/hastd/hast.h | 3 +++ sbin/hastd/hastd.c | 4 ++++ sbin/hastd/parse.y | 32 +++++++++++++++++++++++++++++++- sbin/hastd/primary.c | 6 ++++++ sbin/hastd/proto.c | 26 ++++++++++++++++++++++++++ sbin/hastd/proto.h | 1 + sbin/hastd/proto_common.c | 4 ++-- sbin/hastd/secondary.c | 6 ++++++ sbin/hastd/token.l | 1 + 10 files changed, 87 insertions(+), 3 deletions(-) diff --git a/sbin/hastd/hast.conf.5 b/sbin/hastd/hast.conf.5 index 5734ee8..1ccd479 100644 --- a/sbin/hastd/hast.conf.5 +++ b/sbin/hastd/hast.conf.5 @@ -58,6 +58,7 @@ file is following: control listen replication +timeout on { # Node section @@ -76,6 +77,7 @@ resource { replication name local + timeout on { # Resource-node section @@ -194,6 +196,11 @@ The .Ic async replication mode is currently not implemented. .El +.It Ic timeout Aq seconds +.Pp +Connection timeout in seconds. +The default value is +.Va 5 . .It Ic name Aq name .Pp GEOM provider name that will appear as diff --git a/sbin/hastd/hast.h b/sbin/hastd/hast.h index c5220b5..2230afb 100644 --- a/sbin/hastd/hast.h +++ b/sbin/hastd/hast.h @@ -75,6 +75,7 @@ #define HIO_DELETE 3 #define HIO_FLUSH 4 +#define HAST_TIMEOUT 5 #define HAST_CONFIG "/etc/hast.conf" #define HAST_CONTROL "/var/run/hastctl" #define HASTD_PORT 8457 @@ -148,6 +149,8 @@ struct hast_resource { /* Token to verify both in and out connection are coming from the same node (not necessarily from the same address). */ unsigned char hr_token[HAST_TOKEN_SIZE]; + /* Connection timeout. */ + int hr_timeout; /* Resource unique identifier. */ uint64_t hr_resuid; diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c index 7b2a8e2..7b1e228 100644 --- a/sbin/hastd/hastd.c +++ b/sbin/hastd/hastd.c @@ -187,6 +187,10 @@ listen_accept(void) proto_remote_address(conn, raddr, sizeof(raddr)); pjdlog_info("Connection from %s to %s.", laddr, raddr); + /* Error in setting timeout is not critical, but why should it fail? */ + if (proto_timeout(conn, HAST_TIMEOUT) < 0) + pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); + nvin = nvout = nverr = NULL; /* diff --git a/sbin/hastd/parse.y b/sbin/hastd/parse.y index 6755320..840a844 100644 --- a/sbin/hastd/parse.y +++ b/sbin/hastd/parse.y @@ -58,6 +58,7 @@ static bool mynode; static char depth0_control[HAST_ADDRSIZE]; static char depth0_listen[HAST_ADDRSIZE]; static int depth0_replication; +static int depth0_timeout; static char depth1_provname[PATH_MAX]; static char depth1_localpath[PATH_MAX]; @@ -115,6 +116,7 @@ yy_config_parse(const char *config) curres = NULL; mynode = false; + depth0_timeout = HAST_TIMEOUT; depth0_replication = HAST_REPLICATION_MEMSYNC; strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen)); @@ -154,6 +156,13 @@ yy_config_parse(const char *config) */ curres->hr_replication = depth0_replication; } + if (curres->hr_timeout == -1) { + /* + * Timeout is not set at resource-level. + * Use global or default setting. + */ + curres->hr_timeout = depth0_timeout; + } } return (&lconfig); @@ -171,7 +180,7 @@ yy_config_free(struct hastd_config *config) } %} -%token CONTROL LISTEN PORT REPLICATION EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON +%token CONTROL LISTEN PORT REPLICATION TIMEOUT EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON %token FULLSYNC MEMSYNC ASYNC %token NUM STR OB CB @@ -200,6 +209,8 @@ statement: | replication_statement | + timeout_statement + | node_statement | resource_statement @@ -281,6 +292,22 @@ replication_type: ASYNC { $$ = HAST_REPLICATION_ASYNC; } ; +timeout_statement: TIMEOUT NUM + { + switch (depth) { + case 0: + depth0_timeout = $2; + break; + case 1: + if (curres != NULL) + curres->hr_timeout = $2; + break; + default: + assert(!"timeout at wrong depth level"); + } + } + ; + node_statement: ON node_start OB node_entries CB { mynode = false; @@ -389,6 +416,7 @@ resource_start: STR curres->hr_role = HAST_ROLE_INIT; curres->hr_previous_role = HAST_ROLE_INIT; curres->hr_replication = -1; + curres->hr_timeout = -1; curres->hr_provname[0] = '\0'; curres->hr_localpath[0] = '\0'; curres->hr_localfd = -1; @@ -405,6 +433,8 @@ resource_entries: resource_entry: replication_statement | + timeout_statement + | name_statement | local_statement diff --git a/sbin/hastd/primary.c b/sbin/hastd/primary.c index 73f722b..9f2b2c7 100644 --- a/sbin/hastd/primary.c +++ b/sbin/hastd/primary.c @@ -489,6 +489,9 @@ init_remote(struct hast_resource *res, struct proto_conn **inp, res->hr_remoteaddr); goto close; } + /* Error in setting timeout is not critical, but why should it fail? */ + if (proto_timeout(out, res->hr_timeout) < 0) + pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); /* * First handshake step. * Setup outgoing connection with remote node. @@ -552,6 +555,9 @@ init_remote(struct hast_resource *res, struct proto_conn **inp, res->hr_remoteaddr); goto close; } + /* Error in setting timeout is not critical, but why should it fail? */ + if (proto_timeout(in, res->hr_timeout) < 0) + pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); nvout = nv_alloc(); nv_add_string(nvout, res->hr_name, "resource"); nv_add_uint8_array(nvout, res->hr_token, sizeof(res->hr_token), diff --git a/sbin/hastd/proto.c b/sbin/hastd/proto.c index 103f20c..531e7e5 100644 --- a/sbin/hastd/proto.c +++ b/sbin/hastd/proto.c @@ -30,7 +30,9 @@ #include __FBSDID("$FreeBSD$"); +#include #include +#include #include #include @@ -247,6 +249,30 @@ proto_remote_address(const struct proto_conn *conn, char *addr, size_t size) conn->pc_proto->hp_remote_address(conn->pc_ctx, addr, size); } +int +proto_timeout(const struct proto_conn *conn, int timeout) +{ + struct timeval tv; + int fd; + + assert(conn != NULL); + assert(conn->pc_magic == PROTO_CONN_MAGIC); + assert(conn->pc_proto != NULL); + + fd = proto_descriptor(conn); + if (fd < 0) + return (-1); + + tv.tv_sec = timeout; + tv.tv_usec = 0; + if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) + return (-1); + if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) + return (-1); + + return (0); +} + void proto_close(struct proto_conn *conn) { diff --git a/sbin/hastd/proto.h b/sbin/hastd/proto.h index cb196d8..13248ba 100644 --- a/sbin/hastd/proto.h +++ b/sbin/hastd/proto.h @@ -49,6 +49,7 @@ void proto_local_address(const struct proto_conn *conn, char *addr, size_t size); void proto_remote_address(const struct proto_conn *conn, char *addr, size_t size); +int proto_timeout(const struct proto_conn *conn, int timeout); void proto_close(struct proto_conn *conn); #endif /* !_PROTO_H_ */ diff --git a/sbin/hastd/proto_common.c b/sbin/hastd/proto_common.c index 22102d8..131d30e 100644 --- a/sbin/hastd/proto_common.c +++ b/sbin/hastd/proto_common.c @@ -58,7 +58,7 @@ proto_common_send(int fd, const unsigned char *data, size_t size) if (done == 0) return (ENOTCONN); else if (done < 0) { - if (errno == EAGAIN) + if (errno == EINTR) continue; return (errno); } @@ -76,7 +76,7 @@ proto_common_recv(int fd, unsigned char *data, size_t size) do { done = recv(fd, data, size, MSG_WAITALL); - } while (done == -1 && errno == EAGAIN); + } while (done == -1 && errno == EINTR); if (done == 0) return (ENOTCONN); else if (done < 0) diff --git a/sbin/hastd/secondary.c b/sbin/hastd/secondary.c index 6af95b5..b189b7e 100644 --- a/sbin/hastd/secondary.c +++ b/sbin/hastd/secondary.c @@ -337,6 +337,12 @@ hastd_secondary(struct hast_resource *res, struct nv *nvin) setproctitle("%s (secondary)", res->hr_name); + /* Error in setting timeout is not critical, but why should it fail? */ + if (proto_timeout(res->hr_remotein, 0) < 0) + pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); + if (proto_timeout(res->hr_remoteout, res->hr_timeout) < 0) + pjdlog_errno(LOG_WARNING, "Unable to set connection timeout"); + init_local(res); init_remote(res, nvin); init_environment(); diff --git a/sbin/hastd/token.l b/sbin/hastd/token.l index 7b80384..e5d4ca1 100644 --- a/sbin/hastd/token.l +++ b/sbin/hastd/token.l @@ -48,6 +48,7 @@ control { DP; return CONTROL; } listen { DP; return LISTEN; } port { DP; return PORT; } replication { DP; return REPLICATION; } +timeout { DP; return TIMEOUT; } resource { DP; return RESOURCE; } name { DP; return NAME; } local { DP; return LOCAL; } -- cgit v1.1 From db164aeb155dac81c7d06bc5e1780b7dadebde0b Mon Sep 17 00:00:00 2001 From: pjd Date: Thu, 29 Apr 2010 15:42:24 +0000 Subject: - Check if the worker process was killed by signal and restart it. - Improve logging. Pointed out by: Garrett Cooper MFC after: 3 days --- sbin/hastd/hastd.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/sbin/hastd/hastd.c b/sbin/hastd/hastd.c index 7b1e228..27b9bba 100644 --- a/sbin/hastd/hastd.c +++ b/sbin/hastd/hastd.c @@ -108,6 +108,22 @@ g_gate_load(void) } static void +child_exit_log(unsigned int pid, int status) +{ + + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + pjdlog_debug(1, "Worker process exited gracefully (pid=%u).", + pid); + } else if (WIFSIGNALED(status)) { + pjdlog_error("Worker process killed (pid=%u, signal=%d).", + pid, WTERMSIG(status)); + } else { + pjdlog_error("Worker process exited ungracefully (pid=%u, exitcode=%d).", + pid, WIFEXITED(status) ? WEXITSTATUS(status) : -1); + } +} + +static void child_exit(void) { struct hast_resource *res; @@ -129,18 +145,17 @@ child_exit(void) } pjdlog_prefix_set("[%s] (%s) ", res->hr_name, role2str(res->hr_role)); - if (WEXITSTATUS(status) == 0) { - pjdlog_debug(1, - "Worker process exited gracefully (pid=%u).", - (unsigned int)pid); - } else { - pjdlog_error("Worker process failed (pid=%u, status=%d).", - (unsigned int)pid, WEXITSTATUS(status)); - } + child_exit_log(pid, status); proto_close(res->hr_ctrl); res->hr_workerpid = 0; if (res->hr_role == HAST_ROLE_PRIMARY) { - if (WEXITSTATUS(status) == EX_TEMPFAIL) { + /* + * Restart child process if it was killed by signal + * or exited because of temporary problem. + */ + if (WIFSIGNALED(status) || + (WIFEXITED(status) && + WEXITSTATUS(status) == EX_TEMPFAIL)) { sleep(1); pjdlog_info("Restarting worker process."); hastd_primary(res); @@ -300,19 +315,12 @@ listen_accept(void) /* Wait for it to exit. */ else if ((pid = waitpid(res->hr_workerpid, &status, 0)) != res->hr_workerpid) { + /* We can only log the problem. */ pjdlog_errno(LOG_ERR, "Waiting for worker process (pid=%u) failed", (unsigned int)res->hr_workerpid); - /* See above. */ - } else if (WEXITSTATUS(status) != 0) { - pjdlog_error("Worker process (pid=%u) exited ungracefully: status=%d.", - (unsigned int)res->hr_workerpid, - WEXITSTATUS(status)); - /* See above. */ } else { - pjdlog_debug(1, - "Worker process (pid=%u) exited gracefully.", - (unsigned int)res->hr_workerpid); + child_exit_log(res->hr_workerpid, status); } res->hr_workerpid = 0; } else if (res->hr_remotein != NULL) { -- cgit v1.1 From df2257e061f55c35d76f33f91541c65c33f7a2a7 Mon Sep 17 00:00:00 2001 From: alc Date: Thu, 29 Apr 2010 15:47:31 +0000 Subject: MFamd64/i386 r207205 Clearing a page table entry's accessed bit and setting the page's PG_REFERENCED flag in pmap_protect() can't really be justified, so don't do it. Moreover, on ia64, don't set the page's dirty field unless pmap_protect() is removing write access. --- sys/ia64/ia64/pmap.c | 16 +++++----------- sys/sparc64/sparc64/pmap.c | 9 +++------ sys/sun4v/sun4v/pmap.c | 15 ++++----------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c index a7c47ef..91b2e07 100644 --- a/sys/ia64/ia64/pmap.c +++ b/sys/ia64/ia64/pmap.c @@ -1450,19 +1450,13 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) if (pmap_prot(pte) == prot) continue; - if (pmap_managed(pte)) { - vm_offset_t pa = pmap_ppn(pte); + if ((prot & VM_PROT_WRITE) == 0 && + pmap_managed(pte) && pmap_dirty(pte)) { + vm_paddr_t pa = pmap_ppn(pte); vm_page_t m = PHYS_TO_VM_PAGE(pa); - if (pmap_dirty(pte)) { - vm_page_dirty(m); - pmap_clear_dirty(pte); - } - - if (pmap_accessed(pte)) { - vm_page_flag_set(m, PG_REFERENCED); - pmap_clear_accessed(pte); - } + vm_page_dirty(m); + pmap_clear_dirty(pte); } if (prot & VM_PROT_EXECUTE) diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index d97900c..22ae860 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -1273,13 +1273,10 @@ pmap_protect_tte(struct pmap *pm, struct pmap *pm2, struct tte *tp, u_long data; vm_page_t m; - data = atomic_clear_long(&tp->tte_data, TD_REF | TD_SW | TD_W); - if ((data & TD_PV) != 0) { + data = atomic_clear_long(&tp->tte_data, TD_SW | TD_W); + if ((data & (TD_PV | TD_W)) == (TD_PV | TD_W)) { m = PHYS_TO_VM_PAGE(TD_PA(data)); - if ((data & TD_REF) != 0) - vm_page_flag_set(m, PG_REFERENCED); - if ((data & TD_W) != 0) - vm_page_dirty(m); + vm_page_dirty(m); } return (1); } diff --git a/sys/sun4v/sun4v/pmap.c b/sys/sun4v/sun4v/pmap.c index 2633b8e..cbd8106 100644 --- a/sys/sun4v/sun4v/pmap.c +++ b/sys/sun4v/sun4v/pmap.c @@ -1824,17 +1824,10 @@ pmap_protect(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, vm_prot_t prot) if (!anychanged && (otte_data & VTD_W)) anychanged = 1; - if (otte_data & VTD_MANAGED) { - m = NULL; - - if (otte_data & VTD_REF) { - m = PHYS_TO_VM_PAGE(TTE_GET_PA(otte_data)); - vm_page_flag_set(m, PG_REFERENCED); - } - if (otte_data & VTD_W) { - m = PHYS_TO_VM_PAGE(TTE_GET_PA(otte_data)); - vm_page_dirty(m); - } + if ((otte_data & (VTD_MANAGED | VTD_W)) == (VTD_MANAGED | + VTD_W)) { + m = PHYS_TO_VM_PAGE(TTE_GET_PA(otte_data)); + vm_page_dirty(m); } } -- cgit v1.1 From a05508f205782767efaaf7a6043901b3e1a3056d Mon Sep 17 00:00:00 2001 From: alc Date: Thu, 29 Apr 2010 16:18:45 +0000 Subject: Simplify the inner loop of vm_pageout_object_deactivate_pages(). Rather than checking each page for PG_UNMANAGED, check the vm object's type. Only OBJT_PHYS can have unmanaged pages. Eliminate a pointless counter. The vm object is locked, that lock is never released by the inner loop, and the set of pages contained by the vm object is not changed by the inner loop. Therefore, the counter serves no purpose. --- sys/vm/vm_pageout.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 735beee..258da8b 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -508,17 +508,16 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired) { vm_object_t backing_object, object; vm_page_t p, next; - int actcount, rcount, remove_mode; + int actcount, remove_mode; VM_OBJECT_LOCK_ASSERT(first_object, MA_OWNED); if (first_object->type == OBJT_DEVICE || - first_object->type == OBJT_SG || - first_object->type == OBJT_PHYS) + first_object->type == OBJT_SG) return; for (object = first_object;; object = backing_object) { if (pmap_resident_count(pmap) <= desired) goto unlock_return; - if (object->paging_in_progress) + if (object->type == OBJT_PHYS || object->paging_in_progress) goto unlock_return; remove_mode = 0; @@ -527,10 +526,9 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired) /* * scan the objects entire memory queue */ - rcount = object->resident_page_count; p = TAILQ_FIRST(&object->memq); vm_page_lock_queues(); - while (p && (rcount-- > 0)) { + while (p != NULL) { if (pmap_resident_count(pmap) <= desired) { vm_page_unlock_queues(); goto unlock_return; @@ -541,7 +539,6 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired) p->hold_count != 0 || p->busy != 0 || (p->oflags & VPO_BUSY) || - (p->flags & PG_UNMANAGED) || !pmap_page_exists_quick(pmap, p)) { p = next; continue; -- cgit v1.1 From a246ed9355e08cb824a3c0a02a16db772c33a915 Mon Sep 17 00:00:00 2001 From: yongari Date: Thu, 29 Apr 2010 17:28:07 +0000 Subject: Preserve unknown bits of RX MAC control register when driver programs RX filter configuration. It seems RX MAC control register is one of key registers to get various offloading features as well as performance. Blindly clearing unrelated bits can result in unexpected results. Tested by: xclin cs dot nctu dot edu dot tw > --- sys/dev/sge/if_sge.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index 6c737bd..49f6c0e 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -453,8 +453,9 @@ sge_rxfilter(struct sge_softc *sc) SGE_LOCK_ASSERT(sc); ifp = sc->sge_ifp; - hashes[0] = hashes[1] = 0; - rxfilt = AcceptMyPhys; + rxfilt = CSR_READ_2(sc, RxMacControl); + rxfilt &= ~(AcceptBroadcast | AcceptAllPhys | AcceptMulticast); + rxfilt |= AcceptMyPhys; if ((ifp->if_flags & IFF_BROADCAST) != 0) rxfilt |= AcceptBroadcast; if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) { @@ -463,20 +464,20 @@ sge_rxfilter(struct sge_softc *sc) rxfilt |= AcceptMulticast; hashes[0] = 0xFFFFFFFF; hashes[1] = 0xFFFFFFFF; - goto done; - } - rxfilt |= AcceptMulticast; - /* Now program new ones. */ - if_maddr_rlock(ifp); - TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { - if (ifma->ifma_addr->sa_family != AF_LINK) - continue; - crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) - ifma->ifma_addr), ETHER_ADDR_LEN); - hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); + } else { + rxfilt |= AcceptMulticast; + hashes[0] = hashes[1] = 0; + /* Now program new ones. */ + if_maddr_rlock(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + crc = ether_crc32_be(LLADDR((struct sockaddr_dl *) + ifma->ifma_addr), ETHER_ADDR_LEN); + hashes[crc >> 31] |= 1 << ((crc >> 26) & 0x1f); + } + if_maddr_runlock(ifp); } - if_maddr_runlock(ifp); -done: CSR_WRITE_2(sc, RxMacControl, rxfilt | 0x02); CSR_WRITE_4(sc, RxHashTable, hashes[0]); CSR_WRITE_4(sc, RxHashTable2, hashes[1]); -- cgit v1.1 From 6bf8e888ec998d27bd923a8c9a6f4473f7d02aab Mon Sep 17 00:00:00 2001 From: yongari Date: Thu, 29 Apr 2010 17:30:21 +0000 Subject: Remove wrong link state chage. --- sys/dev/sge/if_sge.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index 49f6c0e..736ac6a 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -1591,7 +1591,6 @@ sge_ifmedia_upd(struct ifnet *ifp) sc = ifp->if_softc; SGE_LOCK(sc); mii = device_get_softc(sc->sge_miibus); - sc->sge_flags &= ~SGE_FLAG_LINK; if (mii->mii_instance) { struct mii_softc *miisc; LIST_FOREACH(miisc, &mii->mii_phys, mii_list) -- cgit v1.1 From 76cab47064a41fa53a74e876f1f0024b16fcc959 Mon Sep 17 00:00:00 2001 From: yongari Date: Thu, 29 Apr 2010 17:34:01 +0000 Subject: Explicitly marks SiS190 to differentiate it from SiS191. --- sys/dev/sge/if_sge.c | 2 +- sys/dev/sge/if_sgereg.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index 736ac6a..813f063 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -572,7 +572,7 @@ sge_attach(device_t dev) } sc->sge_rev = pci_get_revid(dev); if (pci_get_device(dev) == SIS_DEVICEID_190) - sc->sge_flags |= SGE_FLAG_FASTETHER; + sc->sge_flags |= SGE_FLAG_FASTETHER | SGE_FLAG_SIS190; /* Reset the adapter. */ sge_reset(sc); diff --git a/sys/dev/sge/if_sgereg.h b/sys/dev/sge/if_sgereg.h index 29253e0..074886e 100644 --- a/sys/dev/sge/if_sgereg.h +++ b/sys/dev/sge/if_sgereg.h @@ -331,6 +331,7 @@ struct sge_softc { int sge_timer; int sge_flags; #define SGE_FLAG_FASTETHER 0x0001 +#define SGE_FLAG_SIS190 0x0002 #define SGE_FLAG_RGMII 0x0010 #define SGE_FLAG_SPEED_1000 0x2000 #define SGE_FLAG_FDX 0x4000 -- cgit v1.1 From a570282110995e0f6d99702a9761d4373e4c1dc6 Mon Sep 17 00:00:00 2001 From: yongari Date: Thu, 29 Apr 2010 18:00:42 +0000 Subject: Enable FCS stripping and padding 10 bytes bit of RX MAC control register. Due to lack of SiS190 controller, I'm not sure whether this is also applicable to SiS190 so this feature is only activated on SiS191 controller. The controller can pad 10 bytes before DMAing a received frame to RX buffer and received bytes include the padded bytes. This padding is very useful on strict-alignment architectures because driver does not have to copy received frame to align IP header on 4 bytes boundary. It also gives better RX performance on non-strict alignment architectures. Special thanks to xclin to give me valuable register information. Without his enthusiastic trial and errors this wouldn't be even possible. While I'm here tighten validity check of received frame. Controller clears RDS_CRCOK bit when it received bad CRC frames. xclin found that using loop back testing. Tested by: xclin cs dot nctu dot edu dot tw > --- sys/dev/sge/if_sge.c | 33 ++++++++++++++++++++++++++++----- sys/dev/sge/if_sgereg.h | 4 ++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index 813f063..d30f456 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -1144,7 +1144,8 @@ sge_rxeof(struct sge_softc *sc) if ((rxinfo & RDC_OWN) != 0) break; rxstat = le32toh(cur_rx->sge_sts_size); - if (SGE_RX_ERROR(rxstat) != 0 || SGE_RX_NSEGS(rxstat) != 1) { + if ((rxstat & RDS_CRCOK) == 0 || SGE_RX_ERROR(rxstat) != 0 || + SGE_RX_NSEGS(rxstat) != 1) { /* XXX We don't support multi-segment frames yet. */ #ifdef SGE_SHOW_ERRORS device_printf(sc->sge_dev, "Rx error : 0x%b\n", rxstat, @@ -1177,11 +1178,23 @@ sge_rxeof(struct sge_softc *sc) /* * TODO : VLAN hardware tag stripping. */ - m->m_pkthdr.len = m->m_len = - SGE_RX_BYTES(rxstat) - ETHER_CRC_LEN; + if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) { + /* + * Account for 10bytes auto padding which is used + * to align IP header on 32bit boundary. Also note, + * CRC bytes is automatically removed by the + * hardware. + */ + m->m_data += SGE_RX_PAD_BYTES; + m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) - + SGE_RX_PAD_BYTES; + } else { + m->m_pkthdr.len = m->m_len = SGE_RX_BYTES(rxstat) - + ETHER_CRC_LEN; #ifndef __NO_STRICT_ALIGNMENT - sge_fixup_rx(m); + sge_fixup_rx(m); #endif + } m->m_pkthdr.rcvif = ifp; ifp->if_ipackets++; SGE_UNLOCK(sc); @@ -1503,6 +1516,7 @@ sge_init_locked(struct sge_softc *sc) { struct ifnet *ifp; struct mii_data *mii; + uint16_t rxfilt; int i; SGE_LOCK_ASSERT(sc); @@ -1535,10 +1549,19 @@ sge_init_locked(struct sge_softc *sc) CSR_WRITE_4(sc, RxWakeOnLan, 0); CSR_WRITE_4(sc, RxWakeOnLanData, 0); /* Allow receiving VLAN frames. */ - CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN); + if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) + CSR_WRITE_2(sc, RxMPSControl, + ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN + SGE_RX_PAD_BYTES); + else + CSR_WRITE_2(sc, RxMPSControl, ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN); for (i = 0; i < ETHER_ADDR_LEN; i++) CSR_WRITE_1(sc, RxMacAddr + i, IF_LLADDR(ifp)[i]); + /* Configure RX MAC. */ + rxfilt = 0; + if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) + rxfilt |= RXMAC_STRIP_FCS | RXMAC_PAD_ENB; + CSR_WRITE_2(sc, RxMacControl, rxfilt); sge_rxfilter(sc); /* Initialize default speed/duplex information. */ diff --git a/sys/dev/sge/if_sgereg.h b/sys/dev/sge/if_sgereg.h index 074886e..e8cf514 100644 --- a/sys/dev/sge/if_sgereg.h +++ b/sys/dev/sge/if_sgereg.h @@ -137,6 +137,10 @@ #define AcceptAllPhys 0x0100 #define AcceptErr 0x0020 #define AcceptRunt 0x0010 +#define RXMAC_STRIP_FCS 0x0010 +#define RXMAC_PAD_ENB 0x0004 + +#define SGE_RX_PAD_BYTES 10 /* Station control register. */ #define SC_LOOPBACK 0x80000000 -- cgit v1.1 From 1294f271f53dae4b9e3a0fc0983b5d3ef574579d Mon Sep 17 00:00:00 2001 From: yongari Date: Thu, 29 Apr 2010 18:14:14 +0000 Subject: Enable VLAN hardware tag insertion/stripping. Due to lack of SiS190 controller, I'm not sure whether this is also applicable to SiS190 so this feature is only activated on SiS191 controller. In theory, controller reinitialization is not needed when VLAN tag configuration is changed, but xclin said controller was not stable whenever toggling VLAN tag bit. To address that, sge(4) reinitialize controller for VLAN configuration which seems to work as expected. VLAN tag information for TX/RX descriptor and configure bit of RxMacControl register was found by xclin. Submitted by: xclin cs dot nctu dot edu dot tw > (initial version) Tested by: xclin cs dot nctu dot edu dot tw > --- sys/dev/sge/if_sge.c | 58 +++++++++++++++++++++++++++++++++++++++++++++---- sys/dev/sge/if_sgereg.h | 8 +++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index d30f456..37476a2 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -137,6 +137,7 @@ static int sge_get_mac_addr_eeprom(struct sge_softc *, uint8_t *); static uint16_t sge_read_eeprom(struct sge_softc *, int); static void sge_rxfilter(struct sge_softc *); +static void sge_setvlan(struct sge_softc *); static void sge_reset(struct sge_softc *); static int sge_list_rx_init(struct sge_softc *); static int sge_list_rx_free(struct sge_softc *); @@ -484,6 +485,25 @@ sge_rxfilter(struct sge_softc *sc) } static void +sge_setvlan(struct sge_softc *sc) +{ + struct ifnet *ifp; + uint16_t rxfilt; + + SGE_LOCK_ASSERT(sc); + + ifp = sc->sge_ifp; + if ((ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0) + return; + rxfilt = CSR_READ_2(sc, RxMacControl); + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) + rxfilt |= RXMAC_STRIP_VLAN; + else + rxfilt &= ~RXMAC_STRIP_VLAN; + CSR_WRITE_2(sc, RxMacControl, rxfilt); +} + +static void sge_reset(struct sge_softc *sc) { @@ -619,6 +639,9 @@ sge_attach(device_t dev) ether_ifattach(ifp, eaddr); /* VLAN setup. */ + if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) + ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | + IFCAP_VLAN_HWCSUM; ifp->if_capabilities |= IFCAP_VLAN_MTU; ifp->if_capenable = ifp->if_capabilities; /* Tell the upper layer(s) we support long frames. */ @@ -1175,9 +1198,12 @@ sge_rxeof(struct sge_softc *sc) m->m_pkthdr.csum_data = 0xffff; } } - /* - * TODO : VLAN hardware tag stripping. - */ + /* Check for VLAN tagged frame. */ + if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 && + (rxstat & RDS_VLAN) != 0) { + m->m_pkthdr.ether_vtag = rxinfo & RDC_VLAN_MASK; + m->m_flags |= M_VLANTAG; + } if ((sc->sge_flags & SGE_FLAG_SIS190) == 0) { /* * Account for 10bytes auto padding which is used @@ -1422,6 +1448,11 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head) desc->sge_flags = htole32(txsegs[0].ds_len); if (prod == SGE_TX_RING_CNT - 1) desc->sge_flags |= htole32(RING_END); + /* Configure VLAN. */ + if(((*m_head)->m_flags & M_VLANTAG) != 0) { + cflags |= (*m_head)->m_pkthdr.ether_vtag; + desc->sge_sts_size |= htole32(TDS_INS_VLAN); + } desc->sge_cmdsts = htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags); #if 1 if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0) @@ -1563,6 +1594,7 @@ sge_init_locked(struct sge_softc *sc) rxfilt |= RXMAC_STRIP_FCS | RXMAC_PAD_ENB; CSR_WRITE_2(sc, RxMacControl, rxfilt); sge_rxfilter(sc); + sge_setvlan(sc); /* Initialize default speed/duplex information. */ if ((sc->sge_flags & SGE_FLAG_FASTETHER) == 0) @@ -1653,7 +1685,7 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) struct sge_softc *sc; struct ifreq *ifr; struct mii_data *mii; - int error = 0, mask; + int error = 0, mask, reinit; sc = ifp->if_softc; ifr = (struct ifreq *)data; @@ -1675,6 +1707,7 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) break; case SIOCSIFCAP: SGE_LOCK(sc); + reinit = 0; mask = ifr->ifr_reqcap ^ ifp->if_capenable; if ((mask & IFCAP_TXCSUM) != 0 && (ifp->if_capabilities & IFCAP_TXCSUM) != 0) { @@ -1687,7 +1720,24 @@ sge_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if ((mask & IFCAP_RXCSUM) != 0 && (ifp->if_capabilities & IFCAP_RXCSUM) != 0) ifp->if_capenable ^= IFCAP_RXCSUM; + if ((mask & IFCAP_VLAN_HWCSUM) != 0 && + (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0) + ifp->if_capenable ^= IFCAP_VLAN_HWCSUM; + if ((mask & IFCAP_VLAN_HWTAGGING) != 0 && + (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0) { + /* + * Due to unknown reason, toggling VLAN hardware + * tagging require interface reinitialization. + */ + ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; + reinit = 1; + } + if (reinit > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + sge_init_locked(sc); + } SGE_UNLOCK(sc); + VLAN_CAPABILITIES(ifp); break; case SIOCADDMULTI: case SIOCDELMULTI: diff --git a/sys/dev/sge/if_sgereg.h b/sys/dev/sge/if_sgereg.h index e8cf514..722dd3c 100644 --- a/sys/dev/sge/if_sgereg.h +++ b/sys/dev/sge/if_sgereg.h @@ -137,6 +137,7 @@ #define AcceptAllPhys 0x0100 #define AcceptErr 0x0020 #define AcceptRunt 0x0010 +#define RXMAC_STRIP_VLAN 0x0020 #define RXMAC_STRIP_FCS 0x0010 #define RXMAC_PAD_ENB 0x0004 @@ -187,12 +188,14 @@ #define TDC_COL 0x00040000 #define TDC_CRC 0x00020000 #define TDC_PAD 0x00010000 +#define TDC_VLAN_MASK 0x0000FFFF #define SGE_TX_INTR_FRAMES 32 /* * TX descriptor status bits. */ +#define TDS_INS_VLAN 0x80000000 #define TDS_OWC 0x00080000 #define TDS_ABT 0x00040000 #define TDS_FIFO 0x00020000 @@ -219,11 +222,12 @@ #define RDC_UCAST 0x00040000 #define RDC_CRCOFF 0x00020000 #define RDC_PREADD 0x00010000 +#define RDC_VLAN_MASK 0x0000FFFF /* * RX descriptor status bits */ -#define RDS_TAGON 0x80000000 +#define RDS_VLAN 0x80000000 #define RDS_DESCS 0x3f000000 #define RDS_ABORT 0x00800000 #define RDS_SHORT 0x00400000 @@ -240,7 +244,7 @@ #define RX_ERR_BITS "\20" \ "\21CRCOK\22COLON\23NIBON\24OVRUN" \ "\25MIIER\26LIMIT\27SHORT\30ABORT" \ - "\40TAGON" + "\40VLAN" #define RING_END 0x80000000 #define SGE_RX_BYTES(x) ((x) & 0xFFFF) -- cgit v1.1 From d597b82ca45c62e6be82119bb2240ac816160cb1 Mon Sep 17 00:00:00 2001 From: yongari Date: Thu, 29 Apr 2010 18:21:27 +0000 Subject: Now sge(4) supports hardware VLAN tag insertion/stripping. --- share/man/man4/sge.4 | 10 +++++----- share/man/man4/vlan.4 | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/share/man/man4/sge.4 b/share/man/man4/sge.4 index a3d057d..9ef179c 100644 --- a/share/man/man4/sge.4 +++ b/share/man/man4/sge.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 14, 2010 +.Dd April 29, 2010 .Dt SGE 4 .Os .Sh NAME @@ -53,11 +53,11 @@ controllers and SiS191 Fast/Gigabit Ethernet controllers. .Pp All LOMs supported by the .Nm -driver have TCP/UDP/IP checksum offload for transmit and receive. +driver have TCP/UDP/IP checksum offload for transmit and receive, +hardware VLAN tag stripping/insertion features. Due to lack of documentation more offloading features like TCP -segmentation offload (TSO), hardware VLAN tag stripping/insertion -features, Wake On Lan (WOL), Jumbo frame and an interrupt moderation -mechanism are not supported yet. +segmentation offload (TSO), Wake On Lan (WOL), Jumbo frame and an +interrupt moderation mechanism are not supported yet. .Pp The .Nm diff --git a/share/man/man4/vlan.4 b/share/man/man4/vlan.4 index f7f7807..17fff6a 100644 --- a/share/man/man4/vlan.4 +++ b/share/man/man4/vlan.4 @@ -134,6 +134,7 @@ in the hardware is limited to the following devices: .Xr msk 4 , .Xr nge 4 , .Xr re 4 , +.Xr sge 4 , .Xr stge 4 , .Xr ti 4 , .Xr txp 4 , @@ -172,7 +173,6 @@ natively: .Xr nve 4 , .Xr rl 4 , .Xr sf 4 , -.Xr sge 4 , .Xr sis 4 , .Xr sk 4 , .Xr ste 4 , -- cgit v1.1 From 1ca2e668b798d3452083d6ba8f932b37e7f41280 Mon Sep 17 00:00:00 2001 From: delphij Date: Thu, 29 Apr 2010 18:32:14 +0000 Subject: bwn(4) will first appear in FreeBSD 8.1-RELEASE. MFC after: 1 week --- share/man/man4/bwn.4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/share/man/man4/bwn.4 b/share/man/man4/bwn.4 index 1293c36..b75f9d0 100644 --- a/share/man/man4/bwn.4 +++ b/share/man/man4/bwn.4 @@ -123,7 +123,7 @@ ifconfig wlan create wlandev bwn0 ssid my_net \e The .Nm driver first appeared in -.Fx 8.0 . +.Fx 8.1 . .Sh AUTHORS .An -nosplit The -- cgit v1.1 From b520866979ef8cadf97e3db819b45046bc782c19 Mon Sep 17 00:00:00 2001 From: delphij Date: Thu, 29 Apr 2010 18:37:56 +0000 Subject: Add FreeBSD 8.1 to known list as it's being referenced by a couple of manpages already. MFC after: 3 days --- gnu/usr.bin/groff/tmac/mdoc.local | 1 + 1 file changed, 1 insertion(+) diff --git a/gnu/usr.bin/groff/tmac/mdoc.local b/gnu/usr.bin/groff/tmac/mdoc.local index 4c83635..a3073ff 100644 --- a/gnu/usr.bin/groff/tmac/mdoc.local +++ b/gnu/usr.bin/groff/tmac/mdoc.local @@ -75,6 +75,7 @@ .ds doc-operating-system-FreeBSD-7.2 7.2 .ds doc-operating-system-FreeBSD-7.3 7.3 .ds doc-operating-system-FreeBSD-8.0 8.0 +.ds doc-operating-system-FreeBSD-8.1 8.1 .ds doc-operating-system-FreeBSD-9.0 9.0 . .\" Definitions not (yet) in doc-syms -- cgit v1.1 From 1f717ed2d0f18a2bfb45acde8630100453f6b8a3 Mon Sep 17 00:00:00 2001 From: pjd Date: Thu, 29 Apr 2010 21:55:20 +0000 Subject: Default connection timeout is way too long. To make it shorter we have to make socket non-blocking, connect() and if we get EINPROGRESS, we have to wait using select(). Very complex, but I know no other way to define connection timeout for a given socket. Reported by: hiroshi@soupacific.com MFC after: 3 days --- sbin/hastd/proto_tcp4.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/sbin/hastd/proto_tcp4.c b/sbin/hastd/proto_tcp4.c index 2fba996..5af82d5 100644 --- a/sbin/hastd/proto_tcp4.c +++ b/sbin/hastd/proto_tcp4.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -47,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include "hast.h" #include "pjdlog.h" #include "proto_impl.h" +#include "subr.h" #define TCP4_CTX_MAGIC 0x7c441c struct tcp4_ctx { @@ -222,18 +224,88 @@ static int tcp4_connect(void *ctx) { struct tcp4_ctx *tctx = ctx; + struct timeval tv; + fd_set fdset; + socklen_t esize; + int error, flags, ret; assert(tctx != NULL); assert(tctx->tc_magic == TCP4_CTX_MAGIC); assert(tctx->tc_side == TCP4_SIDE_CLIENT); assert(tctx->tc_fd >= 0); - if (connect(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sin, - sizeof(tctx->tc_sin)) < 0) { + flags = fcntl(tctx->tc_fd, F_GETFL); + if (flags == -1) { + KEEP_ERRNO(pjdlog_common(LOG_DEBUG, 1, errno, + "fcntl(F_GETFL) failed")); + return (errno); + } + /* + * We make socket non-blocking so we have decided about connection + * timeout. + */ + flags |= O_NONBLOCK; + if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) { + KEEP_ERRNO(pjdlog_common(LOG_DEBUG, 1, errno, + "fcntl(F_SETFL, O_NONBLOCK) failed")); return (errno); } - return (0); + if (connect(tctx->tc_fd, (struct sockaddr *)&tctx->tc_sin, + sizeof(tctx->tc_sin)) == 0) { + error = 0; + goto done; + } + if (errno != EINPROGRESS) { + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, "connect() failed"); + goto done; + } + /* + * Connection can't be established immediately, let's wait + * for HAST_TIMEOUT seconds. + */ + tv.tv_sec = HAST_TIMEOUT; + tv.tv_usec = 0; +again: + FD_ZERO(&fdset); + FD_SET(tctx->tc_fd, &fdset); + ret = select(tctx->tc_fd + 1, NULL, &fdset, NULL, &tv); + if (ret == 0) { + error = ETIMEDOUT; + goto done; + } else if (ret == -1) { + if (errno == EINTR) + goto again; + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, "select() failed"); + goto done; + } + assert(ret > 0); + assert(FD_ISSET(tctx->tc_fd, &fdset)); + esize = sizeof(error); + if (getsockopt(tctx->tc_fd, SOL_SOCKET, SO_ERROR, &error, + &esize) == -1) { + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, + "getsockopt(SO_ERROR) failed"); + goto done; + } + if (error != 0) { + pjdlog_common(LOG_DEBUG, 1, error, + "getsockopt(SO_ERROR) returned error"); + goto done; + } + error = 0; +done: + flags &= ~O_NONBLOCK; + if (fcntl(tctx->tc_fd, F_SETFL, flags) == -1) { + if (error == 0) + error = errno; + pjdlog_common(LOG_DEBUG, 1, errno, + "fcntl(F_SETFL, ~O_NONBLOCK) failed"); + } + return (error); } static int -- cgit v1.1 From 104994efcf6a00276077f8e7a50df2b5b8bb3cec Mon Sep 17 00:00:00 2001 From: davidch Date: Thu, 29 Apr 2010 22:00:57 +0000 Subject: - Pass flow control settings back to bce(4). MFC after: Two weeks --- sys/dev/mii/brgphy.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index 97a423c..a733597 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -685,16 +685,15 @@ brgphy_status(struct mii_softc *sc) } -#if 0 - /* Todo: Change bge/bce to use these settings. */ + /* Todo: Change bge to use these settings. */ - /* Fetch flow control settings from the PHY */ + /* Fetch flow control settings from the copper PHY. */ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) { - /* Set FLAG0 is RX is enabled and FLAG1 if TX is enabled */ + /* Set FLAG0 if RX is enabled and FLAG1 if TX is enabled */ if ((anar & BRGPHY_ANAR_PC) && (anlpar & BRGPHY_ANLPAR_PC)) { mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1; } else if (!(anar & BRGPHY_ANAR_PC) && (anlpar & BRGPHY_ANAR_ASP) && - (anlpar & BRPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) { + (anlpar & BRGPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) { mii->mii_media_active |= IFM_FLAG1; } else if ((anar & BRGPHY_ANAR_PC) && (anar & BRGPHY_ANAR_ASP) && !(anlpar & BRGPHY_ANLPAR_PC) && (anlpar & BRGPHY_ANLPAR_ASP)) { @@ -703,7 +702,6 @@ brgphy_status(struct mii_softc *sc) } /* Todo: Add support for fiber settings too. */ -#endif brgphy_status_exit: -- cgit v1.1 From ed0300c12fff75dd5b24a7c1e90c16edee74d17e Mon Sep 17 00:00:00 2001 From: thompsa Date: Thu, 29 Apr 2010 22:51:18 +0000 Subject: usb_controller.c requires opt_ddb.h --- sys/modules/usb/usb/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/modules/usb/usb/Makefile b/sys/modules/usb/usb/Makefile index 5b0104e..32a2107 100644 --- a/sys/modules/usb/usb/Makefile +++ b/sys/modules/usb/usb/Makefile @@ -31,7 +31,7 @@ S= ${.CURDIR}/../../.. KMOD= usb SRCS= bus_if.h device_if.h usb_if.h usb_if.c vnode_if.h \ - opt_usb.h opt_bus.h \ + opt_usb.h opt_bus.h opt_ddb.h \ usbdevs.h usbdevs_data.h \ usb_busdma.c usb_controller.c usb_compat_linux.c usb_core.c usb_debug.c \ usb_dev.c usb_device.c usb_dynamic.c usb_error.c usb_generic.c \ -- cgit v1.1 From a43425e8835983e7c93a15a2d6a42fdb292c1676 Mon Sep 17 00:00:00 2001 From: yongari Date: Fri, 30 Apr 2010 00:34:00 +0000 Subject: Both RX_GMF_LP_THR and RX_GMF_UP_THR must be 16 bits register. If it is 8bits register then RX FIFO size can't exceed 2KB which is not true for almost all Yukon II controller. --- sys/dev/msk/if_msk.c | 4 ++-- sys/dev/msk/if_mskreg.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c index c083e1e..9b92435 100644 --- a/sys/dev/msk/if_msk.c +++ b/sys/dev/msk/if_msk.c @@ -3822,9 +3822,9 @@ msk_init_locked(struct msk_if_softc *sc_if) if ((sc_if->msk_flags & MSK_FLAG_RAMBUF) == 0) { /* Set Rx Pause threshould. */ - CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_LP_THR), + CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_LP_THR), MSK_ECU_LLPP); - CSR_WRITE_1(sc, MR_ADDR(sc_if->msk_port, RX_GMF_UP_THR), + CSR_WRITE_2(sc, MR_ADDR(sc_if->msk_port, RX_GMF_UP_THR), MSK_ECU_ULPP); /* Configure store-and-forward for Tx. */ msk_set_tx_stfwd(sc_if); diff --git a/sys/dev/msk/if_mskreg.h b/sys/dev/msk/if_mskreg.h index 34cac67..293ca29 100644 --- a/sys/dev/msk/if_mskreg.h +++ b/sys/dev/msk/if_mskreg.h @@ -621,8 +621,8 @@ #define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */ #define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */ #define RX_GMF_TR_THR 0x0c54 /* 32 bit Rx Truncation Threshold (Yukon-2) */ -#define RX_GMF_UP_THR 0x0c58 /* 8 bit Rx Upper Pause Thr (Yukon-EC_U) */ -#define RX_GMF_LP_THR 0x0c5a /* 8 bit Rx Lower Pause Thr (Yukon-EC_U) */ +#define RX_GMF_UP_THR 0x0c58 /* 16 bit Rx Upper Pause Thr (Yukon-EC_U) */ +#define RX_GMF_LP_THR 0x0c5a /* 16 bit Rx Lower Pause Thr (Yukon-EC_U) */ #define RX_GMF_VLAN 0x0c5c /* 32 bit Rx VLAN Type Register (Yukon-2) */ #define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */ #define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */ -- cgit v1.1 From 1dc1263413262d13f45f42d89c554d0ddc167ca2 Mon Sep 17 00:00:00 2001 From: kmacy Date: Fri, 30 Apr 2010 00:46:43 +0000 Subject: On Alan's advice, rather than do a wholesale conversion on a single architecture from page queue lock to a hashed array of page locks (based on a patch by Jeff Roberson), I've implemented page lock support in the MI code and have only moved vm_page's hold_count out from under page queue mutex to page lock. This changes pmap_extract_and_hold on all pmaps. Supported by: Bitgravity Inc. Discussed with: alc, jeffr, and kib --- UPDATING | 8 ++++ sys/amd64/amd64/pmap.c | 17 ++++++--- sys/amd64/include/pmap.h | 2 + sys/amd64/include/vmparam.h | 4 ++ sys/arm/arm/pmap.c | 13 ++++--- sys/arm/include/pmap.h | 2 + sys/dev/drm/via_dmablit.c | 2 + sys/i386/i386/pmap.c | 11 +++++- sys/i386/include/pmap.h | 3 ++ sys/i386/xen/pmap.c | 11 +++++- sys/ia64/ia64/pmap.c | 8 +++- sys/ia64/include/pmap.h | 2 + sys/kern/kern_exec.c | 8 ++-- sys/kern/subr_witness.c | 9 +++++ sys/kern/sys_pipe.c | 12 +++--- sys/kern/sys_process.c | 8 ++-- sys/kern/uipc_cow.c | 4 +- sys/kern/vfs_bio.c | 13 ++++--- sys/mips/include/pmap.h | 2 + sys/mips/mips/pmap.c | 11 ++++-- sys/net/bpf_zerocopy.c | 2 + sys/powerpc/aim/mmu_oea.c | 10 +++-- sys/powerpc/aim/mmu_oea64.c | 9 ++++- sys/powerpc/booke/pmap.c | 11 ++++-- sys/powerpc/include/pmap.h | 2 + sys/sparc64/include/pmap.h | 2 + sys/sparc64/sparc64/pmap.c | 14 ++++--- sys/sun4v/include/pmap.h | 2 + sys/sun4v/sun4v/pmap.c | 8 +++- sys/sys/param.h | 2 +- sys/vm/device_pager.c | 19 +++++++--- sys/vm/sg_pager.c | 9 +++-- sys/vm/swap_pager.c | 28 +++++++++++--- sys/vm/uma_core.c | 2 + sys/vm/vm_contig.c | 2 + sys/vm/vm_fault.c | 62 +++++++++++++++++++++++++++++-- sys/vm/vm_glue.c | 14 +++++-- sys/vm/vm_kern.c | 2 + sys/vm/vm_mmap.c | 2 + sys/vm/vm_object.c | 89 +++++++++++++++++++++++++++++++++++++++------ sys/vm/vm_page.c | 71 +++++++++++++++++++++++++++++++++++- sys/vm/vm_page.h | 29 ++++++++++++++- sys/vm/vm_pageout.c | 86 +++++++++++++++++++++++++++++++++++++------ sys/vm/vm_param.h | 8 ++++ sys/vm/vnode_pager.c | 85 ++++++++++++++++++++++++++++++------------- 45 files changed, 587 insertions(+), 133 deletions(-) diff --git a/UPDATING b/UPDATING index 553e961..937f917 100644 --- a/UPDATING +++ b/UPDATING @@ -22,6 +22,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW: machines to maximize performance. (To disable malloc debugging, run ln -s aj /etc/malloc.conf.) + +20100429: + 'vm_page's are now hashed by physical address to an array of mutexes. + Currently this is only used to serialize access to hold_count. Over + time the page queue mutex will be peeled away. This changes the size + of pmap on every architecture. And requires all callers of vm_page_hold + and vm_page_unhold to be updated. + 20100402: WITH_CTF can now be specified in src.conf (not recommended, there are some problems with static executables), make.conf (would also diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index d07292d..045b634 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -793,7 +793,6 @@ static u_long pmap_pdpe_demotions; SYSCTL_ULONG(_vm_pmap_pdpe, OID_AUTO, demotions, CTLFLAG_RD, &pmap_pdpe_demotions, 0, "1GB page demotions"); - /*************************************************** * Low level helper routines..... ***************************************************/ @@ -1200,15 +1199,20 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) { pd_entry_t pde, *pdep; pt_entry_t pte; + vm_paddr_t pa; vm_page_t m; + pa = 0; m = NULL; - vm_page_lock_queues(); PMAP_LOCK(pmap); +retry: pdep = pmap_pde(pmap, va); if (pdep != NULL && (pde = *pdep)) { if (pde & PG_PS) { if ((pde & PG_RW) || (prot & VM_PROT_WRITE) == 0) { + if (vm_page_pa_tryrelock(pmap, (pde & PG_PS_FRAME) | + (va & PDRMASK), &pa)) + goto retry; m = PHYS_TO_VM_PAGE((pde & PG_PS_FRAME) | (va & PDRMASK)); vm_page_hold(m); @@ -1217,12 +1221,14 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) pte = *pmap_pde_to_pte(pdep, va); if ((pte & PG_V) && ((pte & PG_RW) || (prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pmap, pte & PG_FRAME, &pa)) + goto retry; m = PHYS_TO_VM_PAGE(pte & PG_FRAME); vm_page_hold(m); } } } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); PMAP_UNLOCK(pmap); return (m); } @@ -3143,9 +3149,8 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m, * In the case that a page table page is not * resident, we are creating it here. */ - if (va < VM_MAXUSER_ADDRESS) { + if (va < VM_MAXUSER_ADDRESS) mpte = pmap_allocpte(pmap, va, M_WAITOK); - } pde = pmap_pde(pmap, va); if (pde != NULL && (*pde & PG_V) != 0) { @@ -3393,7 +3398,7 @@ pmap_enter_object(pmap_t pmap, vm_offset_t start, vm_offset_t end, mpte); m = TAILQ_NEXT(m, listq); } - PMAP_UNLOCK(pmap); + PMAP_UNLOCK(pmap); } /* diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index 11a5628..6f0b188 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -245,6 +245,8 @@ struct pmap { pml4_entry_t *pm_pml4; /* KVA of level 4 page table */ TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */ u_int pm_active; /* active on cpus */ + uint32_t pm_gen_count; /* generation count (pmap lock dropped) */ + u_int pm_retries; /* spare u_int here due to padding */ struct pmap_statistics pm_stats; /* pmap statistics */ vm_page_t pm_root; /* spare page table pages */ diff --git a/sys/amd64/include/vmparam.h b/sys/amd64/include/vmparam.h index 0b5004c..6dbe371 100644 --- a/sys/amd64/include/vmparam.h +++ b/sys/amd64/include/vmparam.h @@ -145,6 +145,10 @@ #define VM_LEVEL_0_ORDER 9 #endif +#ifdef SMP +#define PA_LOCK_COUNT 256 +#endif + /* * Virtual addresses of things. Derived from the page directory and * page table indexes from pmap.h for precision. diff --git a/sys/arm/arm/pmap.c b/sys/arm/arm/pmap.c index 366b43f..8fe6424 100644 --- a/sys/arm/arm/pmap.c +++ b/sys/arm/arm/pmap.c @@ -3740,13 +3740,14 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) struct l2_dtable *l2; pd_entry_t l1pd; pt_entry_t *ptep, pte; - vm_paddr_t pa; + vm_paddr_t pa, paddr; vm_page_t m = NULL; u_int l1idx; l1idx = L1_IDX(va); + paddr = 0; - vm_page_lock_queues(); PMAP_LOCK(pmap); +retry: l1pd = pmap->pm_l1->l1_kva[l1idx]; if (l1pte_section_p(l1pd)) { /* @@ -3758,6 +3759,8 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) pa = (l1pd & L1_SUP_FRAME) | (va & L1_SUP_OFFSET); else pa = (l1pd & L1_S_FRAME) | (va & L1_S_OFFSET); + if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr)) + goto retry; if (l1pd & L1_S_PROT_W || (prot & VM_PROT_WRITE) == 0) { m = PHYS_TO_VM_PAGE(pa); vm_page_hold(m); @@ -3774,7 +3777,6 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) if (l2 == NULL || (ptep = l2->l2_bucket[L2_BUCKET(l1idx)].l2b_kva) == NULL) { PMAP_UNLOCK(pmap); - vm_page_unlock_queues(); return (NULL); } @@ -3783,7 +3785,6 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) if (pte == 0) { PMAP_UNLOCK(pmap); - vm_page_unlock_queues(); return (NULL); } if (pte & L2_S_PROT_W || (prot & VM_PROT_WRITE) == 0) { @@ -3796,13 +3797,15 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) pa = (pte & L2_S_FRAME) | (va & L2_S_OFFSET); break; } + if (vm_page_pa_tryrelock(pmap, pa & PG_FRAME, &paddr)) + goto retry; m = PHYS_TO_VM_PAGE(pa); vm_page_hold(m); } } PMAP_UNLOCK(pmap); - vm_page_unlock_queues(); + PA_UNLOCK_COND(paddr); return (m); } diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index 8ee7bac..287c4c1 100644 --- a/sys/arm/include/pmap.h +++ b/sys/arm/include/pmap.h @@ -134,6 +134,8 @@ struct pmap { struct l1_ttable *pm_l1; struct l2_dtable *pm_l2[L2_SIZE]; pd_entry_t *pm_pdir; /* KVA of page directory */ + uint32_t pm_gen_count; /* generation count (pmap lock dropped) */ + u_int pm_retries; int pm_active; /* active on cpus */ struct pmap_statistics pm_stats; /* pmap statictics */ TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */ diff --git a/sys/dev/drm/via_dmablit.c b/sys/dev/drm/via_dmablit.c index ea449f1..3a66b26 100644 --- a/sys/dev/drm/via_dmablit.c +++ b/sys/dev/drm/via_dmablit.c @@ -248,10 +248,12 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) (vm_offset_t)xfer->mem_addr + IDX_TO_OFF(i), VM_PROT_RW); if (m == NULL) break; + vm_page_lock(m); vm_page_lock_queues(); vm_page_wire(m); vm_page_unhold(m); vm_page_unlock_queues(); + vm_page_unlock(m); vsg->pages[i] = m; } vsg->state = dr_via_pages_locked; diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index d8b9686..661fade 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -1346,14 +1346,19 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) pd_entry_t pde; pt_entry_t pte; vm_page_t m; + vm_paddr_t pa; + pa = 0; m = NULL; - vm_page_lock_queues(); PMAP_LOCK(pmap); +retry: pde = *pmap_pde(pmap, va); if (pde != 0) { if (pde & PG_PS) { if ((pde & PG_RW) || (prot & VM_PROT_WRITE) == 0) { + if (vm_page_pa_tryrelock(pmap, (pde & PG_PS_FRAME) | + (va & PDRMASK), &pa)) + goto retry; m = PHYS_TO_VM_PAGE((pde & PG_PS_FRAME) | (va & PDRMASK)); vm_page_hold(m); @@ -1363,13 +1368,15 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) pte = *pmap_pte_quick(pmap, va); if (pte != 0 && ((pte & PG_RW) || (prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pmap, pte & PG_FRAME, &pa)) + goto retry; m = PHYS_TO_VM_PAGE(pte & PG_FRAME); vm_page_hold(m); } sched_unpin(); } } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); PMAP_UNLOCK(pmap); return (m); } diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h index ae7d79d..f45a9df 100644 --- a/sys/i386/include/pmap.h +++ b/sys/i386/include/pmap.h @@ -420,11 +420,14 @@ struct pmap { u_int pm_active; /* active on cpus */ struct pmap_statistics pm_stats; /* pmap statistics */ LIST_ENTRY(pmap) pm_list; /* List of all pmaps */ + uint32_t pm_gen_count; /* generation count (pmap lock dropped) */ + u_int pm_retries; #ifdef PAE pdpt_entry_t *pm_pdpt; /* KVA of page director pointer table */ #endif vm_page_t pm_root; /* spare page table pages */ + }; typedef struct pmap *pmap_t; diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index 18619c3..ec96ef0 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -1219,14 +1219,19 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) pd_entry_t pde; pt_entry_t pte; vm_page_t m; + vm_paddr_t pa; + pa = 0; m = NULL; - vm_page_lock_queues(); PMAP_LOCK(pmap); +retry: pde = PT_GET(pmap_pde(pmap, va)); if (pde != 0) { if (pde & PG_PS) { if ((pde & PG_RW) || (prot & VM_PROT_WRITE) == 0) { + if (vm_page_pa_tryrelock(pmap, (pde & PG_PS_FRAME) | + (va & PDRMASK), &pa)) + goto retry; m = PHYS_TO_VM_PAGE((pde & PG_PS_FRAME) | (va & PDRMASK)); vm_page_hold(m); @@ -1238,13 +1243,15 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) PT_SET_MA(PADDR1, 0); if ((pte & PG_V) && ((pte & PG_RW) || (prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pmap, pte & PG_FRAME, &pa)) + goto retry; m = PHYS_TO_VM_PAGE(pte & PG_FRAME); vm_page_hold(m); } sched_unpin(); } } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); PMAP_UNLOCK(pmap); return (m); } diff --git a/sys/ia64/ia64/pmap.c b/sys/ia64/ia64/pmap.c index 91b2e07..7cc18c1 100644 --- a/sys/ia64/ia64/pmap.c +++ b/sys/ia64/ia64/pmap.c @@ -1028,18 +1028,22 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) struct ia64_lpte *pte; pmap_t oldpmap; vm_page_t m; + vm_paddr_t pa; + pa = 0; m = NULL; - vm_page_lock_queues(); PMAP_LOCK(pmap); oldpmap = pmap_switch(pmap); +retry: pte = pmap_find_vhpt(va); if (pte != NULL && pmap_present(pte) && (pmap_prot(pte) & prot) == prot) { m = PHYS_TO_VM_PAGE(pmap_ppn(pte)); + if (vm_page_pa_tryrelock(pmap, pmap_ppn(pte), &pa)) + goto retry; vm_page_hold(m); } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); pmap_switch(oldpmap); PMAP_UNLOCK(pmap); return (m); diff --git a/sys/ia64/include/pmap.h b/sys/ia64/include/pmap.h index 44079c8..ff059fd 100644 --- a/sys/ia64/include/pmap.h +++ b/sys/ia64/include/pmap.h @@ -77,6 +77,8 @@ struct pmap { TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */ u_int32_t pm_rid[5]; /* base RID for pmap */ struct pmap_statistics pm_stats; /* pmap statistics */ + uint32_t pm_gen_count; /* generation count (pmap lock dropped) */ + u_int pm_retries; }; typedef struct pmap *pmap_t; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index ed22519..bb92972 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -957,9 +957,9 @@ exec_map_first_page(imgp) return (EIO); } } - vm_page_lock_queues(); + vm_page_lock(ma[0]); vm_page_hold(ma[0]); - vm_page_unlock_queues(); + vm_page_unlock(ma[0]); vm_page_wakeup(ma[0]); VM_OBJECT_UNLOCK(object); @@ -979,9 +979,9 @@ exec_unmap_first_page(imgp) m = sf_buf_page(imgp->firstpage); sf_buf_free(imgp->firstpage); imgp->firstpage = NULL; - vm_page_lock_queues(); + vm_page_lock(m); vm_page_unhold(m); - vm_page_unlock_queues(); + vm_page_unlock(m); } } diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c index 5b7d565..ef1bc39 100644 --- a/sys/kern/subr_witness.c +++ b/sys/kern/subr_witness.c @@ -597,6 +597,15 @@ static struct witness_order_list_entry order_lists[] = { { "cdev", &lock_class_mtx_sleep }, { NULL, NULL }, /* + * VM + * + */ + { "vm object", &lock_class_mtx_sleep }, + { "page lock", &lock_class_mtx_sleep }, + { "vm page queue mutex", &lock_class_mtx_sleep }, + { "pmap", &lock_class_mtx_sleep }, + { NULL, NULL }, + /* * kqueue/VFS interaction */ { "kqueue", &lock_class_mtx_sleep }, diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index e098648..7130c26 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -773,10 +773,12 @@ pipe_build_write_buffer(wpipe, uio) */ race: if (vm_fault_quick((caddr_t)addr, VM_PROT_READ) < 0) { - vm_page_lock_queues(); - for (j = 0; j < i; j++) + + for (j = 0; j < i; j++) { + vm_page_lock(wpipe->pipe_map.ms[j]); vm_page_unhold(wpipe->pipe_map.ms[j]); - vm_page_unlock_queues(); + vm_page_unlock(wpipe->pipe_map.ms[j]); + } return (EFAULT); } wpipe->pipe_map.ms[i] = pmap_extract_and_hold(pmap, addr, @@ -816,11 +818,11 @@ pipe_destroy_write_buffer(wpipe) int i; PIPE_LOCK_ASSERT(wpipe, MA_OWNED); - vm_page_lock_queues(); for (i = 0; i < wpipe->pipe_map.npages; i++) { + vm_page_lock(wpipe->pipe_map.ms[i]); vm_page_unhold(wpipe->pipe_map.ms[i]); + vm_page_unlock(wpipe->pipe_map.ms[i]); } - vm_page_unlock_queues(); wpipe->pipe_map.npages = 0; } diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index f5671d9..d8cc4f0 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -328,9 +328,9 @@ proc_rwmem(struct proc *p, struct uio *uio) /* * Hold the page in memory. */ - vm_page_lock_queues(); + vm_page_lock(m); vm_page_hold(m); - vm_page_unlock_queues(); + vm_page_unlock(m); /* * We're done with tmap now. @@ -349,9 +349,9 @@ proc_rwmem(struct proc *p, struct uio *uio) /* * Release the page. */ - vm_page_lock_queues(); + vm_page_lock(m); vm_page_unhold(m); - vm_page_unlock_queues(); + vm_page_unlock(m); } while (error == 0 && uio->uio_resid > 0); diff --git a/sys/kern/uipc_cow.c b/sys/kern/uipc_cow.c index 52988dd..5c0dcd2 100644 --- a/sys/kern/uipc_cow.c +++ b/sys/kern/uipc_cow.c @@ -128,10 +128,12 @@ socow_setup(struct mbuf *m0, struct uio *uio) /* * set up COW */ + vm_page_lock(pp); vm_page_lock_queues(); if (vm_page_cowsetup(pp) != 0) { vm_page_unhold(pp); vm_page_unlock_queues(); + vm_page_unlock(pp); return (0); } @@ -141,7 +143,7 @@ socow_setup(struct mbuf *m0, struct uio *uio) vm_page_wire(pp); vm_page_unhold(pp); vm_page_unlock_queues(); - + vm_page_unlock(pp); /* * Allocate an sf buf */ diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 156b676..ea846a5 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -3860,12 +3860,12 @@ vmapbuf(struct buf *bp) retry: if (vm_fault_quick(addr >= bp->b_data ? addr : bp->b_data, prot) < 0) { - vm_page_lock_queues(); for (i = 0; i < pidx; ++i) { + vm_page_lock(bp->b_pages[i]); vm_page_unhold(bp->b_pages[i]); + vm_page_unlock(bp->b_pages[i]); bp->b_pages[i] = NULL; } - vm_page_unlock_queues(); return(-1); } m = pmap_extract_and_hold(pmap, (vm_offset_t)addr, prot); @@ -3896,11 +3896,12 @@ vunmapbuf(struct buf *bp) npages = bp->b_npages; pmap_qremove(trunc_page((vm_offset_t)bp->b_data), npages); - vm_page_lock_queues(); - for (pidx = 0; pidx < npages; pidx++) + for (pidx = 0; pidx < npages; pidx++) { + vm_page_lock(bp->b_pages[pidx]); vm_page_unhold(bp->b_pages[pidx]); - vm_page_unlock_queues(); - + vm_page_unlock(bp->b_pages[pidx]); + } + bp->b_data = bp->b_saveaddr; } diff --git a/sys/mips/include/pmap.h b/sys/mips/include/pmap.h index 80772d9..f4df6ca 100644 --- a/sys/mips/include/pmap.h +++ b/sys/mips/include/pmap.h @@ -88,6 +88,8 @@ struct pmap { pd_entry_t *pm_segtab; /* KVA of segment table */ TAILQ_HEAD(, pv_entry) pm_pvlist; /* list of mappings in * pmap */ + uint32_t pm_gen_count; /* generation count (pmap lock dropped) */ + u_int pm_retries; int pm_active; /* active on cpus */ struct { u_int32_t asid:ASID_BITS; /* TLB address space tag */ diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c index e7c3239..826177f 100644 --- a/sys/mips/mips/pmap.c +++ b/sys/mips/mips/pmap.c @@ -147,7 +147,6 @@ unsigned pmap_max_asid; /* max ASID supported by the system */ #define PMAP_ASID_RESERVED 0 - vm_offset_t kernel_vm_end; static struct tlb tlbstash[MAXCPU][MIPS_MAX_TLB_ENTRIES]; @@ -710,18 +709,22 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) { pt_entry_t pte; vm_page_t m; + vm_paddr_t pa; m = NULL; - vm_page_lock_queues(); + pa = 0; PMAP_LOCK(pmap); - +retry: pte = *pmap_pte(pmap, va); if (pte != 0 && pmap_pte_v(&pte) && ((pte & PTE_RW) || (prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pmap, mips_tlbpfn_to_paddr(pte), &pa)) + goto retry; + m = PHYS_TO_VM_PAGE(mips_tlbpfn_to_paddr(pte)); vm_page_hold(m); } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); PMAP_UNLOCK(pmap); return (m); } diff --git a/sys/net/bpf_zerocopy.c b/sys/net/bpf_zerocopy.c index a1dd923..3cf4b8d 100644 --- a/sys/net/bpf_zerocopy.c +++ b/sys/net/bpf_zerocopy.c @@ -168,10 +168,12 @@ zbuf_sfbuf_get(struct vm_map *map, vm_offset_t uaddr) VM_PROT_WRITE); if (pp == NULL) return (NULL); + vm_page_lock(pp); vm_page_lock_queues(); vm_page_wire(pp); vm_page_unhold(pp); vm_page_unlock_queues(); + vm_page_unlock(pp); sf = sf_buf_alloc(pp, SFB_NOWAIT); if (sf == NULL) { zbuf_page_free(pp); diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c index 24e7b4e..95936ed 100644 --- a/sys/powerpc/aim/mmu_oea.c +++ b/sys/powerpc/aim/mmu_oea.c @@ -1241,18 +1241,22 @@ moea_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot) { struct pvo_entry *pvo; vm_page_t m; - + vm_paddr_t pa; + m = NULL; - vm_page_lock_queues(); + pa = 0; PMAP_LOCK(pmap); +retry: pvo = moea_pvo_find_va(pmap, va & ~ADDR_POFF, NULL); if (pvo != NULL && (pvo->pvo_pte.pte.pte_hi & PTE_VALID) && ((pvo->pvo_pte.pte.pte_lo & PTE_PP) == PTE_RW || (prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pmap, pvo->pvo_pte.pte.pte_lo & PTE_RPGN, &pa)) + goto retry; m = PHYS_TO_VM_PAGE(pvo->pvo_pte.pte.pte_lo & PTE_RPGN); vm_page_hold(m); } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); PMAP_UNLOCK(pmap); return (m); } diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c index 2571587..0483b41 100644 --- a/sys/powerpc/aim/mmu_oea64.c +++ b/sys/powerpc/aim/mmu_oea64.c @@ -1374,18 +1374,23 @@ moea64_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot) { struct pvo_entry *pvo; vm_page_t m; + vm_paddr_t pa; m = NULL; - vm_page_lock_queues(); + pa = 0; PMAP_LOCK(pmap); +retry: pvo = moea64_pvo_find_va(pmap, va & ~ADDR_POFF, NULL); if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) && ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) == LPTE_RW || (prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pmap, + pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN, &pa)) + goto retry; m = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN); vm_page_hold(m); } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); PMAP_UNLOCK(pmap); return (m); } diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index 549eaaa..0b0fce4 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -2034,11 +2034,12 @@ mmu_booke_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, pte_t *pte; vm_page_t m; uint32_t pte_wbit; - + vm_paddr_t pa; + m = NULL; - vm_page_lock_queues(); + pa = 0; PMAP_LOCK(pmap); - +retry: pte = pte_find(mmu, pmap, va); if ((pte != NULL) && PTE_ISVALID(pte)) { if (pmap == kernel_pmap) @@ -2047,12 +2048,14 @@ mmu_booke_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, pte_wbit = PTE_UW; if ((pte->flags & pte_wbit) || ((prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pmap, PTE_PA(pte), &pa)) + goto retry; m = PHYS_TO_VM_PAGE(PTE_PA(pte)); vm_page_hold(m); } } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); PMAP_UNLOCK(pmap); return (m); } diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h index a23052e..a49bd6c 100644 --- a/sys/powerpc/include/pmap.h +++ b/sys/powerpc/include/pmap.h @@ -88,6 +88,8 @@ struct pmap { struct mtx pm_mtx; u_int pm_sr[16]; u_int pm_active; + uint32_t pm_gen_count; /* generation count (pmap lock dropped) */ + u_int pm_retries; u_int pm_context; struct pmap *pmap_phys; diff --git a/sys/sparc64/include/pmap.h b/sys/sparc64/include/pmap.h index 83c8190..388f751 100644 --- a/sys/sparc64/include/pmap.h +++ b/sys/sparc64/include/pmap.h @@ -62,6 +62,8 @@ struct pmap { struct tte *pm_tsb; vm_object_t pm_tsb_obj; u_int pm_active; + uint32_t pm_gen_count; /* generation count (pmap lock dropped) */ + u_int pm_retries; u_int pm_context[MAXCPU]; struct pmap_statistics pm_stats; }; diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index 22ae860..5d69c13 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -694,13 +694,17 @@ pmap_extract_and_hold(pmap_t pm, vm_offset_t va, vm_prot_t prot) { struct tte *tp; vm_page_t m; + vm_paddr_t pa; m = NULL; - vm_page_lock_queues(); + pa = 0; + PMAP_LOCK(pm); +retry: if (pm == kernel_pmap) { if (va >= VM_MIN_DIRECT_ADDRESS) { tp = NULL; m = PHYS_TO_VM_PAGE(TLB_DIRECT_TO_PHYS(va)); + (void)vm_page_pa_tryrelock(pm, TLB_DIRECT_TO_PHYS(va), &pa); vm_page_hold(m); } else { tp = tsb_kvtotte(va); @@ -708,17 +712,17 @@ pmap_extract_and_hold(pmap_t pm, vm_offset_t va, vm_prot_t prot) tp = NULL; } } else { - PMAP_LOCK(pm); tp = tsb_tte_lookup(pm, va); } if (tp != NULL && ((tp->tte_data & TD_SW) || (prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pm, TTE_GET_PA(tp), &pa)) + goto retry; m = PHYS_TO_VM_PAGE(TTE_GET_PA(tp)); vm_page_hold(m); } - vm_page_unlock_queues(); - if (pm != kernel_pmap) - PMAP_UNLOCK(pm); + PA_UNLOCK_COND(pa); + PMAP_UNLOCK(pm); return (m); } diff --git a/sys/sun4v/include/pmap.h b/sys/sun4v/include/pmap.h index 90ae4c4..6acebb4 100644 --- a/sys/sun4v/include/pmap.h +++ b/sys/sun4v/include/pmap.h @@ -75,6 +75,8 @@ struct pmap { struct tte_hash *pm_hash; TAILQ_HEAD(,pv_entry) pm_pvlist; /* list of mappings in pmap */ struct hv_tsb_info pm_tsb; + uint32_t pm_gen_count; /* generation count (pmap lock dropped) */ + u_int pm_retries; pmap_cpumask_t pm_active; /* mask of cpus currently using pmap */ pmap_cpumask_t pm_tlbactive; /* mask of cpus that have used this pmap */ struct pmap_statistics pm_stats; diff --git a/sys/sun4v/sun4v/pmap.c b/sys/sun4v/sun4v/pmap.c index cbd8106..0c84421 100644 --- a/sys/sun4v/sun4v/pmap.c +++ b/sys/sun4v/sun4v/pmap.c @@ -1275,17 +1275,21 @@ pmap_extract_and_hold(pmap_t pmap, vm_offset_t va, vm_prot_t prot) { tte_t tte_data; vm_page_t m; + vm_paddr_t pa; m = NULL; - vm_page_lock_queues(); + pa = 0; PMAP_LOCK(pmap); +retry: tte_data = tte_hash_lookup(pmap->pm_hash, va); if (tte_data != 0 && ((tte_data & VTD_SW_W) || (prot & VM_PROT_WRITE) == 0)) { + if (vm_page_pa_tryrelock(pmap, TTE_GET_PA(tte_data), &pa)) + goto retry; m = PHYS_TO_VM_PAGE(TTE_GET_PA(tte_data)); vm_page_hold(m); } - vm_page_unlock_queues(); + PA_UNLOCK_COND(pa); PMAP_UNLOCK(pmap); return (m); diff --git a/sys/sys/param.h b/sys/sys/param.h index 9f87ee2..11c15ab 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -58,7 +58,7 @@ * in the range 5 to 9. */ #undef __FreeBSD_version -#define __FreeBSD_version 900010 /* Master, propagated to newvers */ +#define __FreeBSD_version 900011 /* Master, propagated to newvers */ #ifndef LOCORE #include diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index 9002e77..996f740 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -251,12 +251,16 @@ dev_pager_getpages(object, m, count, reqpage) VM_OBJECT_LOCK(object); dev_pager_updatefake(page, paddr, memattr); if (count > 1) { - vm_page_lock_queues(); + for (i = 0; i < count; i++) { - if (i != reqpage) + if (i != reqpage) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } } - vm_page_unlock_queues(); } } else { /* @@ -266,10 +270,13 @@ dev_pager_getpages(object, m, count, reqpage) page = dev_pager_getfake(paddr, memattr); VM_OBJECT_LOCK(object); TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist, page, pageq); - vm_page_lock_queues(); - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } vm_page_insert(page, object, offset); m[reqpage] = page; } diff --git a/sys/vm/sg_pager.c b/sys/vm/sg_pager.c index a17fe82..845401a 100644 --- a/sys/vm/sg_pager.c +++ b/sys/vm/sg_pager.c @@ -198,10 +198,13 @@ sg_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage) TAILQ_INSERT_TAIL(&object->un_pager.sgp.sgp_pglist, page, pageq); /* Free the original pages and insert this fake page into the object. */ - vm_page_lock_queues(); - for (i = 0; i < count; i++) + for (i = 0; i < count; i++) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } vm_page_insert(page, object, offset); m[reqpage] = page; page->valid = VM_PAGE_BITS_ALL; diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c index f47719b..6017a52 100644 --- a/sys/vm/swap_pager.c +++ b/sys/vm/swap_pager.c @@ -1137,12 +1137,21 @@ swap_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage) if (0 < i || j < count) { int k; - vm_page_lock_queues(); - for (k = 0; k < i; ++k) + + for (k = 0; k < i; ++k) { + vm_page_lock(m[k]); + vm_page_lock_queues(); swp_pager_free_nrpage(m[k]); - for (k = j; k < count; ++k) + vm_page_unlock_queues(); + vm_page_unlock(m[k]); + } + for (k = j; k < count; ++k) { + vm_page_lock(m[k]); + vm_page_lock_queues(); swp_pager_free_nrpage(m[k]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[k]); + } } /* @@ -1497,7 +1506,7 @@ swp_pager_async_iodone(struct buf *bp) object = bp->b_pages[0]->object; VM_OBJECT_LOCK(object); } - vm_page_lock_queues(); + /* * cleanup pages. If an error occurs writing to swap, we are in * very serious trouble. If it happens to be a disk error, though, @@ -1509,6 +1518,8 @@ swp_pager_async_iodone(struct buf *bp) for (i = 0; i < bp->b_npages; ++i) { vm_page_t m = bp->b_pages[i]; + vm_page_lock(m); + vm_page_lock_queues(); m->oflags &= ~VPO_SWAPINPROG; if (bp->b_ioflags & BIO_ERROR) { @@ -1605,8 +1616,9 @@ swp_pager_async_iodone(struct buf *bp) if (vm_page_count_severe()) vm_page_try_to_cache(m); } + vm_page_unlock_queues(); + vm_page_unlock(m); } - vm_page_unlock_queues(); /* * adjust pip. NOTE: the original parent may still have its own @@ -1702,10 +1714,12 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex) m = vm_page_grab(object, pindex, VM_ALLOC_NORMAL|VM_ALLOC_RETRY); if (m->valid == VM_PAGE_BITS_ALL) { vm_object_pip_subtract(object, 1); + vm_page_lock(m); vm_page_lock_queues(); vm_page_activate(m); vm_page_dirty(m); vm_page_unlock_queues(); + vm_page_unlock(m); vm_page_wakeup(m); vm_pager_page_unswapped(m); return; @@ -1714,10 +1728,12 @@ swp_pager_force_pagein(vm_object_t object, vm_pindex_t pindex) if (swap_pager_getpages(object, &m, 1, 0) != VM_PAGER_OK) panic("swap_pager_force_pagein: read from swap failed");/*XXX*/ vm_object_pip_subtract(object, 1); + vm_page_lock(m); vm_page_lock_queues(); vm_page_dirty(m); vm_page_dontneed(m); vm_page_unlock_queues(); + vm_page_unlock(m); vm_page_wakeup(m); vm_pager_page_unswapped(m); } diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index a2d5633..00a8276 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -1022,10 +1022,12 @@ obj_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) while (pages != startpages) { pages--; p = TAILQ_LAST(&object->memq, pglist); + vm_page_lock(p); vm_page_lock_queues(); vm_page_unwire(p, 0); vm_page_free(p); vm_page_unlock_queues(); + vm_page_unlock(p); } retkva = 0; goto done; diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index 78d7e28..7220055 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -257,9 +257,11 @@ retry: i -= PAGE_SIZE; m = vm_page_lookup(object, OFF_TO_IDX(offset + i)); + vm_page_lock(m); vm_page_lock_queues(); vm_page_free(m); vm_page_unlock_queues(); + vm_page_unlock(m); } VM_OBJECT_UNLOCK(object); vm_map_delete(map, addr, addr + size); diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 058cbb0..de74915 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -137,9 +137,11 @@ release_page(struct faultstate *fs) { vm_page_wakeup(fs->m); + vm_page_lock(fs->m); vm_page_lock_queues(); vm_page_deactivate(fs->m); vm_page_unlock_queues(); + vm_page_unlock(fs->m); fs->m = NULL; } @@ -161,9 +163,11 @@ unlock_and_deallocate(struct faultstate *fs) VM_OBJECT_UNLOCK(fs->object); if (fs->object != fs->first_object) { VM_OBJECT_LOCK(fs->first_object); + vm_page_lock(fs->first_m); vm_page_lock_queues(); vm_page_free(fs->first_m); vm_page_unlock_queues(); + vm_page_unlock(fs->first_m); vm_object_pip_wakeup(fs->first_object); VM_OBJECT_UNLOCK(fs->first_object); fs->first_m = NULL; @@ -305,12 +309,14 @@ RetryFault:; * removes the page from the backing object, * which is not what we want. */ + vm_page_lock(fs.m); vm_page_lock_queues(); if ((fs.m->cow) && (fault_type & VM_PROT_WRITE) && (fs.object == fs.first_object)) { vm_page_cowfault(fs.m); vm_page_unlock_queues(); + vm_page_unlock(fs.m); unlock_and_deallocate(&fs); goto RetryFault; } @@ -333,12 +339,15 @@ RetryFault:; */ if ((fs.m->oflags & VPO_BUSY) || fs.m->busy) { vm_page_unlock_queues(); + vm_page_unlock(fs.m); VM_OBJECT_UNLOCK(fs.object); if (fs.object != fs.first_object) { VM_OBJECT_LOCK(fs.first_object); + vm_page_lock(fs.first_m); vm_page_lock_queues(); vm_page_free(fs.first_m); vm_page_unlock_queues(); + vm_page_unlock(fs.first_m); vm_object_pip_wakeup(fs.first_object); VM_OBJECT_UNLOCK(fs.first_object); fs.first_m = NULL; @@ -358,6 +367,7 @@ RetryFault:; } vm_pageq_remove(fs.m); vm_page_unlock_queues(); + vm_page_unlock(fs.m); /* * Mark page busy for other processes, and the @@ -481,17 +491,25 @@ readrest: continue; if (!are_queues_locked) { are_queues_locked = TRUE; + vm_page_lock(mt); + vm_page_lock_queues(); + } else { + vm_page_unlock_queues(); + vm_page_lock(mt); vm_page_lock_queues(); } if (mt->hold_count || - mt->wire_count) + mt->wire_count) { + vm_page_unlock(mt); continue; + } pmap_remove_all(mt); if (mt->dirty) { vm_page_deactivate(mt); } else { vm_page_cache(mt); } + vm_page_unlock(mt); } if (are_queues_locked) vm_page_unlock_queues(); @@ -623,17 +641,21 @@ vnode_locked: */ if (((fs.map != kernel_map) && (rv == VM_PAGER_ERROR)) || (rv == VM_PAGER_BAD)) { + vm_page_lock(fs.m); vm_page_lock_queues(); vm_page_free(fs.m); vm_page_unlock_queues(); + vm_page_unlock(fs.m); fs.m = NULL; unlock_and_deallocate(&fs); return ((rv == VM_PAGER_ERROR) ? KERN_FAILURE : KERN_PROTECTION_FAILURE); } if (fs.object != fs.first_object) { + vm_page_lock(fs.m); vm_page_lock_queues(); vm_page_free(fs.m); vm_page_unlock_queues(); + vm_page_unlock(fs.m); fs.m = NULL; /* * XXX - we cannot just fall out at this @@ -746,18 +768,24 @@ vnode_locked: * We don't chase down the shadow chain */ fs.object == fs.first_object->backing_object) { + vm_page_lock(fs.first_m); vm_page_lock_queues(); /* * get rid of the unnecessary page */ vm_page_free(fs.first_m); + vm_page_unlock_queues(); + vm_page_unlock(fs.first_m); /* * grab the page and put it into the * process'es object. The page is * automatically made dirty. */ + vm_page_lock(fs.m); + vm_page_lock_queues(); vm_page_rename(fs.m, fs.first_object, fs.first_pindex); vm_page_unlock_queues(); + vm_page_unlock(fs.m); vm_page_busy(fs.m); fs.first_m = fs.m; fs.m = NULL; @@ -770,10 +798,17 @@ vnode_locked: fs.first_m->valid = VM_PAGE_BITS_ALL; if (wired && (fault_flags & VM_FAULT_CHANGE_WIRING) == 0) { + vm_page_lock(fs.first_m); vm_page_lock_queues(); vm_page_wire(fs.first_m); + vm_page_unlock_queues(); + vm_page_unlock(fs.first_m); + + vm_page_lock(fs.m); + vm_page_lock_queues(); vm_page_unwire(fs.m, FALSE); vm_page_unlock_queues(); + vm_page_unlock(fs.m); } /* * We no longer need the old page or object. @@ -923,6 +958,7 @@ vnode_locked: if ((fault_flags & VM_FAULT_CHANGE_WIRING) == 0 && wired == 0) vm_fault_prefault(fs.map->pmap, vaddr, fs.entry); VM_OBJECT_LOCK(fs.object); + vm_page_lock(fs.m); vm_page_lock_queues(); /* @@ -938,6 +974,7 @@ vnode_locked: vm_page_activate(fs.m); } vm_page_unlock_queues(); + vm_page_unlock(fs.m); vm_page_wakeup(fs.m); /* @@ -1014,9 +1051,11 @@ vm_fault_prefault(pmap_t pmap, vm_offset_t addra, vm_map_entry_t entry) } if (m->valid == VM_PAGE_BITS_ALL && (m->flags & PG_FICTITIOUS) == 0) { + vm_page_lock(m); vm_page_lock_queues(); pmap_enter_quick(pmap, addr, m, entry->protection); vm_page_unlock_queues(); + vm_page_unlock(m); } VM_OBJECT_UNLOCK(lobject); } @@ -1092,9 +1131,11 @@ vm_fault_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, if (pa != 0) { pmap_change_wiring(pmap, va, FALSE); if (!fictitious) { + vm_page_lock(PHYS_TO_VM_PAGE(pa)); vm_page_lock_queues(); vm_page_unwire(PHYS_TO_VM_PAGE(pa), 1); vm_page_unlock_queues(); + vm_page_unlock(PHYS_TO_VM_PAGE(pa)); } } } @@ -1237,13 +1278,26 @@ vm_fault_copy_entry(vm_map_t dst_map, vm_map_t src_map, * Mark it no longer busy, and put it on the active list. */ VM_OBJECT_LOCK(dst_object); - vm_page_lock_queues(); + if (upgrade) { + vm_page_lock(src_m); + vm_page_lock_queues(); vm_page_unwire(src_m, 0); + vm_page_unlock_queues(); + vm_page_lock(src_m); + + vm_page_lock(dst_m); + vm_page_lock_queues(); vm_page_wire(dst_m); - } else + vm_page_unlock_queues(); + vm_page_lock(dst_m); + } else { + vm_page_lock(dst_m); + vm_page_lock_queues(); vm_page_activate(dst_m); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_lock(dst_m); + } vm_page_wakeup(dst_m); } VM_OBJECT_UNLOCK(dst_object); diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 4eeaa4d..288c5d7 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -257,16 +257,18 @@ vm_imgact_hold_page(vm_object_t object, vm_ooffset_t offset) if (m == NULL) goto out; if (rv != VM_PAGER_OK) { + vm_page_lock(m); vm_page_lock_queues(); vm_page_free(m); vm_page_unlock_queues(); + vm_page_unlock(m); m = NULL; goto out; } } - vm_page_lock_queues(); + vm_page_lock(m); vm_page_hold(m); - vm_page_unlock_queues(); + vm_page_unlock(m); vm_page_wakeup(m); out: VM_OBJECT_UNLOCK(object); @@ -300,9 +302,9 @@ vm_imgact_unmap_page(struct sf_buf *sf) m = sf_buf_page(sf); sf_buf_free(sf); sched_unpin(); - vm_page_lock_queues(); + vm_page_lock(m); vm_page_unhold(m); - vm_page_unlock_queues(); + vm_page_unlock(m); } void @@ -434,10 +436,12 @@ vm_thread_stack_dispose(vm_object_t ksobj, vm_offset_t ks, int pages) m = vm_page_lookup(ksobj, i); if (m == NULL) panic("vm_thread_dispose: kstack already missing?"); + vm_page_lock(m); vm_page_lock_queues(); vm_page_unwire(m, 0); vm_page_free(m); vm_page_unlock_queues(); + vm_page_unlock(m); } VM_OBJECT_UNLOCK(ksobj); vm_object_deallocate(ksobj); @@ -524,9 +528,11 @@ vm_thread_swapout(struct thread *td) if (m == NULL) panic("vm_thread_swapout: kstack already missing?"); vm_page_dirty(m); + vm_page_lock(m); vm_page_lock_queues(); vm_page_unwire(m, 0); vm_page_unlock_queues(); + vm_page_unlock(m); } VM_OBJECT_UNLOCK(ksobj); } diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index 739d289..ead6d0d 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -380,10 +380,12 @@ retry: i -= PAGE_SIZE; m = vm_page_lookup(kmem_object, OFF_TO_IDX(offset + i)); + vm_page_lock(m); vm_page_lock_queues(); vm_page_unwire(m, 0); vm_page_free(m); vm_page_unlock_queues(); + vm_page_unlock(m); } VM_OBJECT_UNLOCK(kmem_object); vm_map_delete(map, addr, addr + size); diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 88ed3d5..f9b3db3 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -866,6 +866,7 @@ RestartScan: */ if (m != NULL && m->valid != 0) { mincoreinfo = MINCORE_INCORE; + vm_page_lock(m); vm_page_lock_queues(); if (m->dirty || pmap_is_modified(m)) @@ -874,6 +875,7 @@ RestartScan: pmap_is_referenced(m)) mincoreinfo |= MINCORE_REFERENCED_OTHER; vm_page_unlock_queues(); + vm_page_unlock(m); } VM_OBJECT_UNLOCK(current->object.vm_object); } diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index c25ab77..47ef973 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -717,19 +717,21 @@ vm_object_terminate(vm_object_t object) * removes them from paging queues. Don't free wired pages, just * remove them from the object. */ - vm_page_lock_queues(); while ((p = TAILQ_FIRST(&object->memq)) != NULL) { KASSERT(!p->busy && (p->oflags & VPO_BUSY) == 0, ("vm_object_terminate: freeing busy page %p " "p->busy = %d, p->oflags %x\n", p, p->busy, p->oflags)); + vm_page_lock(p); + vm_page_lock_queues(); if (p->wire_count == 0) { vm_page_free(p); cnt.v_pfree++; } else { vm_page_remove(p); } + vm_page_unlock_queues(); + vm_page_unlock(p); } - vm_page_unlock_queues(); #if VM_NRESERVLEVEL > 0 if (__predict_false(!LIST_EMPTY(&object->rvq))) @@ -789,7 +791,6 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int tend = end; } - vm_page_lock_queues(); /* * If the caller is smart and only msync()s a range he knows is * dirty, we may be able to avoid an object scan. This results in @@ -818,8 +819,12 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int ++tscan; continue; } + vm_page_lock(p); + vm_page_lock_queues(); vm_page_test_dirty(p); if (p->dirty == 0) { + vm_page_unlock_queues(); + vm_page_unlock(p); if (--scanlimit == 0) break; ++tscan; @@ -830,6 +835,8 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int * this is a nosync page, we can't continue. */ if ((flags & OBJPC_NOSYNC) && (p->oflags & VPO_NOSYNC)) { + vm_page_unlock_queues(); + vm_page_unlock(p); if (--scanlimit == 0) break; ++tscan; @@ -842,6 +849,8 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int * page (i.e. had to sleep). */ tscan += vm_object_page_collect_flush(object, p, curgeneration, pagerflags); + vm_page_unlock_queues(); + vm_page_unlock(p); } /* @@ -871,8 +880,13 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int p->oflags |= VPO_CLEANCHK; if ((flags & OBJPC_NOSYNC) && (p->oflags & VPO_NOSYNC)) clearobjflags = 0; - else + else { + vm_page_lock(p); + vm_page_lock_queues(); pmap_remove_write(p); + vm_page_unlock_queues(); + vm_page_unlock(p); + } } if (clearobjflags && (tstart == 0) && (tend == object->size)) @@ -895,8 +909,12 @@ again: continue; } + vm_page_lock(p); + vm_page_lock_queues(); vm_page_test_dirty(p); if (p->dirty == 0) { + vm_page_unlock_queues(); + vm_page_unlock(p); p->oflags &= ~VPO_CLEANCHK; continue; } @@ -907,28 +925,37 @@ again: * not cleared in this case so we do not have to set them. */ if ((flags & OBJPC_NOSYNC) && (p->oflags & VPO_NOSYNC)) { + vm_page_unlock_queues(); + vm_page_unlock(p); p->oflags &= ~VPO_CLEANCHK; continue; } n = vm_object_page_collect_flush(object, p, curgeneration, pagerflags); - if (n == 0) + if (n == 0) { + vm_page_unlock_queues(); + vm_page_unlock(p); goto rescan; + } - if (object->generation != curgeneration) + if (object->generation != curgeneration) { + vm_page_unlock_queues(); + vm_page_unlock(p); goto rescan; + } /* * Try to optimize the next page. If we can't we pick up * our (random) scan where we left off. */ if (msync_flush_flags & MSYNC_FLUSH_SOFTSEQ) { + vm_page_unlock_queues(); + vm_page_unlock(p); if ((p = vm_page_lookup(object, pi + n)) != NULL) goto again; } } - vm_page_unlock_queues(); #if 0 VOP_FSYNC(vp, (pagerflags & VM_PAGER_PUT_SYNC)?MNT_WAIT:0, curproc); #endif @@ -951,8 +978,10 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, vm_page_t ma[vm_pageout_page_count]; mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(p, MA_OWNED); pi = p->pindex; while (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) { + vm_page_lock(p); vm_page_lock_queues(); if (object->generation != curgeneration) { return(0); @@ -968,11 +997,16 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, (tp->oflags & VPO_CLEANCHK) == 0) || (tp->busy != 0)) break; + vm_page_unlock_queues(); + vm_page_lock(tp); + vm_page_lock_queues(); vm_page_test_dirty(tp); if (tp->dirty == 0) { + vm_page_unlock(tp); tp->oflags &= ~VPO_CLEANCHK; break; } + vm_page_unlock(tp); maf[ i - 1 ] = tp; maxf++; continue; @@ -992,11 +1026,16 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, (tp->oflags & VPO_CLEANCHK) == 0) || (tp->busy != 0)) break; + vm_page_unlock_queues(); + vm_page_lock(tp); + vm_page_lock_queues(); vm_page_test_dirty(tp); if (tp->dirty == 0) { + vm_page_unlock(tp); tp->oflags &= ~VPO_CLEANCHK; break; } + vm_page_unlock(tp); mab[ i - 1 ] = tp; maxb++; continue; @@ -1022,7 +1061,11 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, vm_pageout_flush(ma, runlen, pagerflags); for (i = 0; i < runlen; i++) { if (ma[i]->dirty) { + vm_page_unlock_queues(); + vm_page_lock(ma[i]); + vm_page_lock_queues(); pmap_remove_write(ma[i]); + vm_page_unlock(ma[i]); ma[i]->oflags |= VPO_CLEANCHK; /* @@ -1195,9 +1238,11 @@ shadowlookup: /* * If the page is not in a normal state, skip it. */ + vm_page_lock(m); vm_page_lock_queues(); if (m->hold_count != 0 || m->wire_count != 0) { vm_page_unlock_queues(); + vm_page_unlock(m); goto unlock_tobject; } if ((m->oflags & VPO_BUSY) || m->busy) { @@ -1209,6 +1254,7 @@ shadowlookup: */ vm_page_flag_set(m, PG_REFERENCED); vm_page_unlock_queues(); + vm_page_unlock(m); if (object != tobject) VM_OBJECT_UNLOCK(object); m->oflags |= VPO_WANTED; @@ -1243,6 +1289,7 @@ shadowlookup: vm_page_dontneed(m); } vm_page_unlock_queues(); + vm_page_unlock(m); if (advise == MADV_FREE && tobject->type == OBJT_SWAP) swap_pager_freespace(tobject, tpindex, 1); unlock_tobject: @@ -1405,7 +1452,6 @@ retry: m = TAILQ_NEXT(m, listq); } } - vm_page_lock_queues(); for (; m != NULL && (idx = m->pindex - offidxstart) < size; m = m_next) { m_next = TAILQ_NEXT(m, listq); @@ -1425,11 +1471,14 @@ retry: VM_OBJECT_LOCK(new_object); goto retry; } + vm_page_lock(m); + vm_page_lock_queues(); vm_page_rename(m, new_object, idx); + vm_page_unlock_queues(); + vm_page_unlock(m); /* page automatically made dirty by rename and cache handled */ vm_page_busy(m); } - vm_page_unlock_queues(); if (orig_object->type == OBJT_SWAP) { /* * swap_pager_copy() can sleep, in which case the orig_object's @@ -1597,6 +1646,7 @@ vm_object_backing_scan(vm_object_t object, int op) * Page is out of the parent object's range, we * can simply destroy it. */ + vm_page_lock(p); vm_page_lock_queues(); KASSERT(!pmap_page_is_mapped(p), ("freeing mapped page %p", p)); @@ -1605,6 +1655,7 @@ vm_object_backing_scan(vm_object_t object, int op) else vm_page_remove(p); vm_page_unlock_queues(); + vm_page_unlock(p); p = next; continue; } @@ -1621,6 +1672,7 @@ vm_object_backing_scan(vm_object_t object, int op) * * Leave the parent's page alone */ + vm_page_lock(p); vm_page_lock_queues(); KASSERT(!pmap_page_is_mapped(p), ("freeing mapped page %p", p)); @@ -1629,6 +1681,7 @@ vm_object_backing_scan(vm_object_t object, int op) else vm_page_remove(p); vm_page_unlock_queues(); + vm_page_unlock(p); p = next; continue; } @@ -1648,9 +1701,11 @@ vm_object_backing_scan(vm_object_t object, int op) * If the page was mapped to a process, it can remain * mapped through the rename. */ + vm_page_lock(p); vm_page_lock_queues(); vm_page_rename(p, object, new_pindex); vm_page_unlock_queues(); + vm_page_unlock(p); /* page automatically made dirty by rename */ } p = next; @@ -1915,7 +1970,7 @@ again: p = TAILQ_NEXT(p, listq); } } - vm_page_lock_queues(); + /* * Assert: the variable p is either (1) the page with the * least pindex greater than or equal to the parameter pindex @@ -1934,6 +1989,8 @@ again: * cannot be freed. They can, however, be invalidated * if "clean_only" is FALSE. */ + vm_page_lock(p); + vm_page_lock_queues(); if ((wirings = p->wire_count) != 0 && (wirings = pmap_page_wired_mappings(p)) != p->wire_count) { /* Fictitious pages do not have managed mappings. */ @@ -1945,6 +2002,8 @@ again: p->valid = 0; vm_page_undirty(p); } + vm_page_unlock_queues(); + vm_page_unlock(p); continue; } if (vm_page_sleep_if_busy(p, TRUE, "vmopar")) @@ -1953,16 +2012,20 @@ again: ("vm_object_page_remove: page %p is fictitious", p)); if (clean_only && p->valid) { pmap_remove_write(p); - if (p->dirty) + if (p->dirty) { + vm_page_unlock_queues(); + vm_page_unlock(p); continue; + } } pmap_remove_all(p); /* Account for removal of managed, wired mappings. */ if (wirings != 0) p->wire_count -= wirings; vm_page_free(p); + vm_page_unlock_queues(); + vm_page_unlock(p); } - vm_page_unlock_queues(); vm_object_pip_wakeup(object); skipmemq: if (__predict_false(object->cache != NULL)) @@ -1997,9 +2060,11 @@ vm_object_populate(vm_object_t object, vm_pindex_t start, vm_pindex_t end) if (m == NULL) break; if (rv != VM_PAGER_OK) { + vm_page_lock(m); vm_page_lock_queues(); vm_page_free(m); vm_page_unlock_queues(); + vm_page_unlock(m); break; } } diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 7c149c9..4c0d385 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -129,6 +130,24 @@ __FBSDID("$FreeBSD$"); #include +#if defined(__amd64__) || defined (__i386__) +extern struct sysctl_oid_list sysctl__vm_pmap_children; +#else +SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters"); +#endif + +static uint64_t pmap_tryrelock_calls; +SYSCTL_QUAD(_vm_pmap, OID_AUTO, tryrelock_calls, CTLFLAG_RD, + &pmap_tryrelock_calls, 0, "Number of tryrelock calls"); + +static int pmap_tryrelock_restart; +SYSCTL_INT(_vm_pmap, OID_AUTO, tryrelock_restart, CTLFLAG_RD, + &pmap_tryrelock_restart, 0, "Number of tryrelock restarts"); + +static int pmap_tryrelock_race; +SYSCTL_INT(_vm_pmap, OID_AUTO, tryrelock_race, CTLFLAG_RD, + &pmap_tryrelock_race, 0, "Number of tryrelock pmap race cases"); + /* * Associated with page of user-allocatable memory is a * page structure. @@ -138,6 +157,8 @@ struct vpgqueues vm_page_queues[PQ_COUNT]; struct vpglocks vm_page_queue_lock; struct vpglocks vm_page_queue_free_lock; +struct vpglocks pa_lock[PA_LOCK_COUNT] __aligned(CACHE_LINE_SIZE); + vm_page_t vm_page_array = 0; int vm_page_array_size = 0; long first_page = 0; @@ -158,6 +179,43 @@ CTASSERT(sizeof(u_long) >= 8); #endif /* + * Try to acquire a physical address lock while a pmap is locked. If we + * fail to trylock we unlock and lock the pmap directly and cache the + * locked pa in *locked. The caller should then restart their loop in case + * the virtual to physical mapping has changed. + */ +int +vm_page_pa_tryrelock(pmap_t pmap, vm_paddr_t pa, vm_paddr_t *locked) +{ + vm_paddr_t lockpa; + uint32_t gen_count; + + gen_count = pmap->pm_gen_count; + atomic_add_long((volatile long *)&pmap_tryrelock_calls, 1); + lockpa = *locked; + *locked = pa; + if (lockpa) { + PA_LOCK_ASSERT(lockpa, MA_OWNED); + if (PA_LOCKPTR(pa) == PA_LOCKPTR(lockpa)) + return (0); + PA_UNLOCK(lockpa); + } + if (PA_TRYLOCK(pa)) + return (0); + PMAP_UNLOCK(pmap); + atomic_add_int((volatile int *)&pmap_tryrelock_restart, 1); + PA_LOCK(pa); + PMAP_LOCK(pmap); + + if (pmap->pm_gen_count != gen_count + 1) { + pmap->pm_retries++; + atomic_add_int((volatile int *)&pmap_tryrelock_race, 1); + return (EAGAIN); + } + return (0); +} + +/* * vm_set_page_size: * * Sets the page size, perhaps based upon the memory @@ -271,6 +329,11 @@ vm_page_startup(vm_offset_t vaddr) mtx_init(&vm_page_queue_free_mtx, "vm page queue free mutex", NULL, MTX_DEF); + /* Setup page locks. */ + for (i = 0; i < PA_LOCK_COUNT; i++) + mtx_init(&pa_lock[i].data, "page lock", NULL, + MTX_DEF | MTX_RECURSE | MTX_DUPOK); + /* * Initialize the queue headers for the hold queue, the active queue, * and the inactive queue. @@ -489,7 +552,7 @@ void vm_page_hold(vm_page_t mem) { - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(mem, MA_OWNED); mem->hold_count++; } @@ -497,7 +560,7 @@ void vm_page_unhold(vm_page_t mem) { - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(mem, MA_OWNED); --mem->hold_count; KASSERT(mem->hold_count >= 0, ("vm_page_unhold: hold count < 0!!!")); if (mem->hold_count == 0 && VM_PAGE_INQUEUE2(mem, PQ_HOLD)) @@ -542,10 +605,13 @@ vm_page_sleep(vm_page_t m, const char *msg) { VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED); + if (!mtx_owned(vm_page_lockptr(m))) + vm_page_lock(m); if (!mtx_owned(&vm_page_queue_mtx)) vm_page_lock_queues(); vm_page_flag_set(m, PG_REFERENCED); vm_page_unlock_queues(); + vm_page_unlock(m); /* * It's possible that while we sleep, the page will get @@ -1425,6 +1491,7 @@ vm_page_free_toq(vm_page_t m) panic("vm_page_free: freeing wired page"); } if (m->hold_count != 0) { + vm_page_lock_assert(m, MA_OWNED); m->flags &= ~PG_ZERO; vm_page_enqueue(PQ_HOLD, m); } else { diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 662af98..35a81f8 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -177,9 +177,35 @@ struct vpglocks { } __aligned(CACHE_LINE_SIZE); extern struct vpglocks vm_page_queue_free_lock; +extern struct vpglocks pa_lock[]; -#define vm_page_queue_free_mtx vm_page_queue_free_lock.data +#if defined(__arm__) +#define PDRSHIFT PDR_SHIFT +#elif !defined(PDRSHIFT) +#define PDRSHIFT 21 +#endif +#define pa_index(pa) ((pa) >> PDRSHIFT) +#define PA_LOCKPTR(pa) &pa_lock[pa_index((pa)) % PA_LOCK_COUNT].data +#define PA_LOCKOBJPTR(pa) ((struct lock_object *)PA_LOCKPTR((pa))) +#define PA_LOCK(pa) mtx_lock(PA_LOCKPTR(pa)) +#define PA_TRYLOCK(pa) mtx_trylock(PA_LOCKPTR(pa)) +#define PA_UNLOCK(pa) mtx_unlock(PA_LOCKPTR(pa)) +#define PA_UNLOCK_COND(pa) \ + do { \ + if (pa) \ + PA_UNLOCK(pa); \ + } while (0) + +#define PA_LOCK_ASSERT(pa, a) mtx_assert(PA_LOCKPTR(pa), (a)) + +#define vm_page_lockptr(m) (PA_LOCKPTR(VM_PAGE_TO_PHYS((m)))) +#define vm_page_lock(m) mtx_lock(vm_page_lockptr((m))) +#define vm_page_unlock(m) mtx_unlock(vm_page_lockptr((m))) +#define vm_page_trylock(m) mtx_trylock(vm_page_lockptr((m))) +#define vm_page_lock_assert(m, a) mtx_assert(vm_page_lockptr((m)), (a)) + +#define vm_page_queue_free_mtx vm_page_queue_free_lock.data /* * These are the flags defined for vm_page. * @@ -324,6 +350,7 @@ void vm_page_dontneed(vm_page_t); void vm_page_deactivate (vm_page_t); void vm_page_insert (vm_page_t, vm_object_t, vm_pindex_t); vm_page_t vm_page_lookup (vm_object_t, vm_pindex_t); +int vm_page_pa_tryrelock(pmap_t, vm_paddr_t, vm_paddr_t *); void vm_page_remove (vm_page_t); void vm_page_rename (vm_page_t, vm_object_t, vm_pindex_t); void vm_page_requeue(vm_page_t m); diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 258da8b..95517de 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -252,7 +252,9 @@ vm_pageout_fallback_object_lock(vm_page_t m, vm_page_t *next) TAILQ_INSERT_AFTER(&vm_page_queues[queue].pl, m, &marker, pageq); vm_page_unlock_queues(); + vm_page_unlock(m); VM_OBJECT_LOCK(object); + vm_page_lock(m); vm_page_lock_queues(); /* Page queue might have changed. */ @@ -275,8 +277,7 @@ vm_pageout_fallback_object_lock(vm_page_t m, vm_page_t *next) * late and we cannot do anything that will mess with the page. */ static int -vm_pageout_clean(m) - vm_page_t m; +vm_pageout_clean(vm_page_t m) { vm_object_t object; vm_page_t mc[2*vm_pageout_page_count]; @@ -284,7 +285,8 @@ vm_pageout_clean(m) int ib, is, page_base; vm_pindex_t pindex = m->pindex; - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_NOTOWNED); + vm_page_lock(m); VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED); /* @@ -301,6 +303,7 @@ vm_pageout_clean(m) */ if ((m->hold_count != 0) || ((m->busy != 0) || (m->oflags & VPO_BUSY))) { + vm_page_unlock(m); return 0; } @@ -347,13 +350,19 @@ more: ib = 0; break; } + vm_page_lock(p); + vm_page_lock_queues(); vm_page_test_dirty(p); if (p->dirty == 0 || p->queue != PQ_INACTIVE || p->hold_count != 0) { /* may be undergoing I/O */ + vm_page_unlock(p); + vm_page_unlock_queues(); ib = 0; break; } + vm_page_unlock_queues(); + vm_page_unlock(p); mc[--page_base] = p; ++pageout_count; ++ib; @@ -374,12 +383,18 @@ more: if ((p->oflags & VPO_BUSY) || p->busy) { break; } + vm_page_lock(p); + vm_page_lock_queues(); vm_page_test_dirty(p); if (p->dirty == 0 || p->queue != PQ_INACTIVE || p->hold_count != 0) { /* may be undergoing I/O */ + vm_page_unlock_queues(); + vm_page_unlock(p); break; } + vm_page_unlock_queues(); + vm_page_unlock(p); mc[page_base + pageout_count] = p; ++pageout_count; ++is; @@ -393,6 +408,7 @@ more: if (ib && pageout_count < vm_pageout_page_count) goto more; + vm_page_unlock(m); /* * we allow reads during pageouts... */ @@ -416,7 +432,6 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags) int numpagedout = 0; int i; - mtx_assert(&vm_page_queue_mtx, MA_OWNED); VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); /* * Initiate I/O. Bump the vm_page_t->busy counter and @@ -433,17 +448,21 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags) ("vm_pageout_flush: partially invalid page %p index %d/%d", mc[i], i, count)); vm_page_io_start(mc[i]); + vm_page_lock(mc[i]); + vm_page_lock_queues(); pmap_remove_write(mc[i]); + vm_page_unlock(mc[i]); + vm_page_unlock_queues(); } - vm_page_unlock_queues(); vm_object_pip_add(object, count); vm_pager_put_pages(object, mc, count, flags, pageout_status); - vm_page_lock_queues(); for (i = 0; i < count; i++) { vm_page_t mt = mc[i]; + vm_page_lock(mt); + vm_page_lock_queues(); KASSERT(pageout_status[i] == VM_PAGER_PEND || (mt->flags & PG_WRITEABLE) == 0, ("vm_pageout_flush: page %p is not write protected", mt)); @@ -485,6 +504,8 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags) if (vm_page_count_severe()) vm_page_try_to_cache(mt); } + vm_page_unlock_queues(); + vm_page_unlock(mt); } return numpagedout; } @@ -527,10 +548,12 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired) * scan the objects entire memory queue */ p = TAILQ_FIRST(&object->memq); - vm_page_lock_queues(); while (p != NULL) { + vm_page_lock(p); + vm_page_lock_queues(); if (pmap_resident_count(pmap) <= desired) { vm_page_unlock_queues(); + vm_page_unlock(p); goto unlock_return; } next = TAILQ_NEXT(p, listq); @@ -540,6 +563,8 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired) p->busy != 0 || (p->oflags & VPO_BUSY) || !pmap_page_exists_quick(pmap, p)) { + vm_page_unlock_queues(); + vm_page_unlock(p); p = next; continue; } @@ -573,9 +598,10 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired) } else if (p->queue == PQ_INACTIVE) { pmap_remove_all(p); } + vm_page_unlock_queues(); + vm_page_unlock(p); p = next; } - vm_page_unlock_queues(); if ((backing_object = object->backing_object) == NULL) goto unlock_return; VM_OBJECT_LOCK(backing_object); @@ -742,7 +768,6 @@ rescan0: } next = TAILQ_NEXT(m, pageq); - object = m->object; /* * skip marker pages @@ -758,18 +783,26 @@ rescan0: addl_page_shortage++; continue; } + + if (!vm_page_trylock(m) || (object = m->object) == NULL) { + addl_page_shortage++; + continue; + } + /* * Don't mess with busy pages, keep in the front of the * queue, most likely are being paged out. */ if (!VM_OBJECT_TRYLOCK(object) && (!vm_pageout_fallback_object_lock(m, &next) || - m->hold_count != 0)) { + m->hold_count != 0)) { VM_OBJECT_UNLOCK(object); + vm_page_unlock(m); addl_page_shortage++; continue; } if (m->busy || (m->oflags & VPO_BUSY)) { + vm_page_unlock(m); VM_OBJECT_UNLOCK(object); addl_page_shortage++; continue; @@ -798,6 +831,7 @@ rescan0: vm_page_activate(m); VM_OBJECT_UNLOCK(object); m->act_count += (actcount + ACT_ADVANCE); + vm_page_unlock(m); continue; } @@ -813,6 +847,7 @@ rescan0: vm_page_activate(m); VM_OBJECT_UNLOCK(object); m->act_count += (actcount + ACT_ADVANCE + 1); + vm_page_unlock(m); continue; } @@ -898,6 +933,7 @@ rescan0: * Those objects are in a "rundown" state. */ if (!swap_pageouts_ok || (object->flags & OBJ_DEAD)) { + vm_page_unlock(m); VM_OBJECT_UNLOCK(object); vm_page_requeue(m); continue; @@ -937,6 +973,8 @@ rescan0: * of time. */ if (object->type == OBJT_VNODE) { + vm_page_unlock_queues(); + vm_page_unlock(m); vp = object->handle; if (vp->v_type == VREG && vn_start_write(vp, &mp, V_NOWAIT) != 0) { @@ -944,11 +982,11 @@ rescan0: ++pageout_lock_miss; if (object->flags & OBJ_MIGHTBEDIRTY) vnodes_skipped++; + vm_page_lock_queues(); goto unlock_and_continue; } KASSERT(mp != NULL, ("vp %p with NULL v_mount", vp)); - vm_page_unlock_queues(); vm_object_reference_locked(object); VM_OBJECT_UNLOCK(object); vfslocked = VFS_LOCK_GIANT(vp->v_mount); @@ -963,6 +1001,7 @@ rescan0: goto unlock_and_continue; } VM_OBJECT_LOCK(object); + vm_page_lock(m); vm_page_lock_queues(); /* * The page might have been moved to another @@ -973,6 +1012,7 @@ rescan0: if (VM_PAGE_GETQUEUE(m) != PQ_INACTIVE || m->object != object || TAILQ_NEXT(m, pageq) != &marker) { + vm_page_unlock(m); if (object->flags & OBJ_MIGHTBEDIRTY) vnodes_skipped++; goto unlock_and_continue; @@ -985,6 +1025,7 @@ rescan0: * statistics are more correct if we don't. */ if (m->busy || (m->oflags & VPO_BUSY)) { + vm_page_unlock(m); goto unlock_and_continue; } @@ -993,12 +1034,14 @@ rescan0: * be undergoing I/O, so skip it */ if (m->hold_count) { + vm_page_unlock(m); vm_page_requeue(m); if (object->flags & OBJ_MIGHTBEDIRTY) vnodes_skipped++; goto unlock_and_continue; } } + vm_page_unlock(m); /* * If a page is dirty, then it is either being washed @@ -1010,11 +1053,14 @@ rescan0: * the (future) cleaned page. Otherwise we could wind * up laundering or cleaning too many pages. */ + vm_page_unlock_queues(); if (vm_pageout_clean(m) != 0) { --page_shortage; --maxlaunder; } + vm_page_lock_queues(); unlock_and_continue: + vm_page_lock_assert(m, MA_NOTOWNED); VM_OBJECT_UNLOCK(object); if (mp != NULL) { vm_page_unlock_queues(); @@ -1028,8 +1074,10 @@ unlock_and_continue: next = TAILQ_NEXT(&marker, pageq); TAILQ_REMOVE(&vm_page_queues[PQ_INACTIVE].pl, &marker, pageq); + vm_page_lock_assert(m, MA_NOTOWNED); continue; } + vm_page_unlock(m); VM_OBJECT_UNLOCK(object); } @@ -1048,6 +1096,7 @@ unlock_and_continue: */ pcount = cnt.v_active_count; m = TAILQ_FIRST(&vm_page_queues[PQ_ACTIVE].pl); + mtx_assert(&vm_page_queue_mtx, MA_OWNED); while ((m != NULL) && (pcount-- > 0) && (page_shortage > 0)) { @@ -1060,9 +1109,14 @@ unlock_and_continue: m = next; continue; } + if (!vm_page_trylock(m) || (object = m->object) == NULL) { + m = next; + continue; + } if (!VM_OBJECT_TRYLOCK(object) && !vm_pageout_fallback_object_lock(m, &next)) { VM_OBJECT_UNLOCK(object); + vm_page_unlock(m); m = next; continue; } @@ -1073,6 +1127,7 @@ unlock_and_continue: if ((m->busy != 0) || (m->oflags & VPO_BUSY) || (m->hold_count != 0)) { + vm_page_unlock(m); VM_OBJECT_UNLOCK(object); vm_page_requeue(m); m = next; @@ -1132,6 +1187,7 @@ unlock_and_continue: vm_page_requeue(m); } } + vm_page_unlock(m); VM_OBJECT_UNLOCK(object); m = next; } @@ -1317,9 +1373,15 @@ vm_pageout_page_stats() m = next; continue; } + vm_page_lock_assert(m, MA_NOTOWNED); + if (vm_page_trylock(m) == 0 || (object = m->object) == NULL) { + m = next; + continue; + } if (!VM_OBJECT_TRYLOCK(object) && !vm_pageout_fallback_object_lock(m, &next)) { VM_OBJECT_UNLOCK(object); + vm_page_unlock(m); m = next; continue; } @@ -1330,6 +1392,7 @@ vm_pageout_page_stats() if ((m->busy != 0) || (m->oflags & VPO_BUSY) || (m->hold_count != 0)) { + vm_page_unlock(m); VM_OBJECT_UNLOCK(object); vm_page_requeue(m); m = next; @@ -1366,6 +1429,7 @@ vm_pageout_page_stats() vm_page_requeue(m); } } + vm_page_unlock(m); VM_OBJECT_UNLOCK(object); m = next; } diff --git a/sys/vm/vm_param.h b/sys/vm/vm_param.h index 2ff2603..c404989 100644 --- a/sys/vm/vm_param.h +++ b/sys/vm/vm_param.h @@ -126,6 +126,14 @@ struct xswdev { #define KERN_NOT_RECEIVER 7 #define KERN_NO_ACCESS 8 +#ifndef PA_LOCK_COUNT +#ifdef SMP +#define PA_LOCK_COUNT 32 +#else +#define PA_LOCK_COUNT 1 +#endif /* !SMP */ +#endif /* !PA_LOCK_COUNT */ + #ifndef ASSEMBLER #ifdef _KERNEL #define num_pages(x) \ diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c index aedc794..eb21c60 100644 --- a/sys/vm/vnode_pager.c +++ b/sys/vm/vnode_pager.c @@ -429,9 +429,11 @@ vnode_pager_setsize(vp, nsize) * bits. This would prevent bogus_page * replacement from working properly. */ + vm_page_lock(m); vm_page_lock_queues(); vm_page_clear_dirty(m, base, PAGE_SIZE - base); vm_page_unlock_queues(); + vm_page_unlock(m); } else if ((nsize & PAGE_MASK) && __predict_false(object->cache != NULL)) { vm_page_cache_free(object, OFF_TO_IDX(nsize), @@ -719,11 +721,15 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) error = VOP_BMAP(vp, foff / bsize, &bo, &reqblock, NULL, NULL); if (error == EOPNOTSUPP) { VM_OBJECT_LOCK(object); - vm_page_lock_queues(); + for (i = 0; i < count; i++) - if (i != reqpage) + if (i != reqpage) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } PCPU_INC(cnt.v_vnodein); PCPU_INC(cnt.v_vnodepgsin); error = vnode_pager_input_old(object, m[reqpage]); @@ -731,11 +737,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) return (error); } else if (error != 0) { VM_OBJECT_LOCK(object); - vm_page_lock_queues(); for (i = 0; i < count; i++) - if (i != reqpage) + if (i != reqpage) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } VM_OBJECT_UNLOCK(object); return (VM_PAGER_ERROR); @@ -747,11 +756,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) } else if ((PAGE_SIZE / bsize) > 1 && (vp->v_mount->mnt_stat.f_type != nfs_mount_type)) { VM_OBJECT_LOCK(object); - vm_page_lock_queues(); for (i = 0; i < count; i++) - if (i != reqpage) + if (i != reqpage) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } VM_OBJECT_UNLOCK(object); PCPU_INC(cnt.v_vnodein); PCPU_INC(cnt.v_vnodepgsin); @@ -765,11 +777,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) */ VM_OBJECT_LOCK(object); if (m[reqpage]->valid == VM_PAGE_BITS_ALL) { - vm_page_lock_queues(); for (i = 0; i < count; i++) - if (i != reqpage) + if (i != reqpage) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } VM_OBJECT_UNLOCK(object); return VM_PAGER_OK; } else if (reqblock == -1) { @@ -777,11 +792,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) KASSERT(m[reqpage]->dirty == 0, ("vnode_pager_generic_getpages: page %p is dirty", m)); m[reqpage]->valid = VM_PAGE_BITS_ALL; - vm_page_lock_queues(); for (i = 0; i < count; i++) - if (i != reqpage) + if (i != reqpage) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } VM_OBJECT_UNLOCK(object); return (VM_PAGER_OK); } @@ -800,11 +818,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) if (vnode_pager_addr(vp, IDX_TO_OFF(m[i]->pindex), &firstaddr, &runpg) != 0) { VM_OBJECT_LOCK(object); - vm_page_lock_queues(); for (; i < count; i++) - if (i != reqpage) + if (i != reqpage) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } VM_OBJECT_UNLOCK(object); return (VM_PAGER_ERROR); } @@ -818,9 +839,11 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) (object->un_pager.vnp.vnp_size >> 32), (uintmax_t)object->un_pager.vnp.vnp_size); } + vm_page_lock(m[i]); vm_page_lock_queues(); vm_page_free(m[i]); vm_page_unlock_queues(); + vm_page_unlock(m[i]); VM_OBJECT_UNLOCK(object); runend = i + 1; first = runend; @@ -829,18 +852,24 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) runend = i + runpg; if (runend <= reqpage) { VM_OBJECT_LOCK(object); - vm_page_lock_queues(); - for (j = i; j < runend; j++) + for (j = i; j < runend; j++) { + vm_page_lock(m[j]); + vm_page_lock_queues(); vm_page_free(m[j]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[j]); + } VM_OBJECT_UNLOCK(object); } else { if (runpg < (count - first)) { VM_OBJECT_LOCK(object); - vm_page_lock_queues(); - for (i = first + runpg; i < count; i++) + for (i = first + runpg; i < count; i++) { + vm_page_lock(m[i]); + vm_page_lock_queues(); vm_page_free(m[i]); - vm_page_unlock_queues(); + vm_page_unlock_queues(); + vm_page_unlock(m[i]); + } VM_OBJECT_UNLOCK(object); count = first + runpg; } @@ -931,13 +960,14 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) relpbuf(bp, &vnode_pbuf_freecnt); VM_OBJECT_LOCK(object); - vm_page_lock_queues(); for (i = 0, tfoff = foff; i < count; i++, tfoff = nextoff) { vm_page_t mt; nextoff = tfoff + PAGE_SIZE; mt = m[i]; + vm_page_lock(mt); + vm_page_lock_queues(); if (nextoff <= object->un_pager.vnp.vnp_size) { /* * Read filled up entire page. @@ -989,8 +1019,9 @@ vnode_pager_generic_getpages(vp, m, bytecount, reqpage) vm_page_free(mt); } } + vm_page_unlock_queues(); + vm_page_unlock(mt); } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); if (error) { printf("vnode_pager_getpages: I/O read error\n"); @@ -1113,10 +1144,12 @@ vnode_pager_generic_putpages(vp, m, bytecount, flags, rtvals) maxsize = object->un_pager.vnp.vnp_size - poffset; ncount = btoc(maxsize); if ((pgoff = (int)maxsize & PAGE_MASK) != 0) { + vm_page_lock(m[ncount - 1]); vm_page_lock_queues(); vm_page_clear_dirty(m[ncount - 1], pgoff, PAGE_SIZE - pgoff); vm_page_unlock_queues(); + vm_page_unlock(m[ncount - 1]); } } else { maxsize = 0; -- cgit v1.1 From 5724de4184a459c33f997588030ec060f43dcb52 Mon Sep 17 00:00:00 2001 From: davidch Date: Fri, 30 Apr 2010 02:35:46 +0000 Subject: - Enable flow control. - Print device details only when verbose boot is enabled. - Add debug output for shared memory access. - Add debug statistics (checksum offload & VLAN frame counters). - Modify TX path to update consumer index for each frame completed rather than updating the consumer index only once for a group of frames to improve small packet performance. - Print driver/firmware pulse messages only when verbose boot is enabled. - Add debug sysctl to clear statistics. - Fix more style(9) violations. MFC after: 2 weeks --- sys/dev/bce/if_bce.c | 1131 +++++++++++++++++++++++++++-------------------- sys/dev/bce/if_bcereg.h | 622 +++++++++++++------------- 2 files changed, 962 insertions(+), 791 deletions(-) diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c index 2ad5ab2..6608dbd 100644 --- a/sys/dev/bce/if_bce.c +++ b/sys/dev/bce/if_bce.c @@ -303,7 +303,7 @@ static void bce_dump_txbd (struct bce_softc *, static void bce_dump_rxbd (struct bce_softc *, int, struct rx_bd *); #ifdef BCE_JUMBO_HDRSPLIT -static void bce_dump_pgbd (struct bce_softc *, +static void bce_dump_pgbd (struct bce_softc *, int, struct rx_bd *); #endif static void bce_dump_l2fhdr (struct bce_softc *, @@ -368,7 +368,7 @@ static int bce_nvram_write (struct bce_softc *, u32, u8 *, int); /****************************************************************************/ static void bce_get_media (struct bce_softc *); static void bce_init_media (struct bce_softc *); -static void bce_dma_map_addr (void *, +static void bce_dma_map_addr (void *, bus_dma_segment_t *, int, int); static int bce_dma_alloc (device_t); static void bce_dma_free (struct bce_softc *); @@ -379,7 +379,7 @@ static void bce_release_resources (struct bce_softc *); /****************************************************************************/ static int bce_fw_sync (struct bce_softc *, u32); static void bce_load_rv2p_fw (struct bce_softc *, u32 *, u32, u32); -static void bce_load_cpu_fw (struct bce_softc *, +static void bce_load_cpu_fw (struct bce_softc *, struct cpu_reg *, struct fw_info *); static void bce_start_cpu (struct bce_softc *, struct cpu_reg *); static void bce_halt_cpu (struct bce_softc *, struct cpu_reg *); @@ -401,21 +401,21 @@ static int bce_blockinit (struct bce_softc *); static int bce_init_tx_chain (struct bce_softc *); static void bce_free_tx_chain (struct bce_softc *); -static int bce_get_rx_buf (struct bce_softc *, +static int bce_get_rx_buf (struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *); static int bce_init_rx_chain (struct bce_softc *); static void bce_fill_rx_chain (struct bce_softc *); static void bce_free_rx_chain (struct bce_softc *); #ifdef BCE_JUMBO_HDRSPLIT -static int bce_get_pg_buf (struct bce_softc *, +static int bce_get_pg_buf (struct bce_softc *, struct mbuf *, u16 *, u16 *); static int bce_init_pg_chain (struct bce_softc *); static void bce_fill_pg_chain (struct bce_softc *); static void bce_free_pg_chain (struct bce_softc *); #endif -static struct mbuf *bce_tso_setup (struct bce_softc *, +static struct mbuf *bce_tso_setup (struct bce_softc *, struct mbuf **, u16 *); static int bce_tx_encap (struct bce_softc *, struct mbuf **); static void bce_start_locked (struct ifnet *); @@ -566,7 +566,7 @@ bce_probe(device_t dev) /* Print out the device identity. */ snprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d)", - t->bce_name, (((pci_read_config(dev, + t->bce_name, (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'), (pci_read_config(dev, PCIR_REVID, 4) & 0xf)); @@ -593,57 +593,60 @@ bce_probe(device_t dev) static void bce_print_adapter_info(struct bce_softc *sc) { - int i = 0; + int i = 0; DBENTER(BCE_VERBOSE_LOAD); - BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid); - printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A', - ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4)); + if (bootverbose) { + BCE_PRINTF("ASIC (0x%08X); ", sc->bce_chipid); + printf("Rev (%c%d); ", ((BCE_CHIP_ID(sc) & 0xf000) >> + 12) + 'A', ((BCE_CHIP_ID(sc) & 0x0ff0) >> 4)); + - /* Bus info. */ - if (sc->bce_flags & BCE_PCIE_FLAG) { - printf("Bus (PCIe x%d, ", sc->link_width); - switch (sc->link_speed) { - case 1: printf("2.5Gbps); "); break; - case 2: printf("5Gbps); "); break; - default: printf("Unknown link speed); "); + /* Bus info. */ + if (sc->bce_flags & BCE_PCIE_FLAG) { + printf("Bus (PCIe x%d, ", sc->link_width); + switch (sc->link_speed) { + case 1: printf("2.5Gbps); "); break; + case 2: printf("5Gbps); "); break; + default: printf("Unknown link speed); "); + } + } else { + printf("Bus (PCI%s, %s, %dMHz); ", + ((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""), + ((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? + "32-bit" : "64-bit"), sc->bus_speed_mhz); } - } else { - printf("Bus (PCI%s, %s, %dMHz); ", - ((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""), - ((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? - "32-bit" : "64-bit"), sc->bus_speed_mhz); - } - /* Firmware version and device features. */ - printf("B/C (%s); Flags (", sc->bce_bc_ver); + /* Firmware version and device features. */ + printf("B/C (%s); Flags (", sc->bce_bc_ver); -#ifdef BCE_JUMBO_HDRSPLIT - printf("SPLT"); - i++; -#endif + #ifdef BCE_JUMBO_HDRSPLIT + printf("SPLT"); + i++; + #endif - if (sc->bce_flags & BCE_USING_MSI_FLAG) { - if (i > 0) printf("|"); - printf("MSI"); i++; - } + if (sc->bce_flags & BCE_USING_MSI_FLAG) { + if (i > 0) printf("|"); + printf("MSI"); i++; + } - if (sc->bce_flags & BCE_USING_MSIX_FLAG) { - if (i > 0) printf("|"); - printf("MSI-X"); i++; - } + if (sc->bce_flags & BCE_USING_MSIX_FLAG) { + if (i > 0) printf("|"); + printf("MSI-X"); i++; + } - if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) { - if (i > 0) printf("|"); - printf("2.5G"); i++; - } + if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG) { + if (i > 0) printf("|"); + printf("2.5G"); i++; + } - if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) { - if (i > 0) printf("|"); - printf("MFW); MFW (%s)\n", sc->bce_mfw_ver); - } else { - printf(")\n"); + if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) { + if (i > 0) printf("|"); + printf("MFW); MFW (%s)\n", sc->bce_mfw_ver); + } else { + printf(")\n"); + } } DBEXIT(BCE_VERBOSE_LOAD); @@ -785,13 +788,13 @@ bce_attach(device_t dev) (bce_msi_enable >= 1) && (sc->bce_msi_count == 0)) { sc->bce_msi_count = 1; if ((error = pci_alloc_msi(dev, &sc->bce_msi_count)) != 0) { - BCE_PRINTF("%s(%d): MSI allocation failed! error = %d\n", - __FILE__, __LINE__, error); + BCE_PRINTF("%s(%d): MSI allocation failed! " + "error = %d\n", __FILE__, __LINE__, error); sc->bce_msi_count = 0; pci_release_msi(dev); } else { - DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI interrupt.\n", - __FUNCTION__); + DBPRINT(sc, BCE_INFO_LOAD, "%s(): Using MSI " + "interrupt.\n", __FUNCTION__); sc->bce_flags |= BCE_USING_MSI_FLAG; if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) @@ -848,10 +851,11 @@ bce_attach(device_t dev) case BCE_CHIP_ID_5709_B0: case BCE_CHIP_ID_5709_B1: case BCE_CHIP_ID_5709_B2: - BCE_PRINTF("%s(%d): Unsupported controller revision (%c%d)!\n", - __FILE__, __LINE__, - (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'), - (pci_read_config(dev, PCIR_REVID, 4) & 0xf)); + BCE_PRINTF("%s(%d): Unsupported controller " + "revision (%c%d)!\n", __FILE__, __LINE__, + (((pci_read_config(dev, PCIR_REVID, 4) & + 0xf0) >> 4) + 'A'), (pci_read_config(dev, + PCIR_REVID, 4) & 0xf)); rc = ENODEV; goto bce_attach_fail; } @@ -1072,19 +1076,19 @@ bce_attach(device_t dev) ifp = sc->bce_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { BCE_PRINTF("%s(%d): Interface allocation failed!\n", - __FILE__, __LINE__); + __FILE__, __LINE__); rc = ENXIO; goto bce_attach_fail; } /* Initialize the ifnet interface. */ - ifp->if_softc = sc; + ifp->if_softc = sc; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - ifp->if_ioctl = bce_ioctl; - ifp->if_start = bce_start; - ifp->if_init = bce_init; - ifp->if_mtu = ETHERMTU; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = bce_ioctl; + ifp->if_start = bce_start; + ifp->if_init = bce_init; + ifp->if_mtu = ETHERMTU; if (bce_tso_enable) { ifp->if_hwassist = BCE_IF_HWASSIST | CSUM_TSO; @@ -1095,7 +1099,7 @@ bce_attach(device_t dev) ifp->if_capabilities = BCE_IF_CAPABILITIES; } - ifp->if_capenable = ifp->if_capabilities; + ifp->if_capenable = ifp->if_capabilities; /* * Assume standard mbuf sizes for buffer allocation. @@ -1105,16 +1109,17 @@ bce_attach(device_t dev) #ifdef BCE_JUMBO_HDRSPLIT sc->rx_bd_mbuf_alloc_size = MHLEN; /* Make sure offset is 16 byte aligned for hardware. */ - sc->rx_bd_mbuf_align_pad = roundup2((MSIZE - MHLEN), 16) - - (MSIZE - MHLEN); - sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size - - sc->rx_bd_mbuf_align_pad; + sc->rx_bd_mbuf_align_pad = + roundup2((MSIZE - MHLEN), 16) - (MSIZE - MHLEN); + sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size - + sc->rx_bd_mbuf_align_pad; sc->pg_bd_mbuf_alloc_size = MCLBYTES; #else sc->rx_bd_mbuf_alloc_size = MCLBYTES; - sc->rx_bd_mbuf_align_pad = roundup2(MCLBYTES, 16) - MCLBYTES; - sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size - - sc->rx_bd_mbuf_align_pad; + sc->rx_bd_mbuf_align_pad = + roundup2(MCLBYTES, 16) - MCLBYTES; + sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size - + sc->rx_bd_mbuf_align_pad; #endif ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD; @@ -1126,14 +1131,14 @@ bce_attach(device_t dev) else ifp->if_baudrate = IF_Mbps(1000); - /* Handle any special PHY initialization for SerDes PHYs. */ - bce_init_media(sc); + /* Handle any special PHY initialization for SerDes PHYs. */ + bce_init_media(sc); /* MII child bus by probing the PHY. */ if (mii_phy_probe(dev, &sc->bce_miibus, bce_ifmedia_upd, bce_ifmedia_sts)) { BCE_PRINTF("%s(%d): No PHY found on child MII bus!\n", - __FILE__, __LINE__); + __FILE__, __LINE__); rc = ENXIO; goto bce_attach_fail; } @@ -1155,7 +1160,7 @@ bce_attach(device_t dev) if (rc) { BCE_PRINTF("%s(%d): Failed to setup IRQ!\n", - __FILE__, __LINE__); + __FILE__, __LINE__); bce_detach(dev); goto bce_attach_exit; } @@ -1396,6 +1401,9 @@ bce_reg_wr_ind(struct bce_softc *sc, u32 offset, u32 val) static void bce_shmem_wr(struct bce_softc *sc, u32 offset, u32 val) { + DBPRINT(sc, BCE_VERBOSE_FIRMWARE, "%s(): Writing 0x%08X to " + "0x%08X\n", __FUNCTION__, val, offset); + bce_reg_wr_ind(sc, sc->bce_shmem_base + offset, val); } @@ -1411,7 +1419,12 @@ bce_shmem_wr(struct bce_softc *sc, u32 offset, u32 val) static u32 bce_shmem_rd(struct bce_softc *sc, u32 offset) { - return (bce_reg_rd_ind(sc, sc->bce_shmem_base + offset)); + u32 val = bce_reg_rd_ind(sc, sc->bce_shmem_base + offset); + + DBPRINT(sc, BCE_VERBOSE_FIRMWARE, "%s(): Reading 0x%08X from " + "0x%08X\n", __FUNCTION__, val, offset); + + return val; } @@ -1430,9 +1443,9 @@ bce_ctx_rd(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset) { u32 idx, offset, retry_cnt = 5, val; - DBRUNIF((cid_addr > MAX_CID_ADDR || ctx_offset & 0x3 || cid_addr & CTX_MASK), - BCE_PRINTF("%s(): Invalid CID address: 0x%08X.\n", - __FUNCTION__, cid_addr)); + DBRUNIF((cid_addr > MAX_CID_ADDR || ctx_offset & 0x3 || + cid_addr & CTX_MASK), BCE_PRINTF("%s(): Invalid CID " + "address: 0x%08X.\n", __FUNCTION__, cid_addr)); offset = ctx_offset + cid_addr; @@ -1450,8 +1463,8 @@ bce_ctx_rd(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset) if (val & BCE_CTX_CTX_CTRL_READ_REQ) BCE_PRINTF("%s(%d); Unable to read CTX memory: " - "cid_addr = 0x%08X, offset = 0x%08X!\n", - __FILE__, __LINE__, cid_addr, ctx_offset); + "cid_addr = 0x%08X, offset = 0x%08X!\n", + __FILE__, __LINE__, cid_addr, ctx_offset); val = REG_RD(sc, BCE_CTX_CTX_DATA); } else { @@ -1487,7 +1500,7 @@ bce_ctx_wr(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset, u32 ctx_val) DBRUNIF((cid_addr > MAX_CID_ADDR || ctx_offset & 0x3 || cid_addr & CTX_MASK), BCE_PRINTF("%s(): Invalid CID address: 0x%08X.\n", - __FUNCTION__, cid_addr)); + __FUNCTION__, cid_addr)); if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { @@ -1504,8 +1517,8 @@ bce_ctx_wr(struct bce_softc *sc, u32 cid_addr, u32 ctx_offset, u32 ctx_val) if (val & BCE_CTX_CTX_CTRL_WRITE_REQ) BCE_PRINTF("%s(%d); Unable to write CTX memory: " - "cid_addr = 0x%08X, offset = 0x%08X!\n", - __FILE__, __LINE__, cid_addr, ctx_offset); + "cid_addr = 0x%08X, offset = 0x%08X!\n", + __FILE__, __LINE__, cid_addr, ctx_offset); } else { REG_WR(sc, BCE_CTX_DATA_ADR, offset); @@ -1706,54 +1719,73 @@ bce_miibus_statchg(device_t dev) val = REG_RD(sc, BCE_EMAC_MODE); val &= ~(BCE_EMAC_MODE_PORT | BCE_EMAC_MODE_HALF_DUPLEX | - BCE_EMAC_MODE_MAC_LOOP | BCE_EMAC_MODE_FORCE_LINK | - BCE_EMAC_MODE_25G); + BCE_EMAC_MODE_MAC_LOOP | BCE_EMAC_MODE_FORCE_LINK | + BCE_EMAC_MODE_25G); - /* Set MII or GMII interface based on the speed negotiated by the PHY. */ + /* Set MII or GMII interface based on the PHY speed. */ switch (IFM_SUBTYPE(mii->mii_media_active)) { case IFM_10_T: if (BCE_CHIP_NUM(sc) != BCE_CHIP_NUM_5706) { - DBPRINT(sc, BCE_INFO, "Enabling 10Mb interface.\n"); + DBPRINT(sc, BCE_INFO_PHY, + "Enabling 10Mb interface.\n"); val |= BCE_EMAC_MODE_PORT_MII_10; break; } /* fall-through */ case IFM_100_TX: - DBPRINT(sc, BCE_INFO, "Enabling MII interface.\n"); + DBPRINT(sc, BCE_INFO_PHY, "Enabling MII interface.\n"); val |= BCE_EMAC_MODE_PORT_MII; break; case IFM_2500_SX: - DBPRINT(sc, BCE_INFO, "Enabling 2.5G MAC mode.\n"); + DBPRINT(sc, BCE_INFO_PHY, "Enabling 2.5G MAC mode.\n"); val |= BCE_EMAC_MODE_25G; /* fall-through */ case IFM_1000_T: case IFM_1000_SX: - DBPRINT(sc, BCE_INFO, "Enabling GMII interface.\n"); + DBPRINT(sc, BCE_INFO_PHY, "Enabling GMII interface.\n"); val |= BCE_EMAC_MODE_PORT_GMII; break; default: - DBPRINT(sc, BCE_INFO, "Unknown speed, enabling default GMII " - "interface.\n"); + DBPRINT(sc, BCE_INFO_PHY, "Unknown link speed, enabling " + "default GMII interface.\n"); val |= BCE_EMAC_MODE_PORT_GMII; } - /* Set half or full duplex based on the duplicity negotiated by the PHY. */ + /* Set half or full duplex based on PHY settings. */ if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) { - DBPRINT(sc, BCE_INFO, "Setting Half-Duplex interface.\n"); + DBPRINT(sc, BCE_INFO_PHY, + "Setting Half-Duplex interface.\n"); val |= BCE_EMAC_MODE_HALF_DUPLEX; } else - DBPRINT(sc, BCE_INFO, "Setting Full-Duplex interface.\n"); + DBPRINT(sc, BCE_INFO_PHY, + "Setting Full-Duplex interface.\n"); REG_WR(sc, BCE_EMAC_MODE, val); -#if 0 - /* ToDo: Enable flow control support in brgphy and bge. */ /* FLAG0 is set if RX is enabled and FLAG1 if TX is enabled */ - if (mii->mii_media_active & IFM_FLAG0) + if (mii->mii_media_active & IFM_FLAG0) { + DBPRINT(sc, BCE_INFO_PHY, + "%s(): Enabling RX flow control.\n", __FUNCTION__); BCE_SETBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN); - if (mii->mii_media_active & IFM_FLAG1) - BCE_SETBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_TX_MODE_FLOW_EN); -#endif + } else { + DBPRINT(sc, BCE_INFO_PHY, + "%s(): Disabling RX flow control.\n", __FUNCTION__); + BCE_CLRBIT(sc, BCE_EMAC_RX_MODE, BCE_EMAC_RX_MODE_FLOW_EN); + } + + if (mii->mii_media_active & IFM_FLAG1) { + DBPRINT(sc, BCE_INFO_PHY, + "%s(): Enabling TX flow control.\n", __FUNCTION__); + BCE_SETBIT(sc, BCE_EMAC_TX_MODE, BCE_EMAC_TX_MODE_FLOW_EN); + sc->bce_flags |= BCE_USING_TX_FLOW_CONTROL; + } else { + DBPRINT(sc, BCE_INFO_PHY, + "%s(): Disabling TX flow control.\n", __FUNCTION__); + BCE_CLRBIT(sc, BCE_EMAC_TX_MODE, BCE_EMAC_TX_MODE_FLOW_EN); + sc->bce_flags &= ~BCE_USING_TX_FLOW_CONTROL; + } + + /* ToDo: Update watermarks in bce_init_rx_context(). */ DBEXIT(BCE_VERBOSE_PHY); } @@ -1926,8 +1958,8 @@ bce_enable_nvram_access(struct bce_softc *sc) val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE); /* Enable both bits, even on read. */ - REG_WR(sc, BCE_NVM_ACCESS_ENABLE, - val | BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN); + REG_WR(sc, BCE_NVM_ACCESS_ENABLE, val | + BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN); DBEXIT(BCE_VERBOSE_NVRAM); } @@ -1951,9 +1983,8 @@ bce_disable_nvram_access(struct bce_softc *sc) val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE); /* Disable both bits, even after read. */ - REG_WR(sc, BCE_NVM_ACCESS_ENABLE, - val & ~(BCE_NVM_ACCESS_ENABLE_EN | - BCE_NVM_ACCESS_ENABLE_WR_EN)); + REG_WR(sc, BCE_NVM_ACCESS_ENABLE, val & + ~(BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN)); DBEXIT(BCE_VERBOSE_NVRAM); } @@ -1983,7 +2014,7 @@ bce_nvram_erase_page(struct bce_softc *sc, u32 offset) /* Build an erase command. */ cmd = BCE_NVM_COMMAND_ERASE | BCE_NVM_COMMAND_WR | - BCE_NVM_COMMAND_DOIT; + BCE_NVM_COMMAND_DOIT; /* * Clear the DONE bit separately, set the NVRAM adress to erase, @@ -2026,8 +2057,8 @@ bce_nvram_erase_page_exit: /* 0 on success and the 32 bit value read, positive value on failure. */ /****************************************************************************/ static int -bce_nvram_read_dword(struct bce_softc *sc, u32 offset, u8 *ret_val, - u32 cmd_flags) +bce_nvram_read_dword(struct bce_softc *sc, + u32 offset, u8 *ret_val, u32 cmd_flags) { u32 cmd; int i, rc = 0; @@ -2040,8 +2071,8 @@ bce_nvram_read_dword(struct bce_softc *sc, u32 offset, u8 *ret_val, /* Calculate the offset for buffered flash if translation is used. */ if (sc->bce_flash_info->flags & BCE_NV_TRANSLATE) { offset = ((offset / sc->bce_flash_info->page_size) << - sc->bce_flash_info->page_bits) + - (offset % sc->bce_flash_info->page_size); + sc->bce_flash_info->page_bits) + + (offset % sc->bce_flash_info->page_size); } /* @@ -2070,8 +2101,8 @@ bce_nvram_read_dword(struct bce_softc *sc, u32 offset, u8 *ret_val, /* Check for errors. */ if (i >= NVRAM_TIMEOUT_COUNT) { - BCE_PRINTF("%s(%d): Timeout error reading NVRAM at offset 0x%08X!\n", - __FILE__, __LINE__, offset); + BCE_PRINTF("%s(%d): Timeout error reading NVRAM at " + "offset 0x%08X!\n", __FILE__, __LINE__, offset); rc = EBUSY; } @@ -2106,8 +2137,8 @@ bce_nvram_write_dword(struct bce_softc *sc, u32 offset, u8 *val, /* Calculate the offset for buffered flash if translation is used. */ if (sc->bce_flash_info->flags & BCE_NV_TRANSLATE) { offset = ((offset / sc->bce_flash_info->page_size) << - sc->bce_flash_info->page_bits) + - (offset % sc->bce_flash_info->page_size); + sc->bce_flash_info->page_bits) + + (offset % sc->bce_flash_info->page_size); } /* @@ -2129,8 +2160,8 @@ bce_nvram_write_dword(struct bce_softc *sc, u32 offset, u8 *val, break; } if (j >= NVRAM_TIMEOUT_COUNT) { - BCE_PRINTF("%s(%d): Timeout error writing NVRAM at offset 0x%08X\n", - __FILE__, __LINE__, offset); + BCE_PRINTF("%s(%d): Timeout error writing NVRAM at " + "offset 0x%08X\n", __FILE__, __LINE__, offset); rc = EBUSY; } @@ -2232,7 +2263,7 @@ bce_init_nvram(struct bce_softc *sc) if (j == entry_count) { sc->bce_flash_info = NULL; BCE_PRINTF("%s(%d): Unknown Flash NVRAM found!\n", - __FILE__, __LINE__); + __FILE__, __LINE__); rc = ENODEV; } @@ -2246,8 +2277,8 @@ bce_init_nvram_get_flash_size: sc->bce_flash_size = sc->bce_flash_info->total_size; DBPRINT(sc, BCE_INFO_LOAD, "%s(): Found %s, size = 0x%08X\n", - __FUNCTION__, sc->bce_flash_info->name, - sc->bce_flash_info->total_size); + __FUNCTION__, sc->bce_flash_info->name, + sc->bce_flash_info->total_size); DBEXIT(BCE_VERBOSE_NVRAM); return rc; @@ -2604,7 +2635,8 @@ bce_nvram_test(struct bce_softc *sc) * the magic value at offset 0. */ if ((rc = bce_nvram_read(sc, 0, data, 4)) != 0) { - BCE_PRINTF("%s(%d): Unable to read NVRAM!\n", __FILE__, __LINE__); + BCE_PRINTF("%s(%d): Unable to read NVRAM!\n", + __FILE__, __LINE__); goto bce_nvram_test_exit; } @@ -2615,9 +2647,9 @@ bce_nvram_test(struct bce_softc *sc) magic = bce_be32toh(buf[0]); if (magic != BCE_NVRAM_MAGIC) { rc = ENODEV; - BCE_PRINTF("%s(%d): Invalid NVRAM magic value! Expected: 0x%08X, " - "Found: 0x%08X\n", - __FILE__, __LINE__, BCE_NVRAM_MAGIC, magic); + BCE_PRINTF("%s(%d): Invalid NVRAM magic value! " + "Expected: 0x%08X, Found: 0x%08X\n", + __FILE__, __LINE__, BCE_NVRAM_MAGIC, magic); goto bce_nvram_test_exit; } @@ -2626,26 +2658,27 @@ bce_nvram_test(struct bce_softc *sc) * configuration data. */ if ((rc = bce_nvram_read(sc, 0x100, data, BCE_NVRAM_SIZE)) != 0) { - BCE_PRINTF("%s(%d): Unable to read Manufacturing Information from " - "NVRAM!\n", __FILE__, __LINE__); + BCE_PRINTF("%s(%d): Unable to read manufacturing " + "Information from NVRAM!\n", __FILE__, __LINE__); goto bce_nvram_test_exit; } csum = ether_crc32_le(data, 0x100); if (csum != BCE_CRC32_RESIDUAL) { rc = ENODEV; - BCE_PRINTF("%s(%d): Invalid Manufacturing Information NVRAM CRC! " - "Expected: 0x%08X, Found: 0x%08X\n", - __FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum); + BCE_PRINTF("%s(%d): Invalid manufacturing information " + "NVRAM CRC! Expected: 0x%08X, Found: 0x%08X\n", + __FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum); goto bce_nvram_test_exit; } csum = ether_crc32_le(data + 0x100, 0x100); if (csum != BCE_CRC32_RESIDUAL) { rc = ENODEV; - BCE_PRINTF("%s(%d): Invalid Feature Configuration Information " - "NVRAM CRC! Expected: 0x%08X, Found: 08%08X\n", - __FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum); + BCE_PRINTF("%s(%d): Invalid feature configuration " + "information NVRAM CRC! Expected: 0x%08X, " + "Found: 08%08X\n", __FILE__, __LINE__, + BCE_CRC32_RESIDUAL, csum); } bce_nvram_test_exit: @@ -2666,7 +2699,7 @@ bce_get_media(struct bce_softc *sc) { u32 val; - DBENTER(BCE_VERBOSE); + DBENTER(BCE_VERBOSE_PHY); /* Assume PHY address for copper controllers. */ sc->bce_phy_addr = 1; @@ -2692,10 +2725,10 @@ bce_get_media(struct bce_softc *sc) } if (val & BCE_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE) - strap = (val & + strap = (val & BCE_MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21; else - strap = (val & + strap = (val & BCE_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8; if (pci_get_function(sc->bce_dev) == 0) { @@ -2744,7 +2777,7 @@ bce_get_media(struct bce_softc *sc) val = bce_shmem_rd(sc, BCE_SHARED_HW_CFG_CONFIG); if (val & BCE_SHARED_HW_CFG_PHY_2_5G) { - sc->bce_phy_flags |= + sc->bce_phy_flags |= BCE_PHY_2_5G_CAPABLE_FLAG; DBPRINT(sc, BCE_INFO_LOAD, "Found 2.5Gb " "capable adapter\n"); @@ -2758,7 +2791,7 @@ bce_get_media_exit: DBPRINT(sc, (BCE_INFO_LOAD | BCE_INFO_PHY), "Using PHY address %d.\n", sc->bce_phy_addr); - DBEXIT(BCE_VERBOSE); + DBEXIT(BCE_VERBOSE_PHY); } @@ -3056,7 +3089,9 @@ bce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) /* Simulate a mapping failure. */ DBRUNIF(DB_RANDOMTRUE(dma_map_addr_failed_sim_control), - error = ENOMEM); + error = ENOMEM); + + /* ToDo: How to increment debug sim_count variable here? */ /* Check for an error and signal the caller that an error occurred. */ if (error) { @@ -3154,7 +3189,7 @@ bce_dma_alloc(device_t dev) goto bce_dma_alloc_exit; } - DBPRINT(sc, BCE_INFO, "%s(): status_block_paddr = 0x%jX\n", + DBPRINT(sc, BCE_INFO_LOAD, "%s(): status_block_paddr = 0x%jX\n", __FUNCTION__, (uintmax_t) sc->status_block_paddr); /* @@ -3193,7 +3228,7 @@ bce_dma_alloc(device_t dev) goto bce_dma_alloc_exit; } - DBPRINT(sc, BCE_INFO, "%s(): stats_block_paddr = 0x%jX\n", + DBPRINT(sc, BCE_INFO_LOAD, "%s(): stats_block_paddr = 0x%jX\n", __FUNCTION__, (uintmax_t) sc->stats_block_paddr); /* BCM5709 uses host memory as cache for context memory. */ @@ -3217,8 +3252,8 @@ bce_dma_alloc(device_t dev) BCE_DMA_BOUNDARY, sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL, BCM_PAGE_SIZE, 1, BCM_PAGE_SIZE, 0, NULL, NULL, &sc->ctx_tag)) { - BCE_PRINTF("%s(%d): Could not allocate CTX DMA tag!\n", - __FILE__, __LINE__); + BCE_PRINTF("%s(%d): Could not allocate CTX " + "DMA tag!\n", __FILE__, __LINE__); rc = ENOMEM; goto bce_dma_alloc_exit; } @@ -3248,8 +3283,9 @@ bce_dma_alloc(device_t dev) goto bce_dma_alloc_exit; } - DBPRINT(sc, BCE_INFO, "%s(): ctx_paddr[%d] = 0x%jX\n", - __FUNCTION__, i, (uintmax_t) sc->ctx_paddr[i]); + DBPRINT(sc, BCE_INFO_LOAD, "%s(): ctx_paddr[%d] " + "= 0x%jX\n", __FUNCTION__, i, + (uintmax_t) sc->ctx_paddr[i]); } } @@ -3262,15 +3298,15 @@ bce_dma_alloc(device_t dev) sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL, BCE_TX_CHAIN_PAGE_SZ, 1, BCE_TX_CHAIN_PAGE_SZ, 0, NULL, NULL, &sc->tx_bd_chain_tag)) { - BCE_PRINTF("%s(%d): Could not allocate TX descriptor chain " - "DMA tag!\n", __FILE__, __LINE__); + BCE_PRINTF("%s(%d): Could not allocate TX descriptor " + "chain DMA tag!\n", __FILE__, __LINE__); rc = ENOMEM; goto bce_dma_alloc_exit; } for (i = 0; i < TX_PAGES; i++) { - if(bus_dmamem_alloc(sc->tx_bd_chain_tag, + if(bus_dmamem_alloc(sc->tx_bd_chain_tag, (void **)&sc->tx_bd_chain[i], BUS_DMA_NOWAIT, &sc->tx_bd_chain_map[i])) { BCE_PRINTF("%s(%d): Could not allocate TX descriptor " @@ -3291,8 +3327,9 @@ bce_dma_alloc(device_t dev) goto bce_dma_alloc_exit; } - DBPRINT(sc, BCE_INFO, "%s(): tx_bd_chain_paddr[%d] = 0x%jX\n", - __FUNCTION__, i, (uintmax_t) sc->tx_bd_chain_paddr[i]); + DBPRINT(sc, BCE_INFO_LOAD, "%s(): tx_bd_chain_paddr[%d] = " + "0x%jX\n", __FUNCTION__, i, + (uintmax_t) sc->tx_bd_chain_paddr[i]); } /* Check the required size before mapping to conserve resources. */ @@ -3368,8 +3405,9 @@ bce_dma_alloc(device_t dev) goto bce_dma_alloc_exit; } - DBPRINT(sc, BCE_INFO, "%s(): rx_bd_chain_paddr[%d] = 0x%jX\n", - __FUNCTION__, i, (uintmax_t) sc->rx_bd_chain_paddr[i]); + DBPRINT(sc, BCE_INFO_LOAD, "%s(): rx_bd_chain_paddr[%d] = " + "0x%jX\n", __FUNCTION__, i, + (uintmax_t) sc->rx_bd_chain_paddr[i]); } /* @@ -3383,9 +3421,10 @@ bce_dma_alloc(device_t dev) #endif max_segments = 1; - DBPRINT(sc, BCE_INFO, "%s(): Creating rx_mbuf_tag (max size = 0x%jX " - "max segments = %d, max segment size = 0x%jX)\n", __FUNCTION__, - (uintmax_t) max_size, max_segments, (uintmax_t) max_seg_size); + DBPRINT(sc, BCE_INFO_LOAD, "%s(): Creating rx_mbuf_tag " + "(max size = 0x%jX max segments = %d, max segment " + "size = 0x%jX)\n", __FUNCTION__, (uintmax_t) max_size, + max_segments, (uintmax_t) max_seg_size); if (bus_dma_tag_create(sc->parent_tag, 1, BCE_DMA_BOUNDARY, sc->max_bus_addr, BUS_SPACE_MAXADDR, NULL, NULL, max_size, @@ -3429,7 +3468,7 @@ bce_dma_alloc(device_t dev) (void **)&sc->pg_bd_chain[i], BUS_DMA_NOWAIT, &sc->pg_bd_chain_map[i])) { BCE_PRINTF("%s(%d): Could not allocate page " - "descriptor chain DMA memory!\n", + "descriptor chain DMA memory!\n", __FILE__, __LINE__); rc = ENOMEM; goto bce_dma_alloc_exit; @@ -3437,7 +3476,7 @@ bce_dma_alloc(device_t dev) bzero((char *)sc->pg_bd_chain[i], BCE_PG_CHAIN_PAGE_SZ); - error = bus_dmamap_load(sc->pg_bd_chain_tag, + error = bus_dmamap_load(sc->pg_bd_chain_tag, sc->pg_bd_chain_map[i], sc->pg_bd_chain[i], BCE_PG_CHAIN_PAGE_SZ, bce_dma_map_addr, &sc->pg_bd_chain_paddr[i], BUS_DMA_NOWAIT); @@ -3449,8 +3488,9 @@ bce_dma_alloc(device_t dev) goto bce_dma_alloc_exit; } - DBPRINT(sc, BCE_INFO, "%s(): pg_bd_chain_paddr[%d] = 0x%jX\n", - __FUNCTION__, i, (uintmax_t) sc->pg_bd_chain_paddr[i]); + DBPRINT(sc, BCE_INFO_LOAD, "%s(): pg_bd_chain_paddr[%d] = " + "0x%jX\n", __FUNCTION__, i, + (uintmax_t) sc->pg_bd_chain_paddr[i]); } /* @@ -3524,7 +3564,7 @@ bce_release_resources(struct bce_softc *sc) if (sc->bce_res_mem != NULL) { DBPRINT(sc, BCE_INFO_RESET, "Releasing PCI memory.\n"); - bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), + bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), sc->bce_res_mem); } @@ -3582,7 +3622,7 @@ bce_fw_sync(struct bce_softc *sc, u32 msg_data) DELAY(1000); } - /* If we've timed out, tell the bootcode that we've stopped waiting. */ + /* If we've timed out, tell bootcode that we've stopped waiting. */ if (((val & BCE_FW_MSG_ACK) != (msg_data & BCE_DRV_MSG_SEQ)) && ((msg_data & BCE_DRV_MSG_DATA) != BCE_DRV_MSG_DATA_WAIT0)) { @@ -4319,22 +4359,22 @@ bce_init_cpus(struct bce_softc *sc) (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { if ((BCE_CHIP_REV(sc) == BCE_CHIP_REV_Ax)) { - bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc1, - sizeof(bce_xi90_rv2p_proc1), RV2P_PROC1); - bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc2, - sizeof(bce_xi90_rv2p_proc2), RV2P_PROC2); + bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc1, + sizeof(bce_xi90_rv2p_proc1), RV2P_PROC1); + bce_load_rv2p_fw(sc, bce_xi90_rv2p_proc2, + sizeof(bce_xi90_rv2p_proc2), RV2P_PROC2); } else { - bce_load_rv2p_fw(sc, bce_xi_rv2p_proc1, - sizeof(bce_xi_rv2p_proc1), RV2P_PROC1); - bce_load_rv2p_fw(sc, bce_xi_rv2p_proc2, - sizeof(bce_xi_rv2p_proc2), RV2P_PROC2); + bce_load_rv2p_fw(sc, bce_xi_rv2p_proc1, + sizeof(bce_xi_rv2p_proc1), RV2P_PROC1); + bce_load_rv2p_fw(sc, bce_xi_rv2p_proc2, + sizeof(bce_xi_rv2p_proc2), RV2P_PROC2); } } else { - bce_load_rv2p_fw(sc, bce_rv2p_proc1, - sizeof(bce_rv2p_proc1), RV2P_PROC1); + bce_load_rv2p_fw(sc, bce_rv2p_proc1, + sizeof(bce_rv2p_proc1), RV2P_PROC1); bce_load_rv2p_fw(sc, bce_rv2p_proc2, - sizeof(bce_rv2p_proc2), RV2P_PROC2); + sizeof(bce_rv2p_proc2), RV2P_PROC2); } bce_init_rxp_cpu(sc); @@ -4373,7 +4413,7 @@ bce_init_ctx(struct bce_softc *sc) * in host memory so prepare the host memory * for access. */ - val = BCE_CTX_COMMAND_ENABLED | + val = BCE_CTX_COMMAND_ENABLED | BCE_CTX_COMMAND_MEM_INIT | (1 << 12); val |= (BCM_PAGE_BITS - 8) << 16; REG_WR(sc, BCE_CTX_COMMAND, val); @@ -4406,7 +4446,7 @@ bce_init_ctx(struct bce_softc *sc) /* Verify the context memory write was successful. */ for (j = 0; j < retry_cnt; j++) { val = REG_RD(sc, BCE_CTX_HOST_PAGE_TBL_CTRL); - if ((val & + if ((val & BCE_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) == 0) break; DELAY(5); @@ -4461,6 +4501,7 @@ bce_get_mac_addr(struct bce_softc *sc) u32 mac_lo = 0, mac_hi = 0; DBENTER(BCE_VERBOSE_RESET); + /* * The NetXtreme II bootcode populates various NIC * power-on and runtime configuration items in a @@ -4475,7 +4516,7 @@ bce_get_mac_addr(struct bce_softc *sc) if ((mac_lo == 0) && (mac_hi == 0)) { BCE_PRINTF("%s(%d): Invalid Ethernet address!\n", - __FILE__, __LINE__); + __FILE__, __LINE__); } else { sc->eaddr[0] = (u_char)(mac_hi >> 8); sc->eaddr[1] = (u_char)(mac_hi >> 0); @@ -4485,7 +4526,8 @@ bce_get_mac_addr(struct bce_softc *sc) sc->eaddr[5] = (u_char)(mac_lo >> 0); } - DBPRINT(sc, BCE_INFO_MISC, "Permanent Ethernet address = %6D\n", sc->eaddr, ":"); + DBPRINT(sc, BCE_INFO_MISC, "Permanent Ethernet " + "address = %6D\n", sc->eaddr, ":"); DBEXIT(BCE_VERBOSE_RESET); } @@ -4505,14 +4547,15 @@ bce_set_mac_addr(struct bce_softc *sc) /* ToDo: Add support for setting multiple MAC addresses. */ DBENTER(BCE_VERBOSE_RESET); - DBPRINT(sc, BCE_INFO_MISC, "Setting Ethernet address = %6D\n", sc->eaddr, ":"); + DBPRINT(sc, BCE_INFO_MISC, "Setting Ethernet address = " + "%6D\n", sc->eaddr, ":"); val = (mac_addr[0] << 8) | mac_addr[1]; REG_WR(sc, BCE_EMAC_MAC_MATCH0, val); val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | - (mac_addr[4] << 8) | mac_addr[5]; + (mac_addr[4] << 8) | mac_addr[5]; REG_WR(sc, BCE_EMAC_MAC_MATCH1, val); @@ -4598,20 +4641,20 @@ bce_reset(struct bce_softc *sc, u32 reset_code) DBENTER(BCE_VERBOSE_RESET); DBPRINT(sc, BCE_VERBOSE_RESET, "%s(): reset_code = 0x%08X\n", - __FUNCTION__, reset_code); + __FUNCTION__, reset_code); /* Wait for pending PCI transactions to complete. */ REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS, - BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | - BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | - BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | - BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); + BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE | + BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE | + BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE | + BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE); val = REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS); DELAY(5); /* Disable DMA */ if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || - (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { + (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { val = REG_RD(sc, BCE_MISC_NEW_CORE_CTL); val &= ~BCE_MISC_NEW_CORE_CTL_DMA_ENABLE; REG_WR(sc, BCE_MISC_NEW_CORE_CTL, val); @@ -4634,26 +4677,26 @@ bce_reset(struct bce_softc *sc, u32 reset_code) /* Chip reset. */ if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || - (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { + (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { REG_WR(sc, BCE_MISC_COMMAND, BCE_MISC_COMMAND_SW_RESET); REG_RD(sc, BCE_MISC_COMMAND); DELAY(5); val = BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | - BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; + BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; pci_write_config(sc->bce_dev, BCE_PCICFG_MISC_CONFIG, val, 4); } else { val = BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | - BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | - BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; + BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | + BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; REG_WR(sc, BCE_PCICFG_MISC_CONFIG, val); /* Allow up to 30us for reset to complete. */ for (i = 0; i < 10; i++) { val = REG_RD(sc, BCE_PCICFG_MISC_CONFIG); if ((val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | - BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) { + BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) { break; } DELAY(10); @@ -4661,9 +4704,9 @@ bce_reset(struct bce_softc *sc, u32 reset_code) /* Check that reset completed successfully. */ if (val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ | - BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { + BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { BCE_PRINTF("%s(%d): Reset failed!\n", - __FILE__, __LINE__); + __FILE__, __LINE__); rc = EBUSY; goto bce_reset_exit; } @@ -4673,7 +4716,7 @@ bce_reset(struct bce_softc *sc, u32 reset_code) val = REG_RD(sc, BCE_PCI_SWAP_DIAG0); if (val != 0x01020304) { BCE_PRINTF("%s(%d): Byte swap is incorrect!\n", - __FILE__, __LINE__); + __FILE__, __LINE__); rc = ENODEV; goto bce_reset_exit; } @@ -4685,8 +4728,8 @@ bce_reset(struct bce_softc *sc, u32 reset_code) /* Wait for the firmware to finish its initialization. */ rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT1 | reset_code); if (rc) - BCE_PRINTF("%s(%d): Firmware did not complete initialization!\n", - __FILE__, __LINE__); + BCE_PRINTF("%s(%d): Firmware did not complete " + "initialization!\n", __FILE__, __LINE__); bce_reset_exit: DBEXIT(BCE_VERBOSE_RESET); @@ -4709,13 +4752,13 @@ bce_chipinit(struct bce_softc *sc) * channels and PCI clock compensation delay. */ val = BCE_DMA_CONFIG_DATA_BYTE_SWAP | - BCE_DMA_CONFIG_DATA_WORD_SWAP | + BCE_DMA_CONFIG_DATA_WORD_SWAP | #if BYTE_ORDER == BIG_ENDIAN - BCE_DMA_CONFIG_CNTL_BYTE_SWAP | + BCE_DMA_CONFIG_CNTL_BYTE_SWAP | #endif - BCE_DMA_CONFIG_CNTL_WORD_SWAP | - DMA_READ_CHANS << 12 | - DMA_WRITE_CHANS << 16; + BCE_DMA_CONFIG_CNTL_WORD_SWAP | + DMA_READ_CHANS << 12 | + DMA_WRITE_CHANS << 16; val |= (0x2 << 20) | BCE_DMA_CONFIG_CNTL_PCI_COMP_DLY; @@ -4765,7 +4808,7 @@ bce_chipinit(struct bce_softc *sc) /* Enable bins used on the 5709. */ if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || - (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { + (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { val |= BCE_MQ_CONFIG_BIN_MQ_MODE; if (BCE_CHIP_ID(sc) == BCE_CHIP_ID_5709_A1) val |= BCE_MQ_CONFIG_HALT_DIS; @@ -4927,7 +4970,7 @@ bce_blockinit(struct bce_softc *sc) } /* Allow bootcode to apply additional fixes before enabling MAC. */ - rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 | + rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 | BCE_DRV_MSG_CODE_RESET); /* Enable link state change interrupt generation. */ @@ -4938,7 +4981,7 @@ bce_blockinit(struct bce_softc *sc) /* Disable management frames (NC-SI) from flowing to the MCP. */ if (sc->bce_flags & BCE_MFW_ENABLE_FLAG) { - val = REG_RD(sc, BCE_RPM_MGMT_PKT_CTRL) & + val = REG_RD(sc, BCE_RPM_MGMT_PKT_CTRL) & ~BCE_RPM_MGMT_PKT_CTRL_MGMT_EN; REG_WR(sc, BCE_RPM_MGMT_PKT_CTRL, val); } @@ -4946,10 +4989,10 @@ bce_blockinit(struct bce_softc *sc) /* Enable all remaining blocks in the MAC. */ if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) - REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, + REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, BCE_MISC_ENABLE_DEFAULT_XI); else - REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, + REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, BCE_MISC_ENABLE_DEFAULT); REG_RD(sc, BCE_MISC_ENABLE_SET_BITS); @@ -4988,8 +5031,9 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, /* Make sure the inputs are valid. */ DBRUNIF((*chain_prod > MAX_RX_BD), - BCE_PRINTF("%s(%d): RX producer out of range: 0x%04X > 0x%04X\n", - __FILE__, __LINE__, *chain_prod, (u16) MAX_RX_BD)); + BCE_PRINTF("%s(%d): RX producer out of range: " + "0x%04X > 0x%04X\n", __FILE__, __LINE__, + *chain_prod, (u16) MAX_RX_BD)); DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): prod = 0x%04X, " "chain_prod = 0x%04X, prod_bseq = 0x%08X\n", __FUNCTION__, @@ -4997,8 +5041,9 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, /* Update some debug statistic counters */ DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark), - sc->rx_low_watermark = sc->free_rx_bd); - DBRUNIF((sc->free_rx_bd == sc->max_rx_bd), sc->rx_empty_count++); + sc->rx_low_watermark = sc->free_rx_bd); + DBRUNIF((sc->free_rx_bd == sc->max_rx_bd), + sc->rx_empty_count++); /* Check whether this is a new mbuf allocation. */ if (m == NULL) { @@ -5017,7 +5062,7 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, if (sc->rx_bd_mbuf_alloc_size <= MCLBYTES) m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); else - m_new = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, + m_new = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, sc->rx_bd_mbuf_alloc_size); #endif @@ -5049,8 +5094,8 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, /* Handle any mapping errors. */ if (error) { - BCE_PRINTF("%s(%d): Error mapping mbuf into RX chain (%d)!\n", - __FILE__, __LINE__, error); + BCE_PRINTF("%s(%d): Error mapping mbuf into RX " + "chain (%d)!\n", __FILE__, __LINE__, error); sc->dma_map_addr_rx_failed_count++; m_freem(m_new); @@ -5078,11 +5123,11 @@ bce_get_rx_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, sc->rx_mbuf_ptr[*chain_prod] = m_new; sc->free_rx_bd -= nsegs; - DBRUNMSG(BCE_INSANE_RECV, + DBRUNMSG(BCE_INSANE_RECV, bce_dump_rx_mbuf_chain(sc, debug_chain_prod, nsegs)); DBPRINT(sc, BCE_EXTREME_RECV, "%s(exit): prod = 0x%04X, " - "chain_prod = 0x%04X, prod_bseq = 0x%08X\n", + "chain_prod = 0x%04X, prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod, *prod_bseq); bce_get_rx_buf_exit: @@ -5116,8 +5161,9 @@ bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, /* Make sure the inputs are valid. */ DBRUNIF((*prod_idx > MAX_PG_BD), - BCE_PRINTF("%s(%d): page producer out of range: 0x%04X > 0x%04X\n", - __FILE__, __LINE__, *prod_idx, (u16) MAX_PG_BD)); + BCE_PRINTF("%s(%d): page producer out of range: " + "0x%04X > 0x%04X\n", __FILE__, __LINE__, + *prod_idx, (u16) MAX_PG_BD)); DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): prod = 0x%04X, " "chain_prod = 0x%04X\n", __FUNCTION__, *prod, *prod_idx); @@ -5159,7 +5205,7 @@ bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, /* Map the mbuf cluster into device memory. */ map = sc->pg_mbuf_map[*prod_idx]; error = bus_dmamap_load(sc->pg_mbuf_tag, map, mtod(m_new, void *), - sc->pg_bd_mbuf_alloc_size, bce_dma_map_addr, + sc->pg_bd_mbuf_alloc_size, bce_dma_map_addr, &busaddr, BUS_DMA_NOWAIT); /* Handle any mapping errors. */ @@ -5191,7 +5237,7 @@ bce_get_pg_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, sc->pg_mbuf_ptr[*prod_idx] = m_new; sc->free_pg_bd--; - DBRUNMSG(BCE_INSANE_RECV, + DBRUNMSG(BCE_INSANE_RECV, bce_dump_pg_mbuf_chain(sc, debug_prod_idx, 1)); DBPRINT(sc, BCE_EXTREME_RECV, "%s(exit): prod = 0x%04X, " @@ -5222,19 +5268,19 @@ bce_init_tx_context(struct bce_softc *sc) if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { /* Set the CID type to support an L2 connection. */ - val = BCE_L2CTX_TX_TYPE_TYPE_L2_XI | + val = BCE_L2CTX_TX_TYPE_TYPE_L2_XI | BCE_L2CTX_TX_TYPE_SIZE_L2_XI; CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TYPE_XI, val); val = BCE_L2CTX_TX_CMD_TYPE_TYPE_L2_XI | (8 << 16); - CTX_WR(sc, GET_CID_ADDR(TX_CID), + CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_CMD_TYPE_XI, val); /* Point the hardware to the first page in the chain. */ val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]); - CTX_WR(sc, GET_CID_ADDR(TX_CID), + CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TBDR_BHADDR_HI_XI, val); val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]); - CTX_WR(sc, GET_CID_ADDR(TX_CID), + CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TBDR_BHADDR_LO_XI, val); } else { /* Set the CID type to support an L2 connection. */ @@ -5245,10 +5291,10 @@ bce_init_tx_context(struct bce_softc *sc) /* Point the hardware to the first page in the chain. */ val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]); - CTX_WR(sc, GET_CID_ADDR(TX_CID), + CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TBDR_BHADDR_HI, val); val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]); - CTX_WR(sc, GET_CID_ADDR(TX_CID), + CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TX_TBDR_BHADDR_LO, val); } @@ -5331,7 +5377,7 @@ bce_free_tx_chain(struct bce_softc *sc) for (i = 0; i < TOTAL_TX_BD; i++) { if (sc->tx_mbuf_ptr[i] != NULL) { if (sc->tx_mbuf_map[i] != NULL) - bus_dmamap_sync(sc->tx_mbuf_tag, + bus_dmamap_sync(sc->tx_mbuf_tag, sc->tx_mbuf_map[i], BUS_DMASYNC_POSTWRITE); m_freem(sc->tx_mbuf_ptr[i]); @@ -5349,7 +5395,7 @@ bce_free_tx_chain(struct bce_softc *sc) /* Check if we lost any mbufs in the process. */ DBRUNIF((sc->debug_tx_mbuf_alloc), BCE_PRINTF("%s(%d): Memory leak! Lost %d mbufs " - "from tx chain!\n", __FILE__, __LINE__, + "from tx chain!\n", __FILE__, __LINE__, sc->debug_tx_mbuf_alloc)); DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_SEND | BCE_VERBOSE_UNLOAD); @@ -5385,9 +5431,22 @@ bce_init_rx_context(struct bce_softc *sc) (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { u32 lo_water, hi_water; - lo_water = BCE_L2CTX_RX_LO_WATER_MARK_DEFAULT; + if (sc->bce_flags && BCE_USING_TX_FLOW_CONTROL) { + lo_water = BCE_L2CTX_RX_LO_WATER_MARK_DEFAULT; + } else { + lo_water = 0; + } + + if (lo_water >= USABLE_RX_BD) { + lo_water = 0; + } + hi_water = USABLE_RX_BD / 4; + if (hi_water <= lo_water) { + lo_water = 0; + } + lo_water /= BCE_L2CTX_RX_LO_WATER_MARK_SCALE; hi_water /= BCE_L2CTX_RX_HI_WATER_MARK_SCALE; @@ -5395,11 +5454,12 @@ bce_init_rx_context(struct bce_softc *sc) hi_water = 0xf; else if (hi_water == 0) lo_water = 0; + val |= (lo_water << BCE_L2CTX_RX_LO_WATER_MARK_SHIFT) | - (hi_water << BCE_L2CTX_RX_HI_WATER_MARK_SHIFT); + (hi_water << BCE_L2CTX_RX_HI_WATER_MARK_SHIFT); } - CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_CTX_TYPE, val); + CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_RX_CTX_TYPE, val); /* Setup the MQ BIN mapping for l2_ctx_host_bseq. */ if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || @@ -5453,9 +5513,9 @@ bce_init_rx_chain(struct bce_softc *sc) j = i + 1; /* Setup the chain page pointers. */ - rxbd->rx_bd_haddr_hi = + rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(sc->rx_bd_chain_paddr[j])); - rxbd->rx_bd_haddr_lo = + rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(sc->rx_bd_chain_paddr[j])); } @@ -5517,14 +5577,14 @@ bce_fill_rx_chain(struct bce_softc *sc) /* We should never end up pointing to a next page pointer. */ DBRUNIF(((prod & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE), - BCE_PRINTF("%s(): Invalid rx_prod value: 0x%04X\n", - __FUNCTION__, sc->rx_prod)); + BCE_PRINTF("%s(): Invalid rx_prod value: 0x%04X\n", + __FUNCTION__, sc->rx_prod)); /* Write the mailbox and tell the chip about the waiting rx_bd's. */ - REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BDIDX, - sc->rx_prod); - REG_WR(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_BSEQ, - sc->rx_prod_bseq); + REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + + BCE_L2MQ_RX_HOST_BDIDX, sc->rx_prod); + REG_WR(sc, MB_GET_CID_ADDR(RX_CID) + + BCE_L2MQ_RX_HOST_BSEQ, sc->rx_prod_bseq); DBEXIT(BCE_VERBOSE_RESET | BCE_EXTREME_RECV | BCE_VERBOSE_LOAD | BCE_VERBOSE_CTX); @@ -5548,7 +5608,7 @@ bce_free_rx_chain(struct bce_softc *sc) for (i = 0; i < TOTAL_RX_BD; i++) { if (sc->rx_mbuf_ptr[i] != NULL) { if (sc->rx_mbuf_map[i] != NULL) - bus_dmamap_sync(sc->rx_mbuf_tag, + bus_dmamap_sync(sc->rx_mbuf_tag, sc->rx_mbuf_map[i], BUS_DMASYNC_POSTREAD); m_freem(sc->rx_mbuf_ptr[i]); @@ -5560,7 +5620,7 @@ bce_free_rx_chain(struct bce_softc *sc) /* Clear each RX chain page. */ for (i = 0; i < RX_PAGES; i++) if (sc->rx_bd_chain[i] != NULL) { - bzero((char *)sc->rx_bd_chain[i], + bzero((char *)sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ); } @@ -5667,7 +5727,7 @@ bce_fill_pg_chain(struct bce_softc *sc) u16 prod, prod_idx; DBENTER(BCE_VERBOSE_RESET | BCE_EXTREME_RECV | BCE_VERBOSE_LOAD | - BCE_VERBOSE_CTX); + BCE_VERBOSE_CTX); /* Get the page chain prodcuer index. */ prod = sc->pg_prod; @@ -5686,18 +5746,18 @@ bce_fill_pg_chain(struct bce_softc *sc) sc->pg_prod = prod; DBRUNIF(((prod & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE), - BCE_PRINTF("%s(): Invalid pg_prod value: 0x%04X\n", - __FUNCTION__, sc->pg_prod)); + BCE_PRINTF("%s(): Invalid pg_prod value: 0x%04X\n", + __FUNCTION__, sc->pg_prod)); /* * Write the mailbox and tell the chip about * the new rx_bd's in the page chain. */ - REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + BCE_L2MQ_RX_HOST_PG_BDIDX, - sc->pg_prod); + REG_WR16(sc, MB_GET_CID_ADDR(RX_CID) + + BCE_L2MQ_RX_HOST_PG_BDIDX, sc->pg_prod); DBEXIT(BCE_VERBOSE_RESET | BCE_EXTREME_RECV | BCE_VERBOSE_LOAD | - BCE_VERBOSE_CTX); + BCE_VERBOSE_CTX); } @@ -5718,8 +5778,9 @@ bce_free_pg_chain(struct bce_softc *sc) for (i = 0; i < TOTAL_PG_BD; i++) { if (sc->pg_mbuf_ptr[i] != NULL) { if (sc->pg_mbuf_map[i] != NULL) - bus_dmamap_sync(sc->pg_mbuf_tag, sc->pg_mbuf_map[i], - BUS_DMASYNC_POSTREAD); + bus_dmamap_sync(sc->pg_mbuf_tag, + sc->pg_mbuf_map[i], + BUS_DMASYNC_POSTREAD); m_freem(sc->pg_mbuf_ptr[i]); sc->pg_mbuf_ptr[i] = NULL; DBRUN(sc->debug_pg_mbuf_alloc--); @@ -5734,8 +5795,8 @@ bce_free_pg_chain(struct bce_softc *sc) /* Check if we lost any mbufs in the process. */ DBRUNIF((sc->debug_pg_mbuf_alloc), - BCE_PRINTF("%s(): Memory leak! Lost %d mbufs from page chain!\n", - __FUNCTION__, sc->debug_pg_mbuf_alloc)); + BCE_PRINTF("%s(): Memory leak! Lost %d mbufs from page chain!\n", + __FUNCTION__, sc->debug_pg_mbuf_alloc)); DBEXIT(BCE_VERBOSE_RESET | BCE_VERBOSE_RECV | BCE_VERBOSE_UNLOAD); } @@ -5776,7 +5837,7 @@ bce_ifmedia_upd_locked(struct ifnet *ifp) struct bce_softc *sc = ifp->if_softc; struct mii_data *mii; - DBENTER(BCE_VERBOSE); + DBENTER(BCE_VERBOSE_PHY); BCE_LOCK_ASSERT(sc); @@ -5794,7 +5855,7 @@ bce_ifmedia_upd_locked(struct ifnet *ifp) mii_mediachg(mii); } - DBEXIT(BCE_VERBOSE); + DBEXIT(BCE_VERBOSE_PHY); } @@ -5810,7 +5871,7 @@ bce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) struct bce_softc *sc = ifp->if_softc; struct mii_data *mii; - DBENTER(BCE_VERBOSE); + DBENTER(BCE_VERBOSE_PHY); BCE_LOCK(sc); @@ -5822,7 +5883,7 @@ bce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) BCE_UNLOCK(sc); - DBEXIT(BCE_VERBOSE); + DBEXIT(BCE_VERBOSE_PHY); } @@ -5921,7 +5982,7 @@ bce_rx_intr(struct bce_softc *sc) #endif DBENTER(BCE_VERBOSE_RECV | BCE_VERBOSE_INTR); - DBRUN(sc->rx_interrupts++); + DBRUN(sc->interrupts_rx++); DBPRINT(sc, BCE_EXTREME_RECV, "%s(enter): rx_prod = 0x%04X, " "rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n", __FUNCTION__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq); @@ -5943,14 +6004,16 @@ bce_rx_intr(struct bce_softc *sc) /* Get working copies of the driver's view of the consumer indices. */ sw_rx_cons = sc->rx_cons; + #ifdef BCE_JUMBO_HDRSPLIT sw_pg_cons = sc->pg_cons; #endif /* Update some debug statistics counters */ DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark), - sc->rx_low_watermark = sc->free_rx_bd); - DBRUNIF((sc->free_rx_bd == sc->max_rx_bd), sc->rx_empty_count++); + sc->rx_low_watermark = sc->free_rx_bd); + DBRUNIF((sc->free_rx_bd == sc->max_rx_bd), + sc->rx_empty_count++); /* Scan through the receive chain as long as there is work to do */ /* ToDo: Consider setting a limit on the number of packets processed. */ @@ -5962,7 +6025,7 @@ bce_rx_intr(struct bce_softc *sc) sw_rx_cons_idx = RX_CHAIN_IDX(sw_rx_cons); /* Unmap the mbuf from DMA space. */ - bus_dmamap_sync(sc->rx_mbuf_tag, + bus_dmamap_sync(sc->rx_mbuf_tag, sc->rx_mbuf_map[sw_rx_cons_idx], BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc->rx_mbuf_tag, @@ -5975,7 +6038,7 @@ bce_rx_intr(struct bce_softc *sc) sc->free_rx_bd++; if(m0 == NULL) { - DBPRINT(sc, BCE_EXTREME_RECV, + DBPRINT(sc, BCE_EXTREME_RECV, "%s(): Oops! Empty mbuf pointer " "found in sc->rx_mbuf_ptr[0x%04X]!\n", __FUNCTION__, sw_rx_cons_idx); @@ -5983,20 +6046,23 @@ bce_rx_intr(struct bce_softc *sc) } /* - * Frames received on the NetXteme II are prepended with an - * l2_fhdr structure which provides status information about - * the received frame (including VLAN tags and checksum info). - * The frames are also automatically adjusted to align the IP - * header (i.e. two null bytes are inserted before the Ethernet - * header). As a result the data DMA'd by the controller into - * the mbuf is as follows: - * + * Frames received on the NetXteme II are prepended + * with an l2_fhdr structure which provides status + * information about the received frame (including + * VLAN tags and checksum info). The frames are + * also automatically adjusted to align the IP + * header (i.e. two null bytes are inserted before + * the Ethernet header). As a result the data + * DMA'd by the controller into the mbuf looks + * like this: + * * +---------+-----+---------------------+-----+ * | l2_fhdr | pad | packet data | FCS | * +---------+-----+---------------------+-----+ - * - * The l2_fhdr needs to be checked and skipped and the FCS needs - * to be stripped before sending the packet up the stack. + * + * The l2_fhdr needs to be checked and skipped and + * the FCS needs to be stripped before sending the + * packet up the stack. */ l2fhdr = mtod(m0, struct l2_fhdr *); @@ -6100,7 +6166,7 @@ bce_rx_intr(struct bce_softc *sc) m0->m_pkthdr.len = m0->m_len = pkt_len; } #else - /* Set the total packet length. */ + /* Set the total packet length. */ m0->m_pkthdr.len = m0->m_len = pkt_len; #endif @@ -6115,12 +6181,11 @@ bce_rx_intr(struct bce_softc *sc) m_print(m0, 128)); DBRUNIF(DB_RANDOMTRUE(l2fhdr_error_sim_control), - BCE_PRINTF("Simulating l2_fhdr status error.\n"); sc->l2fhdr_error_sim_count++; status = status | L2_FHDR_ERRORS_PHY_DECODE); /* Check the received frame for errors. */ - if (status & (L2_FHDR_ERRORS_BAD_CRC | + if (status & (L2_FHDR_ERRORS_BAD_CRC | L2_FHDR_ERRORS_PHY_DECODE | L2_FHDR_ERRORS_ALIGNMENT | L2_FHDR_ERRORS_TOO_SHORT | L2_FHDR_ERRORS_GIANT_FRAME)) { @@ -6144,12 +6209,12 @@ bce_rx_intr(struct bce_softc *sc) /* Check for an IP datagram. */ if (!(status & L2_FHDR_STATUS_SPLIT) && - (status & L2_FHDR_STATUS_IP_DATAGRAM)) { + (status & L2_FHDR_STATUS_IP_DATAGRAM)) { m0->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; - + DBRUN(sc->csum_offload_ip++); /* Check if the IP checksum is valid. */ if ((l2fhdr->l2_fhdr_ip_xsum ^ 0xffff) == 0) - m0->m_pkthdr.csum_flags |= + m0->m_pkthdr.csum_flags |= CSUM_IP_VALID; } @@ -6160,9 +6225,10 @@ bce_rx_intr(struct bce_softc *sc) /* Check for a good TCP/UDP checksum. */ if ((status & (L2_FHDR_ERRORS_TCP_XSUM | L2_FHDR_ERRORS_UDP_XSUM)) == 0) { + DBRUN(sc->csum_offload_tcp_udp++); m0->m_pkthdr.csum_data = l2fhdr->l2_fhdr_tcp_udp_xsum; - m0->m_pkthdr.csum_flags |= + m0->m_pkthdr.csum_flags |= (CSUM_DATA_VALID | CSUM_PSEUDO_HDR); } @@ -6234,12 +6300,13 @@ bce_rx_int_next_rx: hw_rx_cons = sc->hw_rx_cons = bce_get_hw_rx_cons(sc); } - /* No new packets to process. Refill the RX and page chains and exit. */ #ifdef BCE_JUMBO_HDRSPLIT + /* No new packets. Refill the page chain. */ sc->pg_cons = sw_pg_cons; bce_fill_pg_chain(sc); #endif + /* No new packets. Refill the RX chain. */ sc->rx_cons = sw_rx_cons; bce_fill_rx_chain(sc); @@ -6295,7 +6362,7 @@ bce_tx_intr(struct bce_softc *sc) u16 hw_tx_cons, sw_tx_cons, sw_tx_chain_cons; DBENTER(BCE_VERBOSE_SEND | BCE_VERBOSE_INTR); - DBRUN(sc->tx_interrupts++); + DBRUN(sc->interrupts_tx++); DBPRINT(sc, BCE_EXTREME_SEND, "%s(enter): tx_prod = 0x%04X, " "tx_cons = 0x%04X, tx_prod_bseq = 0x%08X\n", __FUNCTION__, sc->tx_prod, sc->tx_cons, sc->tx_prod_bseq); @@ -6306,7 +6373,7 @@ bce_tx_intr(struct bce_softc *sc) hw_tx_cons = sc->hw_tx_cons = bce_get_hw_tx_cons(sc); sw_tx_cons = sc->tx_cons; - /* Prevent speculative reads from getting ahead of the status block. */ + /* Prevent speculative reads of the status block. */ bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0, BUS_SPACE_BARRIER_READ); @@ -6354,7 +6421,7 @@ bce_tx_intr(struct bce_softc *sc) DBRUNMSG(BCE_INFO_SEND, BCE_PRINTF("%s(): Unloading map/freeing mbuf " - "from tx_bd[0x%04X]\n", __FUNCTION__, + "from tx_bd[0x%04X]\n", __FUNCTION__, sw_tx_chain_cons)); /* Unmap the mbuf. */ @@ -6496,9 +6563,9 @@ bce_init_locked(struct bce_softc *sc) * size. Be generous on the receive if we have room. */ #ifdef BCE_JUMBO_HDRSPLIT - if (ifp->if_mtu <= (sc->rx_bd_mbuf_data_len + + if (ifp->if_mtu <= (sc->rx_bd_mbuf_data_len + sc->pg_bd_mbuf_alloc_size)) - ether_mtu = sc->rx_bd_mbuf_data_len + + ether_mtu = sc->rx_bd_mbuf_data_len + sc->pg_bd_mbuf_alloc_size; #else if (ifp->if_mtu <= sc->rx_bd_mbuf_data_len) @@ -6509,7 +6576,7 @@ bce_init_locked(struct bce_softc *sc) ether_mtu += ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN; - DBPRINT(sc, BCE_INFO_MISC, "%s(): setting h/w mtu = %d\n", + DBPRINT(sc, BCE_INFO_MISC, "%s(): setting h/w mtu = %d\n", __FUNCTION__, ether_mtu); /* Program the mtu, enabling jumbo frame support if necessary. */ @@ -6522,7 +6589,7 @@ bce_init_locked(struct bce_softc *sc) DBPRINT(sc, BCE_INFO_LOAD, "%s(): rx_bd_mbuf_alloc_size = %d, rx_bce_mbuf_data_len = %d, " - "rx_bd_mbuf_align_pad = %d\n", __FUNCTION__, + "rx_bd_mbuf_align_pad = %d\n", __FUNCTION__, sc->rx_bd_mbuf_alloc_size, sc->rx_bd_mbuf_data_len, sc->rx_bd_mbuf_align_pad); @@ -6617,6 +6684,12 @@ bce_init(void *xsc) } +/****************************************************************************/ +/* Modifies an mbuf for TSO on the hardware. */ +/* */ +/* Returns: */ +/* Pointer to a modified mbuf. */ +/****************************************************************************/ static struct mbuf * bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags) { @@ -6627,8 +6700,9 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags) u16 etype; int hdr_len, ip_hlen = 0, tcp_hlen = 0, ip_len = 0; - DBRUN(sc->requested_tso_frames++); - /* Controller requires to monify mbuf chains. */ + DBRUN(sc->tso_frames_requested++); + + /* Controller may modify mbuf chains. */ if (M_WRITABLE(*m_head) == 0) { m = m_dup(*m_head, M_DONTWAIT); m_freem(*m_head); @@ -6639,6 +6713,7 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags) } *m_head = m; } + /* * For TSO the controller needs two pieces of info, * the MSS and the IP+TCP options length. @@ -6714,9 +6789,12 @@ bce_tso_setup(struct bce_softc *sc, struct mbuf **m_head, u16 *flags) /* Set the LSO flag in the TX BD */ *flags |= TX_BD_FLAGS_SW_LSO; + /* Set the length of IP + TCP options (in 32 bit words) */ *flags |= (((ip_hlen + tcp_hlen - sizeof(struct ip) - sizeof(struct tcphdr)) >> 2) << 8); + + DBRUN(sc->tso_frames_completed++); return (*m_head); } @@ -6743,22 +6821,24 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head) #ifdef BCE_DEBUG u16 debug_prod; #endif + int i, error, nsegs, rc = 0; DBENTER(BCE_VERBOSE_SEND); - DBPRINT(sc, BCE_INFO_SEND, - "%s(enter): tx_prod = 0x%04X, tx_chain_prod = %04X, " - "tx_prod_bseq = 0x%08X\n", - __FUNCTION__, sc->tx_prod, (u16) TX_CHAIN_IDX(sc->tx_prod), - sc->tx_prod_bseq); + + /* Make sure we have room in the TX chain. */ + if (sc->used_tx_bd >= sc->max_tx_bd) + goto bce_tx_encap_exit; /* Transfer any checksum offload flags to the bd. */ m0 = *m_head; if (m0->m_pkthdr.csum_flags) { if (m0->m_pkthdr.csum_flags & CSUM_TSO) { m0 = bce_tso_setup(sc, m_head, &flags); - if (m0 == NULL) + if (m0 == NULL) { + DBRUN(sc->tso_frames_failed++); goto bce_tx_encap_exit; + } mss = htole16(m0->m_pkthdr.tso_segsz); } else { if (m0->m_pkthdr.csum_flags & CSUM_IP) @@ -6785,8 +6865,7 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head) /* Check if the DMA mapping was successful */ if (error == EFBIG) { - - sc->fragmented_mbuf_count++; + sc->mbuf_frag_count++; /* Try to defrag the mbuf. */ m0 = m_collapse(*m_head, M_DONTWAIT, BCE_MAX_SEGMENTS); @@ -6801,8 +6880,8 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head) /* Defrag was successful, try mapping again */ *m_head = m0; - error = bus_dmamap_load_mbuf_sg(sc->tx_mbuf_tag, map, m0, - segs, &nsegs, BUS_DMA_NOWAIT); + error = bus_dmamap_load_mbuf_sg(sc->tx_mbuf_tag, + map, m0, segs, &nsegs, BUS_DMA_NOWAIT); /* Still getting an error after a defrag. */ if (error == ENOMEM) { @@ -6864,9 +6943,11 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head) txbd= &sc->tx_bd_chain[TX_PAGE(chain_prod)] [TX_IDX(chain_prod)]; - txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(segs[i].ds_addr)); - txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(segs[i].ds_addr)); - txbd->tx_bd_mss_nbytes = htole32(mss << 16) | + txbd->tx_bd_haddr_lo = + htole32(BCE_ADDR_LO(segs[i].ds_addr)); + txbd->tx_bd_haddr_hi = + htole32(BCE_ADDR_HI(segs[i].ds_addr)); + txbd->tx_bd_mss_nbytes = htole32(mss << 16) | htole16(segs[i].ds_len); txbd->tx_bd_vlan_tag = htole16(vlan_tag); txbd->tx_bd_flags = htole16(flags); @@ -6879,12 +6960,8 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head) /* Set the END flag on the last TX buffer descriptor. */ txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_END); - DBRUNMSG(BCE_EXTREME_SEND, bce_dump_tx_chain(sc, debug_prod, nsegs)); - - DBPRINT(sc, BCE_INFO_SEND, - "%s( end ): prod = 0x%04X, chain_prod = 0x%04X, " - "prod_bseq = 0x%08X\n", - __FUNCTION__, prod, chain_prod, prod_bseq); + DBRUNMSG(BCE_EXTREME_SEND, + bce_dump_tx_chain(sc, debug_prod, nsegs)); /* * Ensure that the mbuf pointer for this transmission @@ -6910,11 +6987,11 @@ bce_tx_encap(struct bce_softc *sc, struct mbuf **m_head) sc->tx_prod = prod; sc->tx_prod_bseq = prod_bseq; - DBPRINT(sc, BCE_INFO_SEND, - "%s(exit): prod = 0x%04X, chain_prod = %04X, " - "prod_bseq = 0x%08X\n", __FUNCTION__, - sc->tx_prod, (u16) TX_CHAIN_IDX(sc->tx_prod), - sc->tx_prod_bseq); + /* Tell the chip about the waiting TX frames. */ + REG_WR16(sc, MB_GET_CID_ADDR(TX_CID) + + BCE_L2MQ_TX_HOST_BIDX, sc->tx_prod); + REG_WR(sc, MB_GET_CID_ADDR(TX_CID) + + BCE_L2MQ_TX_HOST_BSEQ, sc->tx_prod_bseq); bce_tx_encap_exit: DBEXIT(BCE_VERBOSE_SEND); @@ -7006,23 +7083,6 @@ bce_start_locked(struct ifnet *ifp) DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): Inserted %d frames into " "send queue.\n", __FUNCTION__, count); - REG_WR(sc, BCE_MQ_COMMAND, REG_RD(sc, BCE_MQ_COMMAND) | - BCE_MQ_COMMAND_NO_MAP_ERROR); - - /* Write the mailbox and tell the chip about the waiting tx_bd's. */ - DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): MB_GET_CID_ADDR(TX_CID) = " - "0x%08X; BCE_L2MQ_TX_HOST_BIDX = 0x%08X, sc->tx_prod = 0x%04X\n", - __FUNCTION__, MB_GET_CID_ADDR(TX_CID), - BCE_L2MQ_TX_HOST_BIDX, sc->tx_prod); - REG_WR16(sc, MB_GET_CID_ADDR(TX_CID) + - BCE_L2MQ_TX_HOST_BIDX, sc->tx_prod); - - DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): MB_GET_CID_ADDR(TX_CID) = " - "0x%08X; BCE_L2MQ_TX_HOST_BSEQ = 0x%08X, sc->tx_prod_bseq = " - "0x%04X\n", __FUNCTION__, MB_GET_CID_ADDR(TX_CID), - BCE_L2MQ_TX_HOST_BSEQ, sc->tx_prod_bseq); - REG_WR(sc, MB_GET_CID_ADDR(TX_CID) + BCE_L2MQ_TX_HOST_BSEQ, sc->tx_prod_bseq); - /* Set the tx timeout. */ sc->watchdog_timer = BCE_TX_TIMEOUT; @@ -7103,19 +7163,19 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) /* No buffer allocation size changes are necessary. */ #else /* Recalculate our buffer allocation sizes. */ - if ((ifp->if_mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + + if ((ifp->if_mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ETHER_CRC_LEN) > MCLBYTES) { sc->rx_bd_mbuf_alloc_size = MJUM9BYTES; - sc->rx_bd_mbuf_align_pad = + sc->rx_bd_mbuf_align_pad = roundup2(MJUM9BYTES, 16) - MJUM9BYTES; - sc->rx_bd_mbuf_data_len = + sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size - sc->rx_bd_mbuf_align_pad; } else { sc->rx_bd_mbuf_alloc_size = MCLBYTES; - sc->rx_bd_mbuf_align_pad = + sc->rx_bd_mbuf_align_pad = roundup2(MCLBYTES, 16) - MCLBYTES; - sc->rx_bd_mbuf_data_len = + sc->rx_bd_mbuf_data_len = sc->rx_bd_mbuf_alloc_size - sc->rx_bd_mbuf_align_pad; } @@ -7161,7 +7221,7 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) /* Add/Delete multicast address */ case SIOCADDMULTI: case SIOCDELMULTI: - DBPRINT(sc, BCE_VERBOSE_MISC, + DBPRINT(sc, BCE_VERBOSE_MISC, "Received SIOCADDMULTI/SIOCDELMULTI\n"); BCE_LOCK(sc); @@ -7174,7 +7234,7 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) /* Set/Get Interface media */ case SIOCSIFMEDIA: case SIOCGIFMEDIA: - DBPRINT(sc, BCE_VERBOSE_MISC, + DBPRINT(sc, BCE_VERBOSE_MISC, "Received SIOCSIFMEDIA/SIOCGIFMEDIA\n"); mii = device_get_softc(sc->bce_miibus); @@ -7185,7 +7245,7 @@ bce_ioctl(struct ifnet *ifp, u_long command, caddr_t data) /* Set interface capability */ case SIOCSIFCAP: mask = ifr->ifr_reqcap ^ ifp->if_capenable; - DBPRINT(sc, BCE_INFO_MISC, + DBPRINT(sc, BCE_INFO_MISC, "Received SIOCSIFCAP = 0x%08X\n", (u32) mask); /* Toggle the TX checksum capabilities enable flag. */ @@ -7270,7 +7330,7 @@ bce_watchdog(struct bce_softc *sc) goto bce_watchdog_exit; BCE_PRINTF("%s(%d): Watchdog timeout occurred, resetting!\n", - __FILE__, __LINE__); + __FILE__, __LINE__); DBRUNMSG(BCE_INFO, bce_dump_driver_state(sc); @@ -7336,7 +7396,7 @@ bce_intr(void *xsc) * interrupt then there's nothing to do. */ if ((sc->status_block->status_idx == sc->last_status_idx) && - (REG_RD(sc, BCE_PCICFG_MISC_STATUS) & + (REG_RD(sc, BCE_PCICFG_MISC_STATUS) & BCE_PCICFG_MISC_STATUS_INTA_VALUE)) { DBPRINT(sc, BCE_VERBOSE_INTR, "%s(): Spurious interrupt.\n", __FUNCTION__); @@ -7361,17 +7421,17 @@ bce_intr(void *xsc) BCE_PRINTF("Simulating unexpected status attention " "bit set."); sc->unexpected_attention_sim_count++; - status_attn_bits = status_attn_bits | + status_attn_bits = status_attn_bits | STATUS_ATTN_BITS_PARITY_ERROR); /* Was it a link change interrupt? */ if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != - (sc->status_block->status_attn_bits_ack & + (sc->status_block->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE)) { bce_phy_intr(sc); /* Clear transient updates during link state change. */ - REG_WR(sc, BCE_HC_COMMAND, sc->hc_command | + REG_WR(sc, BCE_HC_COMMAND, sc->hc_command | BCE_HC_COMMAND_COAL_NOW_WO_INT); REG_RD(sc, BCE_HC_COMMAND); } @@ -7384,7 +7444,7 @@ bce_intr(void *xsc) sc->unexpected_attention_count++; BCE_PRINTF("%s(%d): Fatal attention detected: " - "0x%08X\n", __FILE__, __LINE__, + "0x%08X\n", __FILE__, __LINE__, sc->status_block->status_attn_bits); DBRUNMSG(BCE_FATAL, @@ -7420,7 +7480,7 @@ bce_intr(void *xsc) hw_rx_cons = bce_get_hw_rx_cons(sc); hw_tx_cons = bce_get_hw_tx_cons(sc); - if ((hw_rx_cons == sc->hw_rx_cons) && + if ((hw_rx_cons == sc->hw_rx_cons) && (hw_tx_cons == sc->hw_tx_cons)) break; @@ -7433,7 +7493,7 @@ bce_intr(void *xsc) bce_enable_intr(sc, 0); /* Handle any frames that arrived while handling the interrupt. */ - if (ifp->if_drv_flags & IFF_DRV_RUNNING && + if (ifp->if_drv_flags & IFF_DRV_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) bce_start_locked(ifp); @@ -7560,7 +7620,7 @@ bce_stats_update(struct bce_softc *sc) */ if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) && !(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0)) - ifp->if_oerrors += + ifp->if_oerrors += (u_long) stats->stat_Dot3StatsCarrierSenseErrors; /* @@ -7799,25 +7859,28 @@ bce_pulse(void *xsc) sc->bc_state = bce_shmem_rd(sc, BCE_BC_STATE_CONDITION); /* Report whether the bootcode still knows the driver is running. */ - if (sc->bce_drv_cardiac_arrest == FALSE) { - if (!(sc->bc_state & BCE_CONDITION_DRV_PRESENT)) { - sc->bce_drv_cardiac_arrest = TRUE; - BCE_PRINTF("%s(): Bootcode lost the driver pulse! " - "(bc_state = 0x%08X)\n", __FUNCTION__, - sc->bc_state); - } - } else { - /* - * Not supported by all bootcode versions. - * (v5.0.11+ and v5.2.1+) Older bootcode - * will require the driver to reset the - * controller to clear this condition. - */ - if (sc->bc_state & BCE_CONDITION_DRV_PRESENT) { - sc->bce_drv_cardiac_arrest = FALSE; - BCE_PRINTF("%s(): Bootcode found the driver pulse! " - "(bc_state = 0x%08X)\n", __FUNCTION__, - sc->bc_state); + if (bootverbose) { + if (sc->bce_drv_cardiac_arrest == FALSE) { + if (!(sc->bc_state & BCE_CONDITION_DRV_PRESENT)) { + sc->bce_drv_cardiac_arrest = TRUE; + BCE_PRINTF("%s(): Warning: bootcode " + "thinks driver is absent! " + "(bc_state = 0x%08X)\n", + __FUNCTION__, sc->bc_state); + } + } else { + /* + * Not supported by all bootcode versions. + * (v5.0.11+ and v5.2.1+) Older bootcode + * will require the driver to reset the + * controller to clear this condition. + */ + if (sc->bc_state & BCE_CONDITION_DRV_PRESENT) { + sc->bce_drv_cardiac_arrest = FALSE; + BCE_PRINTF("%s(): Bootcode found the " + "driver pulse! (bc_state = 0x%08X)\n", + __FUNCTION__, sc->bc_state); + } } } @@ -7874,7 +7937,7 @@ bce_tick(void *xsc) /* Check if the link has come up. */ if ((mii->mii_media_status & IFM_ACTIVE) && (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)) { - DBPRINT(sc, BCE_VERBOSE_MISC, + DBPRINT(sc, BCE_VERBOSE_MISC, "%s(): Link up!\n", __FUNCTION__); sc->bce_link_up = TRUE; if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T || @@ -8011,6 +8074,62 @@ bce_sysctl_stats_block(SYSCTL_HANDLER_ARGS) /****************************************************************************/ +/* Allows the stat counters to be cleared without unloading/reloading the */ +/* driver. */ +/* */ +/* Returns: */ +/* 0 for success, positive value for failure. */ +/****************************************************************************/ +static int +bce_sysctl_stats_clear(SYSCTL_HANDLER_ARGS) +{ + int error; + int result; + struct bce_softc *sc; + + result = -1; + error = sysctl_handle_int(oidp, &result, 0, req); + + if (error || !req->newptr) + return (error); + + if (result == 1) { + sc = (struct bce_softc *)arg1; + + /* Clear the internal H/W statistics counters. */ + REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW); + + /* Reset the driver maintained statistics. */ + sc->interrupts_rx = + sc->interrupts_tx = 0; + sc->tso_frames_requested = + sc->tso_frames_completed = + sc->tso_frames_failed = 0; + sc->rx_empty_count = + sc->tx_full_count = 0; + sc->rx_low_watermark = USABLE_RX_BD; + sc->tx_hi_watermark = 0; + sc->l2fhdr_error_count = + sc->l2fhdr_error_sim_count = 0; + sc->mbuf_alloc_failed_count = + sc->mbuf_alloc_failed_sim_count = 0; + sc->dma_map_addr_rx_failed_count = + sc->dma_map_addr_tx_failed_count = 0; + sc->mbuf_frag_count = 0; + sc->csum_offload_tcp_udp = + sc->csum_offload_ip = 0; + sc->vlan_tagged_frames_rcvd = + sc->vlan_tagged_frames_stripped = 0; + + /* Clear firmware maintained statistics. */ + REG_WR_IND(sc, 0x120084, 0); + } + + return error; +} + + +/****************************************************************************/ /* Allows the bootcode state to be dumped through the sysctl interface. */ /* */ /* Returns: */ @@ -8252,8 +8371,7 @@ static int bce_sysctl_dump_ctx(SYSCTL_HANDLER_ARGS) { struct bce_softc *sc; - int error; - u16 result; + int error, result; result = -1; error = sysctl_handle_int(oidp, &result, 0, req); @@ -8352,8 +8470,8 @@ bce_add_sysctls(struct bce_softc *sc) 0, "Number of mbuf allocation failures"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, - "fragmented_mbuf_count", - CTLFLAG_RD, &sc->fragmented_mbuf_count, + "mbuf_frag_count", + CTLFLAG_RD, &sc->mbuf_frag_count, 0, "Number of fragmented mbufs"); #ifdef BCE_DEBUG @@ -8367,7 +8485,7 @@ bce_add_sysctls(struct bce_softc *sc) "dma_map_addr_failed_sim_count", CTLFLAG_RD, &sc->dma_map_addr_failed_sim_count, 0, "Number of simulated DMA mapping failures"); - + #endif SYSCTL_ADD_INT(ctx, children, OID_AUTO, @@ -8424,18 +8542,48 @@ bce_add_sysctls(struct bce_softc *sc) 0, "Number of times the TX chain was full"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, - "requested_tso_frames", - CTLFLAG_RD, &sc->requested_tso_frames, - 0, "Number of TSO frames received"); + "tso_frames_requested", + CTLFLAG_RD, &sc->tso_frames_requested, + 0, "Number of TSO frames requested"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "tso_frames_completed", + CTLFLAG_RD, &sc->tso_frames_completed, + 0, "Number of TSO frames completed"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "tso_frames_failed", + CTLFLAG_RD, &sc->tso_frames_failed, + 0, "Number of TSO frames failed"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "csum_offload_ip", + CTLFLAG_RD, &sc->csum_offload_ip, + 0, "Number of IP checksum offload frames"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "csum_offload_tcp_udp", + CTLFLAG_RD, &sc->csum_offload_tcp_udp, + 0, "Number of TCP/UDP checksum offload frames"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "vlan_tagged_frames_rcvd", + CTLFLAG_RD, &sc->vlan_tagged_frames_rcvd, + 0, "Number of VLAN tagged frames received"); + + SYSCTL_ADD_INT(ctx, children, OID_AUTO, + "vlan_tagged_frames_stripped", + CTLFLAG_RD, &sc->vlan_tagged_frames_stripped, + 0, "Number of VLAN tagged frames stripped"); SYSCTL_ADD_UINT(ctx, children, OID_AUTO, - "rx_interrupts", - CTLFLAG_RD, &sc->rx_interrupts, + "interrupts_rx", + CTLFLAG_RD, &sc->interrupts_rx, 0, "Number of RX interrupts"); SYSCTL_ADD_UINT(ctx, children, OID_AUTO, - "tx_interrupts", - CTLFLAG_RD, &sc->tx_interrupts, + "interrupts_tx", + CTLFLAG_RD, &sc->interrupts_tx, 0, "Number of TX interrupts"); #endif @@ -8730,12 +8878,17 @@ bce_add_sysctls(struct bce_softc *sc) SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "status_block", CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, - bce_sysctl_status_block, "I", "Status block"); + bce_sysctl_status_block, "I", "Dump status block"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "stats_block", CTLTYPE_INT | CTLFLAG_RW, (void *)sc, 0, - bce_sysctl_stats_block, "I", "Stats block"); + bce_sysctl_stats_block, "I", "Dump statistics block"); + + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, + "stats_clear", CTLTYPE_INT | CTLFLAG_RW, + (void *)sc, 0, + bce_sysctl_stats_clear, "I", "Clear statistics block"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "bc_state", CTLTYPE_INT | CTLFLAG_RW, @@ -8882,18 +9035,18 @@ bce_dump_enet(struct bce_softc *sc, struct mbuf *m) switch (ip->ip_p) { case IPPROTO_TCP: th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); - BCE_PRINTF("-tcp: dest = %d, src = %d, hlen = %d bytes, " - "flags = 0x%b, csum = 0x%04X\n", - ntohs(th->th_dport), ntohs(th->th_sport), - (th->th_off << 2), th->th_flags, + BCE_PRINTF("-tcp: dest = %d, src = %d, hlen = " + "%d bytes, flags = 0x%b, csum = 0x%04X\n", + ntohs(th->th_dport), ntohs(th->th_sport), + (th->th_off << 2), th->th_flags, "\20\10CWR\07ECE\06URG\05ACK\04PSH\03RST" "\02SYN\01FIN", ntohs(th->th_sum)); break; case IPPROTO_UDP: uh = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); BCE_PRINTF("-udp: dest = %d, src = %d, len = %d " - "bytes, csum = 0x%04X\n", ntohs(uh->uh_dport), - ntohs(uh->uh_sport), ntohs(uh->uh_ulen), + "bytes, csum = 0x%04X\n", ntohs(uh->uh_dport), + ntohs(uh->uh_sport), ntohs(uh->uh_ulen), ntohs(uh->uh_sum)); break; case IPPROTO_ICMP: @@ -8960,10 +9113,10 @@ bce_dump_mbuf(struct bce_softc *sc, struct mbuf *m) if (mp->m_flags & M_PKTHDR) { BCE_PRINTF("- m_pkthdr: len = %d, flags = 0x%b, " - "csum_flags = %b\n", mp->m_pkthdr.len, + "csum_flags = %b\n", mp->m_pkthdr.len, mp->m_flags, "\20\12M_BCAST\13M_MCAST\14M_FRAG" "\15M_FIRSTFRAG\16M_LASTFRAG\21M_VLANTAG" - "\22M_PROMISC\23M_NOFREE", + "\22M_PROMISC\23M_NOFREE", mp->m_pkthdr.csum_flags, "\20\1CSUM_IP\2CSUM_TCP\3CSUM_UDP\4CSUM_IP_FRAGS" "\5CSUM_FRAGMENT\6CSUM_TSO\11CSUM_IP_CHECKED" @@ -8995,7 +9148,7 @@ bce_dump_mbuf(struct bce_softc *sc, struct mbuf *m) printf("EXT_DISPOSABLE\n"); break; case EXT_EXTREF: printf("EXT_EXTREF\n"); break; - default: + default: printf("UNKNOWN\n"); } } @@ -9116,96 +9269,96 @@ bce_dump_txbd(struct bce_softc *sc, int idx, struct tx_bd *txbd) else if ((idx & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE) /* TX Chain page pointer. */ BCE_PRINTF("tx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page " - "pointer\n", idx, txbd->tx_bd_haddr_hi, + "pointer\n", idx, txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo); else { /* Normal tx_bd entry. */ BCE_PRINTF("tx_bd[0x%04X]: haddr = 0x%08X:%08X, " "mss_nbytes = 0x%08X, vlan tag = 0x%04X, flags = " - "0x%04X (", idx, txbd->tx_bd_haddr_hi, - txbd->tx_bd_haddr_lo, txbd->tx_bd_mss_nbytes, + "0x%04X (", idx, txbd->tx_bd_haddr_hi, + txbd->tx_bd_haddr_lo, txbd->tx_bd_mss_nbytes, txbd->tx_bd_vlan_tag, txbd->tx_bd_flags); if (txbd->tx_bd_flags & TX_BD_FLAGS_CONN_FAULT) { - if (i>0) - printf("|"); - printf("CONN_FAULT"); + if (i>0) + printf("|"); + printf("CONN_FAULT"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_TCP_UDP_CKSUM) { - if (i>0) - printf("|"); - printf("TCP_UDP_CKSUM"); + if (i>0) + printf("|"); + printf("TCP_UDP_CKSUM"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_IP_CKSUM) { - if (i>0) - printf("|"); - printf("IP_CKSUM"); + if (i>0) + printf("|"); + printf("IP_CKSUM"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_VLAN_TAG) { - if (i>0) - printf("|"); - printf("VLAN"); + if (i>0) + printf("|"); + printf("VLAN"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_COAL_NOW) { - if (i>0) - printf("|"); - printf("COAL_NOW"); + if (i>0) + printf("|"); + printf("COAL_NOW"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_DONT_GEN_CRC) { - if (i>0) - printf("|"); - printf("DONT_GEN_CRC"); + if (i>0) + printf("|"); + printf("DONT_GEN_CRC"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_START) { - if (i>0) - printf("|"); - printf("START"); + if (i>0) + printf("|"); + printf("START"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_END) { - if (i>0) - printf("|"); - printf("END"); + if (i>0) + printf("|"); + printf("END"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_LSO) { - if (i>0) - printf("|"); - printf("LSO"); + if (i>0) + printf("|"); + printf("LSO"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_OPTION_WORD) { - if (i>0) - printf("|"); - printf("SW_OPTION=%d", ((txbd->tx_bd_flags & + if (i>0) + printf("|"); + printf("SW_OPTION=%d", ((txbd->tx_bd_flags & TX_BD_FLAGS_SW_OPTION_WORD) >> 8)); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_FLAGS) { - if (i>0) - printf("|"); - printf("SW_FLAGS"); + if (i>0) + printf("|"); + printf("SW_FLAGS"); i++; } if (txbd->tx_bd_flags & TX_BD_FLAGS_SW_SNAP) { - if (i>0) - printf("|"); + if (i>0) + printf("|"); printf("SNAP)"); } else { printf(")\n"); @@ -9229,13 +9382,13 @@ bce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd) else if ((idx & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE) /* RX Chain page pointer. */ BCE_PRINTF("rx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page " - "pointer\n", idx, rxbd->rx_bd_haddr_hi, + "pointer\n", idx, rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo); else /* Normal rx_bd entry. */ BCE_PRINTF("rx_bd[0x%04X]: haddr = 0x%08X:%08X, nbytes = " - "0x%08X, flags = 0x%08X\n", idx, rxbd->rx_bd_haddr_hi, - rxbd->rx_bd_haddr_lo, rxbd->rx_bd_len, + "0x%08X, flags = 0x%08X\n", idx, rxbd->rx_bd_haddr_hi, + rxbd->rx_bd_haddr_lo, rxbd->rx_bd_len, rxbd->rx_bd_flags); } @@ -9325,57 +9478,57 @@ bce_dump_ctx(struct bce_softc *sc, u16 cid) "index\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_RX_NX_BDIDX)); BCE_PRINTF(" 0x%08X - (L2CTX_RX_HOST_PG_BDIDX) host page " - "producer index\n", CTX_RD(sc, GET_CID_ADDR(cid), + "producer index\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_RX_HOST_PG_BDIDX)); BCE_PRINTF(" 0x%08X - (L2CTX_RX_PG_BUF_SIZE) host rx_bd/page " - "buffer size\n", CTX_RD(sc, GET_CID_ADDR(cid), + "buffer size\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_RX_PG_BUF_SIZE)); BCE_PRINTF(" 0x%08X - (L2CTX_RX_NX_PG_BDHADDR_HI) h/w page " - "chain address\n", CTX_RD(sc, GET_CID_ADDR(cid), + "chain address\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_RX_NX_PG_BDHADDR_HI)); BCE_PRINTF(" 0x%08X - (L2CTX_RX_NX_PG_BDHADDR_LO) h/w page " - "chain address\n", CTX_RD(sc, GET_CID_ADDR(cid), + "chain address\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_RX_NX_PG_BDHADDR_LO)); BCE_PRINTF(" 0x%08X - (L2CTX_RX_NX_PG_BDIDX) h/w page " - "consumer index\n", CTX_RD(sc, GET_CID_ADDR(cid), + "consumer index\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_RX_NX_PG_BDIDX)); } else if (cid == TX_CID) { if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) { BCE_PRINTF(" 0x%08X - (L2CTX_TX_TYPE_XI) ctx type\n", - CTX_RD(sc, GET_CID_ADDR(cid), + CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_TYPE_XI)); BCE_PRINTF(" 0x%08X - (L2CTX_CMD_TX_TYPE_XI) ctx " - "cmd\n", CTX_RD(sc, GET_CID_ADDR(cid), + "cmd\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_CMD_TYPE_XI)); BCE_PRINTF(" 0x%08X - (L2CTX_TX_TBDR_BDHADDR_HI_XI) " - "h/w buffer descriptor address\n", - CTX_RD(sc, GET_CID_ADDR(cid), + "h/w buffer descriptor address\n", + CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_TBDR_BHADDR_HI_XI)); BCE_PRINTF(" 0x%08X - (L2CTX_TX_TBDR_BHADDR_LO_XI) " - "h/w buffer descriptor address\n", + "h/w buffer descriptor address\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_TBDR_BHADDR_LO_XI)); BCE_PRINTF(" 0x%08X - (L2CTX_TX_HOST_BIDX_XI) " - "host producer index\n", + "host producer index\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_HOST_BIDX_XI)); BCE_PRINTF(" 0x%08X - (L2CTX_TX_HOST_BSEQ_XI) " - "host byte sequence\n", + "host byte sequence\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_HOST_BSEQ_XI)); } else { BCE_PRINTF(" 0x%08X - (L2CTX_TX_TYPE) ctx type\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_TYPE)); BCE_PRINTF(" 0x%08X - (L2CTX_TX_CMD_TYPE) ctx cmd\n", - CTX_RD(sc, GET_CID_ADDR(cid), + CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_CMD_TYPE)); BCE_PRINTF(" 0x%08X - (L2CTX_TX_TBDR_BDHADDR_HI) " - "h/w buffer descriptor address\n", + "h/w buffer descriptor address\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_TBDR_BHADDR_HI)); BCE_PRINTF(" 0x%08X - (L2CTX_TX_TBDR_BHADDR_LO) " - "h/w buffer descriptor address\n", + "h/w buffer descriptor address\n", CTX_RD(sc, GET_CID_ADDR(cid), BCE_L2CTX_TX_TBDR_BHADDR_LO)); BCE_PRINTF(" 0x%08X - (L2CTX_TX_HOST_BIDX) host " @@ -9605,8 +9758,8 @@ bce_dump_ftqs(struct bce_softc *sc) if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5709) || (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5716)) - val = val | - (BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI << + val = val | + (BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI << 24); REG_WR(sc, BCE_HC_STAT_GEN_SEL_0, val); @@ -10020,11 +10173,11 @@ bce_dump_driver_state(struct bce_softc *sc) BCE_PRINTF(" 0x%08X - (sc->interrupts_generated) " "h/w intrs\n", sc->interrupts_generated); - BCE_PRINTF(" 0x%08X - (sc->rx_interrupts) " - "rx interrupts handled\n", sc->rx_interrupts); + BCE_PRINTF(" 0x%08X - (sc->interrupts_rx) " + "rx interrupts handled\n", sc->interrupts_rx); - BCE_PRINTF(" 0x%08X - (sc->tx_interrupts) " - "tx interrupts handled\n", sc->tx_interrupts); + BCE_PRINTF(" 0x%08X - (sc->interrupts_tx) " + "tx interrupts handled\n", sc->interrupts_tx); BCE_PRINTF(" 0x%08X - (sc->phy_interrupts) " "phy interrupts handled\n", sc->phy_interrupts); @@ -10122,15 +10275,15 @@ bce_dump_hw_state(struct bce_softc *sc) val, BCE_MISC_ENABLE_STATUS_BITS); val = REG_RD(sc, BCE_DMA_STATUS); - BCE_PRINTF("0x%08X - (0x%06X) dma_status\n", + BCE_PRINTF("0x%08X - (0x%06X) dma_status\n", val, BCE_DMA_STATUS); val = REG_RD(sc, BCE_CTX_STATUS); - BCE_PRINTF("0x%08X - (0x%06X) ctx_status\n", + BCE_PRINTF("0x%08X - (0x%06X) ctx_status\n", val, BCE_CTX_STATUS); val = REG_RD(sc, BCE_EMAC_STATUS); - BCE_PRINTF("0x%08X - (0x%06X) emac_status\n", + BCE_PRINTF("0x%08X - (0x%06X) emac_status\n", val, BCE_EMAC_STATUS); val = REG_RD(sc, BCE_RPM_STATUS); @@ -10139,16 +10292,16 @@ bce_dump_hw_state(struct bce_softc *sc) /* ToDo: Create a #define for this constant. */ val = REG_RD(sc, 0x2004); - BCE_PRINTF("0x%08X - (0x%06X) rlup_status\n", + BCE_PRINTF("0x%08X - (0x%06X) rlup_status\n", val, 0x2004); val = REG_RD(sc, BCE_RV2P_STATUS); - BCE_PRINTF("0x%08X - (0x%06X) rv2p_status\n", + BCE_PRINTF("0x%08X - (0x%06X) rv2p_status\n", val, BCE_RV2P_STATUS); /* ToDo: Create a #define for this constant. */ val = REG_RD(sc, 0x2c04); - BCE_PRINTF("0x%08X - (0x%06X) rdma_status\n", + BCE_PRINTF("0x%08X - (0x%06X) rdma_status\n", val, 0x2c04); val = REG_RD(sc, BCE_TBDR_STATUS); @@ -10156,7 +10309,7 @@ bce_dump_hw_state(struct bce_softc *sc) val, BCE_TBDR_STATUS); val = REG_RD(sc, BCE_TDMA_STATUS); - BCE_PRINTF("0x%08X - (0x%06X) tdma_status\n", + BCE_PRINTF("0x%08X - (0x%06X) tdma_status\n", val, BCE_TDMA_STATUS); val = REG_RD(sc, BCE_HC_STATUS); @@ -10164,27 +10317,27 @@ bce_dump_hw_state(struct bce_softc *sc) val, BCE_HC_STATUS); val = REG_RD_IND(sc, BCE_TXP_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_state\n", val, BCE_TXP_CPU_STATE); val = REG_RD_IND(sc, BCE_TPAT_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_state\n", val, BCE_TPAT_CPU_STATE); val = REG_RD_IND(sc, BCE_RXP_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_state\n", val, BCE_RXP_CPU_STATE); val = REG_RD_IND(sc, BCE_COM_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) com_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) com_cpu_state\n", val, BCE_COM_CPU_STATE); val = REG_RD_IND(sc, BCE_MCP_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) mcp_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) mcp_cpu_state\n", val, BCE_MCP_CPU_STATE); val = REG_RD_IND(sc, BCE_CP_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_state\n", val, BCE_CP_CPU_STATE); BCE_PRINTF( @@ -10306,15 +10459,15 @@ bce_dump_txp_state(struct bce_softc *sc, int regs) BCE_PRINTF("Firmware version - %s\n", (char *) fw_version); val = REG_RD_IND(sc, BCE_TXP_CPU_MODE); - BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_mode\n", + BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_mode\n", val, BCE_TXP_CPU_MODE); val = REG_RD_IND(sc, BCE_TXP_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_state\n", val, BCE_TXP_CPU_STATE); val = REG_RD_IND(sc, BCE_TXP_CPU_EVENT_MASK); - BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_event_mask\n", + BCE_PRINTF("0x%08X - (0x%06X) txp_cpu_event_mask\n", val, BCE_TXP_CPU_EVENT_MASK); if (regs) { @@ -10327,8 +10480,8 @@ bce_dump_txp_state(struct bce_softc *sc, int regs) /* Skip the big blank spaces */ if (i < 0x454000 && i > 0x5ffff) BCE_PRINTF("0x%04X: 0x%08X 0x%08X " - "0x%08X 0x%08X\n", i, - REG_RD_IND(sc, i), + "0x%08X 0x%08X\n", i, + REG_RD_IND(sc, i), REG_RD_IND(sc, i + 0x4), REG_RD_IND(sc, i + 0x8), REG_RD_IND(sc, i + 0xC)); @@ -10366,15 +10519,15 @@ bce_dump_rxp_state(struct bce_softc *sc, int regs) BCE_PRINTF("Firmware version - %s\n", (char *) fw_version); val = REG_RD_IND(sc, BCE_RXP_CPU_MODE); - BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_mode\n", + BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_mode\n", val, BCE_RXP_CPU_MODE); val = REG_RD_IND(sc, BCE_RXP_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_state\n", val, BCE_RXP_CPU_STATE); val = REG_RD_IND(sc, BCE_RXP_CPU_EVENT_MASK); - BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_event_mask\n", + BCE_PRINTF("0x%08X - (0x%06X) rxp_cpu_event_mask\n", val, BCE_RXP_CPU_EVENT_MASK); if (regs) { @@ -10387,10 +10540,10 @@ bce_dump_rxp_state(struct bce_softc *sc, int regs) /* Skip the big blank sapces */ if (i < 0xc5400 && i > 0xdffff) BCE_PRINTF("0x%04X: 0x%08X 0x%08X " - "0x%08X 0x%08X\n", i, - REG_RD_IND(sc, i), + "0x%08X 0x%08X\n", i, + REG_RD_IND(sc, i), REG_RD_IND(sc, i + 0x4), - REG_RD_IND(sc, i + 0x8), + REG_RD_IND(sc, i + 0x8), REG_RD_IND(sc, i + 0xC)); } } @@ -10426,15 +10579,15 @@ bce_dump_tpat_state(struct bce_softc *sc, int regs) BCE_PRINTF("Firmware version - %s\n", (char *) fw_version); val = REG_RD_IND(sc, BCE_TPAT_CPU_MODE); - BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_mode\n", + BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_mode\n", val, BCE_TPAT_CPU_MODE); val = REG_RD_IND(sc, BCE_TPAT_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_state\n", val, BCE_TPAT_CPU_STATE); val = REG_RD_IND(sc, BCE_TPAT_CPU_EVENT_MASK); - BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_event_mask\n", + BCE_PRINTF("0x%08X - (0x%06X) tpat_cpu_event_mask\n", val, BCE_TPAT_CPU_EVENT_MASK); if (regs) { @@ -10448,9 +10601,9 @@ bce_dump_tpat_state(struct bce_softc *sc, int regs) if (i < 0x854000 && i > 0x9ffff) BCE_PRINTF("0x%04X: 0x%08X 0x%08X " "0x%08X 0x%08X\n", i, - REG_RD_IND(sc, i), + REG_RD_IND(sc, i), REG_RD_IND(sc, i + 0x4), - REG_RD_IND(sc, i + 0x8), + REG_RD_IND(sc, i + 0x8), REG_RD_IND(sc, i + 0xC)); } } @@ -10486,11 +10639,11 @@ bce_dump_cp_state(struct bce_softc *sc, int regs) BCE_PRINTF("Firmware version - %s\n", (char *) fw_version); val = REG_RD_IND(sc, BCE_CP_CPU_MODE); - BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_mode\n", + BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_mode\n", val, BCE_CP_CPU_MODE); val = REG_RD_IND(sc, BCE_CP_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) cp_cpu_state\n", val, BCE_CP_CPU_STATE); val = REG_RD_IND(sc, BCE_CP_CPU_EVENT_MASK); @@ -10507,10 +10660,10 @@ bce_dump_cp_state(struct bce_softc *sc, int regs) /* Skip the big blank spaces */ if (i < 0x185400 && i > 0x19ffff) BCE_PRINTF("0x%04X: 0x%08X 0x%08X " - "0x%08X 0x%08X\n", i, - REG_RD_IND(sc, i), + "0x%08X 0x%08X\n", i, + REG_RD_IND(sc, i), REG_RD_IND(sc, i + 0x4), - REG_RD_IND(sc, i + 0x8), + REG_RD_IND(sc, i + 0x8), REG_RD_IND(sc, i + 0xC)); } } @@ -10546,11 +10699,11 @@ bce_dump_com_state(struct bce_softc *sc, int regs) BCE_PRINTF("Firmware version - %s\n", (char *) fw_version); val = REG_RD_IND(sc, BCE_COM_CPU_MODE); - BCE_PRINTF("0x%08X - (0x%06X) com_cpu_mode\n", + BCE_PRINTF("0x%08X - (0x%06X) com_cpu_mode\n", val, BCE_COM_CPU_MODE); val = REG_RD_IND(sc, BCE_COM_CPU_STATE); - BCE_PRINTF("0x%08X - (0x%06X) com_cpu_state\n", + BCE_PRINTF("0x%08X - (0x%06X) com_cpu_state\n", val, BCE_COM_CPU_STATE); val = REG_RD_IND(sc, BCE_COM_CPU_EVENT_MASK); @@ -10565,8 +10718,8 @@ bce_dump_com_state(struct bce_softc *sc, int regs) for (int i = BCE_COM_CPU_MODE; i < 0x1053e8; i += 0x10) { BCE_PRINTF("0x%04X: 0x%08X 0x%08X " - "0x%08X 0x%08X\n", i, - REG_RD_IND(sc, i), + "0x%08X 0x%08X\n", i, + REG_RD_IND(sc, i), REG_RD_IND(sc, i + 0x4), REG_RD_IND(sc, i + 0x8), REG_RD_IND(sc, i + 0xC)); @@ -10605,17 +10758,17 @@ bce_dump_rv2p_state(struct bce_softc *sc) val = 0x00000001; REG_WR_IND(sc, BCE_RV2P_PROC1_ADDR_CMD, val); fw_ver_low = REG_RD_IND(sc, BCE_RV2P_INSTR_LOW); - fw_ver_high = REG_RD_IND(sc, BCE_RV2P_INSTR_HIGH) & + fw_ver_high = REG_RD_IND(sc, BCE_RV2P_INSTR_HIGH) & BCE_RV2P_INSTR_HIGH_HIGH; - BCE_PRINTF("RV2P1 Firmware version - 0x%08X:0x%08X\n", + BCE_PRINTF("RV2P1 Firmware version - 0x%08X:0x%08X\n", fw_ver_high, fw_ver_low); val = 0x00000001; REG_WR_IND(sc, BCE_RV2P_PROC2_ADDR_CMD, val); fw_ver_low = REG_RD_IND(sc, BCE_RV2P_INSTR_LOW); - fw_ver_high = REG_RD_IND(sc, BCE_RV2P_INSTR_HIGH) & + fw_ver_high = REG_RD_IND(sc, BCE_RV2P_INSTR_HIGH) & BCE_RV2P_INSTR_HIGH_HIGH; - BCE_PRINTF("RV2P2 Firmware version - 0x%08X:0x%08X\n", + BCE_PRINTF("RV2P2 Firmware version - 0x%08X:0x%08X\n", fw_ver_high, fw_ver_low); /* Resume the RV2P processors. */ diff --git a/sys/dev/bce/if_bcereg.h b/sys/dev/bce/if_bcereg.h index 49bba63..d6e7c24 100644 --- a/sys/dev/bce/if_bcereg.h +++ b/sys/dev/bce/if_bcereg.h @@ -284,8 +284,8 @@ "\02EnaPauseRcv" \ "\01EnaPausXmit" -/* - * Remove before release: +/* + * Remove before release: * * #define BCE_DEBUG * #define BCE_NVRAM_WRITE_SUPPORT @@ -439,7 +439,7 @@ } /* Runs a particular command based on the code path. */ -#define DBRUNCP(cp, args...) \ +#define DBRUNCP(cp, args...) \ if (BCE_CODE_PATH(cp)) { \ args; \ } @@ -4116,7 +4116,7 @@ struct l2_fhdr { #define BCE_RDMA_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) - + /* * timer_reg definition * offset: 0x4400 @@ -4476,107 +4476,107 @@ struct l2_fhdr { * csch_reg definition * offset: 0x4000 */ -#define BCE_CSCH_COMMAND 0x00004000 -#define BCE_CSCH_CH_FTQ_CMD 0x000043f8 -#define BCE_CSCH_CH_FTQ_CTL 0x000043fc -#define BCE_CSCH_CH_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) -#define BCE_CSCH_CH_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) +#define BCE_CSCH_COMMAND 0x00004000 +#define BCE_CSCH_CH_FTQ_CMD 0x000043f8 +#define BCE_CSCH_CH_FTQ_CTL 0x000043fc +#define BCE_CSCH_CH_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BCE_CSCH_CH_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) /* * tbdr_reg definition * offset: 0x5000 */ -#define BCE_TBDR_COMMAND 0x00005000 -#define BCE_TBDR_COMMAND_ENABLE (1L<<0) -#define BCE_TBDR_COMMAND_SOFT_RST (1L<<1) -#define BCE_TBDR_COMMAND_MSTR_ABORT (1L<<4) - -#define BCE_TBDR_STATUS 0x00005004 -#define BCE_TBDR_STATUS_DMA_WAIT (1L<<0) -#define BCE_TBDR_STATUS_FTQ_WAIT (1L<<1) -#define BCE_TBDR_STATUS_FIFO_OVERFLOW (1L<<2) -#define BCE_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3) -#define BCE_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4) -#define BCE_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5) -#define BCE_TBDR_STATUS_BURST_CNT (1L<<6) - -#define BCE_TBDR_CONFIG 0x00005008 -#define BCE_TBDR_CONFIG_MAX_BDS (0xffL<<0) -#define BCE_TBDR_CONFIG_SWAP_MODE (1L<<8) -#define BCE_TBDR_CONFIG_PRIORITY (1L<<9) +#define BCE_TBDR_COMMAND 0x00005000 +#define BCE_TBDR_COMMAND_ENABLE (1L<<0) +#define BCE_TBDR_COMMAND_SOFT_RST (1L<<1) +#define BCE_TBDR_COMMAND_MSTR_ABORT (1L<<4) + +#define BCE_TBDR_STATUS 0x00005004 +#define BCE_TBDR_STATUS_DMA_WAIT (1L<<0) +#define BCE_TBDR_STATUS_FTQ_WAIT (1L<<1) +#define BCE_TBDR_STATUS_FIFO_OVERFLOW (1L<<2) +#define BCE_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3) +#define BCE_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4) +#define BCE_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5) +#define BCE_TBDR_STATUS_BURST_CNT (1L<<6) + +#define BCE_TBDR_CONFIG 0x00005008 +#define BCE_TBDR_CONFIG_MAX_BDS (0xffL<<0) +#define BCE_TBDR_CONFIG_SWAP_MODE (1L<<8) +#define BCE_TBDR_CONFIG_PRIORITY (1L<<9) #define BCE_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS (1L<<10) -#define BCE_TBDR_CONFIG_PAGE_SIZE (0xfL<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24) -#define BCE_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24) - -#define BCE_TBDR_DEBUG_VECT_PEEK 0x0000500c -#define BCE_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) -#define BCE_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) -#define BCE_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) -#define BCE_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) -#define BCE_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) -#define BCE_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) - -#define BCE_TBDR_FTQ_DATA 0x000053c0 -#define BCE_TBDR_FTQ_CMD 0x000053f8 -#define BCE_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0) -#define BCE_TBDR_FTQ_CMD_WR_TOP (1L<<10) -#define BCE_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10) -#define BCE_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10) -#define BCE_TBDR_FTQ_CMD_SFT_RESET (1L<<25) -#define BCE_TBDR_FTQ_CMD_RD_DATA (1L<<26) -#define BCE_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27) -#define BCE_TBDR_FTQ_CMD_ADD_DATA (1L<<28) -#define BCE_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29) -#define BCE_TBDR_FTQ_CMD_POP (1L<<30) -#define BCE_TBDR_FTQ_CMD_BUSY (1L<<31) - -#define BCE_TBDR_FTQ_CTL 0x000053fc -#define BCE_TBDR_FTQ_CTL_INTERVENE (1L<<0) -#define BCE_TBDR_FTQ_CTL_OVERFLOW (1L<<1) -#define BCE_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2) -#define BCE_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) -#define BCE_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) +#define BCE_TBDR_CONFIG_PAGE_SIZE (0xfL<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24) +#define BCE_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24) + +#define BCE_TBDR_DEBUG_VECT_PEEK 0x0000500c +#define BCE_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BCE_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BCE_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BCE_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BCE_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BCE_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BCE_TBDR_FTQ_DATA 0x000053c0 +#define BCE_TBDR_FTQ_CMD 0x000053f8 +#define BCE_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BCE_TBDR_FTQ_CMD_WR_TOP (1L<<10) +#define BCE_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10) +#define BCE_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10) +#define BCE_TBDR_FTQ_CMD_SFT_RESET (1L<<25) +#define BCE_TBDR_FTQ_CMD_RD_DATA (1L<<26) +#define BCE_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27) +#define BCE_TBDR_FTQ_CMD_ADD_DATA (1L<<28) +#define BCE_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29) +#define BCE_TBDR_FTQ_CMD_POP (1L<<30) +#define BCE_TBDR_FTQ_CMD_BUSY (1L<<31) + +#define BCE_TBDR_FTQ_CTL 0x000053fc +#define BCE_TBDR_FTQ_CTL_INTERVENE (1L<<0) +#define BCE_TBDR_FTQ_CTL_OVERFLOW (1L<<1) +#define BCE_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2) +#define BCE_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) +#define BCE_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) /* * tdma_reg definition * offset: 0x5c00 */ -#define BCE_TDMA_COMMAND 0x00005c00 -#define BCE_TDMA_COMMAND_ENABLED (1L<<0) -#define BCE_TDMA_COMMAND_MASTER_ABORT (1L<<4) -#define BCE_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7) - -#define BCE_TDMA_STATUS 0x00005c04 -#define BCE_TDMA_STATUS_DMA_WAIT (1L<<0) -#define BCE_TDMA_STATUS_PAYLOAD_WAIT (1L<<1) -#define BCE_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2) +#define BCE_TDMA_COMMAND 0x00005c00 +#define BCE_TDMA_COMMAND_ENABLED (1L<<0) +#define BCE_TDMA_COMMAND_MASTER_ABORT (1L<<4) +#define BCE_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7) + +#define BCE_TDMA_STATUS 0x00005c04 +#define BCE_TDMA_STATUS_DMA_WAIT (1L<<0) +#define BCE_TDMA_STATUS_PAYLOAD_WAIT (1L<<1) +#define BCE_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2) #define BCE_TDMA_STATUS_LOCK_WAIT (1L<<3) #define BCE_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16) #define BCE_TDMA_STATUS_BURST_CNT (1L<<17) -#define BCE_TDMA_CONFIG 0x00005c08 -#define BCE_TDMA_CONFIG_ONE_DMA (1L<<0) +#define BCE_TDMA_CONFIG 0x00005c08 +#define BCE_TDMA_CONFIG_ONE_DMA (1L<<0) #define BCE_TDMA_CONFIG_ONE_RECORD (1L<<1) #define BCE_TDMA_CONFIG_LIMIT_SZ (0xfL<<4) #define BCE_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4) #define BCE_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4) #define BCE_TDMA_CONFIG_LIMIT_SZ_256 (0x6L<<4) #define BCE_TDMA_CONFIG_LIMIT_SZ_512 (0x8L<<4) -#define BCE_TDMA_CONFIG_LINE_SZ (0xfL<<8) +#define BCE_TDMA_CONFIG_LINE_SZ (0xfL<<8) #define BCE_TDMA_CONFIG_LINE_SZ_64 (0L<<8) #define BCE_TDMA_CONFIG_LINE_SZ_128 (4L<<8) #define BCE_TDMA_CONFIG_LINE_SZ_256 (6L<<8) @@ -4612,7 +4612,7 @@ struct l2_fhdr { #define BCE_TDMA_DR_INTF_FSM_DR_BUF (0x7L<<12) #define BCE_TDMA_DR_INTF_FSM_DMAD (0x7L<<16) -#define BCE_TDMA_DR_INTF_STATUS 0x00005c8c +#define BCE_TDMA_DR_INTF_STATUS 0x00005c8c #define BCE_TDMA_DR_INTF_STATUS_HOLE_PHASE (0x7L<<0) #define BCE_TDMA_DR_INTF_STATUS_DATA_AVAIL (0x3L<<4) #define BCE_TDMA_DR_INTF_STATUS_SHIFT_ADDR (0x7L<<8) @@ -4621,8 +4621,8 @@ struct l2_fhdr { #define BCE_TDMA_FTQ_DATA 0x00005fc0 #define BCE_TDMA_FTQ_CMD 0x00005ff8 -#define BCE_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0) -#define BCE_TDMA_FTQ_CMD_WR_TOP (1L<<10) +#define BCE_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0) +#define BCE_TDMA_FTQ_CMD_WR_TOP (1L<<10) #define BCE_TDMA_FTQ_CMD_WR_TOP_0 (0L<<10) #define BCE_TDMA_FTQ_CMD_WR_TOP_1 (1L<<10) #define BCE_TDMA_FTQ_CMD_SFT_RESET (1L<<25) @@ -4645,7 +4645,7 @@ struct l2_fhdr { * nvm_reg definition * offset: 0x6400 */ -#define BCE_NVM_COMMAND 0x00006400 +#define BCE_NVM_COMMAND 0x00006400 #define BCE_NVM_COMMAND_RST (1L<<0) #define BCE_NVM_COMMAND_DONE (1L<<3) #define BCE_NVM_COMMAND_DOIT (1L<<4) @@ -4694,23 +4694,23 @@ struct l2_fhdr { #define BCE_NVM_READ_NVM_READ_VALUE_SI (32L<<0) #define BCE_NVM_CFG1 0x00006414 -#define BCE_NVM_CFG1_FLASH_MODE (1L<<0) +#define BCE_NVM_CFG1_FLASH_MODE (1L<<0) #define BCE_NVM_CFG1_BUFFER_MODE (1L<<1) #define BCE_NVM_CFG1_PASS_MODE (1L<<2) #define BCE_NVM_CFG1_BITBANG_MODE (1L<<3) -#define BCE_NVM_CFG1_STATUS_BIT (0x7L<<4) +#define BCE_NVM_CFG1_STATUS_BIT (0x7L<<4) #define BCE_NVM_CFG1_STATUS_BIT_FLASH_RDY (0L<<4) #define BCE_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4) #define BCE_NVM_CFG1_SPI_CLK_DIV (0xfL<<7) #define BCE_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11) #define BCE_NVM_CFG1_PROTECT_MODE (1L<<24) -#define BCE_NVM_CFG1_FLASH_SIZE (1L<<25) +#define BCE_NVM_CFG1_FLASH_SIZE (1L<<25) #define BCE_NVM_CFG1_COMPAT_BYPASSS (1L<<31) #define BCE_NVM_CFG2 0x00006418 #define BCE_NVM_CFG2_ERASE_CMD (0xffL<<0) #define BCE_NVM_CFG2_DUMMY (0xffL<<8) -#define BCE_NVM_CFG2_STATUS_CMD (0xffL<<16) +#define BCE_NVM_CFG2_STATUS_CMD (0xffL<<16) #define BCE_NVM_CFG3 0x0000641c #define BCE_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0) @@ -4727,10 +4727,10 @@ struct l2_fhdr { #define BCE_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5) #define BCE_NVM_SW_ARB_ARB_REQ_CLR2 (1L<<6) #define BCE_NVM_SW_ARB_ARB_REQ_CLR3 (1L<<7) -#define BCE_NVM_SW_ARB_ARB_ARB0 (1L<<8) -#define BCE_NVM_SW_ARB_ARB_ARB1 (1L<<9) -#define BCE_NVM_SW_ARB_ARB_ARB2 (1L<<10) -#define BCE_NVM_SW_ARB_ARB_ARB3 (1L<<11) +#define BCE_NVM_SW_ARB_ARB_ARB0 (1L<<8) +#define BCE_NVM_SW_ARB_ARB_ARB1 (1L<<9) +#define BCE_NVM_SW_ARB_ARB_ARB2 (1L<<10) +#define BCE_NVM_SW_ARB_ARB_ARB3 (1L<<11) #define BCE_NVM_SW_ARB_REQ0 (1L<<12) #define BCE_NVM_SW_ARB_REQ1 (1L<<13) #define BCE_NVM_SW_ARB_REQ2 (1L<<14) @@ -4741,8 +4741,8 @@ struct l2_fhdr { #define BCE_NVM_ACCESS_ENABLE_WR_EN (1L<<1) #define BCE_NVM_WRITE1 0x00006428 -#define BCE_NVM_WRITE1_WREN_CMD (0xffL<<0) -#define BCE_NVM_WRITE1_WRDI_CMD (0xffL<<8) +#define BCE_NVM_WRITE1_WREN_CMD (0xffL<<0) +#define BCE_NVM_WRITE1_WRDI_CMD (0xffL<<8) #define BCE_NVM_WRITE1_SR_DATA (0xffL<<16) @@ -4753,7 +4753,7 @@ struct l2_fhdr { #define BCE_HC_COMMAND 0x00006800 #define BCE_HC_COMMAND_ENABLE (1L<<0) #define BCE_HC_COMMAND_SKIP_ABORT (1L<<4) -#define BCE_HC_COMMAND_COAL_NOW (1L<<16) +#define BCE_HC_COMMAND_COAL_NOW (1L<<16) #define BCE_HC_COMMAND_COAL_NOW_WO_INT (1L<<17) #define BCE_HC_COMMAND_STATS_NOW (1L<<18) #define BCE_HC_COMMAND_FORCE_INT (0x3L<<19) @@ -4769,7 +4769,7 @@ struct l2_fhdr { #define BCE_HC_STATUS_MASTER_ABORT (1L<<0) #define BCE_HC_STATUS_PARITY_ERROR_STATE (1L<<1) #define BCE_HC_STATUS_PCI_CLK_CNT_STAT (1L<<16) -#define BCE_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17) +#define BCE_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17) #define BCE_HC_STATUS_NUM_STATUS_BLOCKS_STAT (1L<<18) #define BCE_HC_STATUS_NUM_INT_GEN_STAT (1L<<19) #define BCE_HC_STATUS_NUM_INT_MBOX_WR_STAT (1L<<20) @@ -4790,27 +4790,27 @@ struct l2_fhdr { #define BCE_HC_CONFIG_ONE_SHOT (1L<<17) #define BCE_HC_CONFIG_USE_INT_PARAM (1L<<18) #define BCE_HC_CONFIG_SET_MASK_AT_RD (1L<<19) -#define BCE_HC_CONFIG_PER_COLLECT_LIMIT (0xfL<<20) +#define BCE_HC_CONFIG_PER_COLLECT_LIMIT (0xfL<<20) #define BCE_HC_CONFIG_SB_ADDR_INC (0x7L<<24) #define BCE_HC_CONFIG_SB_ADDR_INC_64B (0L<<24) #define BCE_HC_CONFIG_SB_ADDR_INC_128B (1L<<24) #define BCE_HC_CONFIG_SB_ADDR_INC_256B (2L<<24) #define BCE_HC_CONFIG_SB_ADDR_INC_512B (3L<<24) -#define BCE_HC_CONFIG_SB_ADDR_INC_1024B (4L<<24) -#define BCE_HC_CONFIG_SB_ADDR_INC_2048B (5L<<24) -#define BCE_HC_CONFIG_SB_ADDR_INC_4096B (6L<<24) -#define BCE_HC_CONFIG_SB_ADDR_INC_8192B (7L<<24) -#define BCE_HC_CONFIG_GEN_STAT_AVG_INTR (1L<<29) +#define BCE_HC_CONFIG_SB_ADDR_INC_1024B (4L<<24) +#define BCE_HC_CONFIG_SB_ADDR_INC_2048B (5L<<24) +#define BCE_HC_CONFIG_SB_ADDR_INC_4096B (6L<<24) +#define BCE_HC_CONFIG_SB_ADDR_INC_8192B (7L<<24) +#define BCE_HC_CONFIG_GEN_STAT_AVG_INTR (1L<<29) #define BCE_HC_CONFIG_UNMASK_ALL (1L<<30) #define BCE_HC_CONFIG_TX_SEL (1L<<31) -#define BCE_HC_ATTN_BITS_ENABLE 0x0000680c +#define BCE_HC_ATTN_BITS_ENABLE 0x0000680c #define BCE_HC_STATUS_ADDR_L 0x00006810 #define BCE_HC_STATUS_ADDR_H 0x00006814 #define BCE_HC_STATISTICS_ADDR_L 0x00006818 #define BCE_HC_STATISTICS_ADDR_H 0x0000681c #define BCE_HC_TX_QUICK_CONS_TRIP 0x00006820 -#define BCE_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0) +#define BCE_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0) #define BCE_HC_TX_QUICK_CONS_TRIP_INT (0xffL<<16) #define BCE_HC_COMP_PROD_TRIP 0x00006824 @@ -4818,14 +4818,14 @@ struct l2_fhdr { #define BCE_HC_COMP_PROD_TRIP_INT (0xffL<<16) #define BCE_HC_RX_QUICK_CONS_TRIP 0x00006828 -#define BCE_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0) +#define BCE_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0) #define BCE_HC_RX_QUICK_CONS_TRIP_INT (0xffL<<16) -#define BCE_HC_RX_TICKS 0x0000682c +#define BCE_HC_RX_TICKS 0x0000682c #define BCE_HC_RX_TICKS_VALUE (0x3ffL<<0) #define BCE_HC_RX_TICKS_INT (0x3ffL<<16) -#define BCE_HC_TX_TICKS 0x00006830 +#define BCE_HC_TX_TICKS 0x00006830 #define BCE_HC_TX_TICKS_VALUE (0x3ffL<<0) #define BCE_HC_TX_TICKS_INT (0x3ffL<<16) @@ -4838,7 +4838,7 @@ struct l2_fhdr { #define BCE_HC_CMD_TICKS_INT (0x3ffL<<16) #define BCE_HC_PERIODIC_TICKS 0x0000683c -#define BCE_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0) +#define BCE_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0) #define BCE_HC_PERIODIC_TICKS_HC_INT_PERIODIC_TICKS (0xffffL<<16) #define BCE_HC_STAT_COLLECT_TICKS 0x00006840 @@ -4848,12 +4848,12 @@ struct l2_fhdr { #define BCE_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8) #define BCE_HC_STATS_INTERRUPT_STATUS 0x00006848 -#define BCE_HC_STATS_INTERRUPT_STATUS_SB_STATUS (0x1ffL<<0) +#define BCE_HC_STATS_INTERRUPT_STATUS_SB_STATUS (0x1ffL<<0) #define BCE_HC_STATS_INTERRUPT_STATUS_INT_STATUS (0x1ffL<<16) #define BCE_HC_STAT_MEM_DATA 0x0000684c #define BCE_HC_STAT_GEN_SEL_0 0x00006850 -#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0) +#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0) #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0 (0L<<0) #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1 (1L<<0) #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2 (2L<<0) @@ -4921,9 +4921,9 @@ struct l2_fhdr { #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT (66L<<0) #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT (67L<<0) #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT (68L<<0) -#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0) -#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0) -#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0) +#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0) +#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0) +#define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0) #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT (72L<<0) #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT (73L<<0) #define BCE_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT (74L<<0) @@ -6006,7 +6006,7 @@ struct l2_fhdr { #define BCE_TAS_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) #define BCE_TAS_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) - + /* * mcp_reg definition * offset: 0x140000 @@ -6372,7 +6372,7 @@ struct fw_info { struct bce_softc { - /* Interface info */ + /* Interface info. Must be first!! */ struct ifnet *bce_ifp; /* Parent device handle */ @@ -6403,167 +6403,168 @@ struct bce_softc /* Interrupt handler. */ driver_intr_t *bce_intr; - void *bce_intrhand; - int bce_irq_rid; - int bce_msi_count; + void *bce_intrhand; + int bce_irq_rid; + int bce_msi_count; /* ASIC Chip ID. */ - u32 bce_chipid; + u32 bce_chipid; /* General controller flags. */ - u32 bce_flags; -#define BCE_PCIX_FLAG 0x00000001 -#define BCE_PCI_32BIT_FLAG 0x00000002 -#define BCE_RESERVED_FLAG 0x00000004 -#define BCE_NO_WOL_FLAG 0x00000008 -#define BCE_USING_DAC_FLAG 0x00000010 -#define BCE_USING_MSI_FLAG 0x00000020 -#define BCE_MFW_ENABLE_FLAG 0x00000040 -#define BCE_ONE_SHOT_MSI_FLAG 0x00000080 -#define BCE_USING_MSIX_FLAG 0x00000100 -#define BCE_PCIE_FLAG 0x00000200 + u32 bce_flags; +#define BCE_PCIX_FLAG 0x00000001 +#define BCE_PCI_32BIT_FLAG 0x00000002 +#define BCE_RESERVED_FLAG 0x00000004 +#define BCE_NO_WOL_FLAG 0x00000008 +#define BCE_USING_DAC_FLAG 0x00000010 +#define BCE_USING_MSI_FLAG 0x00000020 +#define BCE_MFW_ENABLE_FLAG 0x00000040 +#define BCE_ONE_SHOT_MSI_FLAG 0x00000080 +#define BCE_USING_MSIX_FLAG 0x00000100 +#define BCE_PCIE_FLAG 0x00000200 +#define BCE_USING_TX_FLOW_CONTROL 0x00000400 /* Controller capability flags. */ - u32 bce_cap_flags; -#define BCE_MSI_CAPABLE_FLAG 0x00000001 -#define BCE_MSIX_CAPABLE_FLAG 0x00000002 -#define BCE_PCIE_CAPABLE_FLAG 0x00000004 -#define BCE_PCIX_CAPABLE_FLAG 0x00000008 + u32 bce_cap_flags; +#define BCE_MSI_CAPABLE_FLAG 0x00000001 +#define BCE_MSIX_CAPABLE_FLAG 0x00000002 +#define BCE_PCIE_CAPABLE_FLAG 0x00000004 +#define BCE_PCIX_CAPABLE_FLAG 0x00000008 /* PHY specific flags. */ - u32 bce_phy_flags; -#define BCE_PHY_SERDES_FLAG 0x00000001 -#define BCE_PHY_CRC_FIX_FLAG 0x00000002 -#define BCE_PHY_PARALLEL_DETECT_FLAG 0x00000004 -#define BCE_PHY_2_5G_CAPABLE_FLAG 0x00000008 -#define BCE_PHY_INT_MODE_MASK_FLAG 0x00000300 -#define BCE_PHY_INT_MODE_AUTO_POLLING_FLAG 0x00000100 -#define BCE_PHY_INT_MODE_LINK_READY_FLAG 0x00000200 -#define BCE_PHY_IEEE_CLAUSE_45_FLAG 0x00000400 + u32 bce_phy_flags; +#define BCE_PHY_SERDES_FLAG 0x00000001 +#define BCE_PHY_CRC_FIX_FLAG 0x00000002 +#define BCE_PHY_PARALLEL_DETECT_FLAG 0x00000004 +#define BCE_PHY_2_5G_CAPABLE_FLAG 0x00000008 +#define BCE_PHY_INT_MODE_MASK_FLAG 0x00000300 +#define BCE_PHY_INT_MODE_AUTO_POLLING_FLAG 0x00000100 +#define BCE_PHY_INT_MODE_LINK_READY_FLAG 0x00000200 +#define BCE_PHY_IEEE_CLAUSE_45_FLAG 0x00000400 /* Values that need to be shared with the PHY driver. */ - u32 bce_shared_hw_cfg; - u32 bce_port_hw_cfg; + u32 bce_shared_hw_cfg; + u32 bce_port_hw_cfg; - bus_addr_t max_bus_addr; + bus_addr_t max_bus_addr; /* PCI bus speed */ - u16 bus_speed_mhz; + u16 bus_speed_mhz; /* PCIe link width */ - u16 link_width; + u16 link_width; /* PCIe link speed */ - u16 link_speed; + u16 link_speed; /* Flash NVRAM settings */ - struct flash_spec *bce_flash_info; + struct flash_spec *bce_flash_info; /* Flash NVRAM size */ - u32 bce_flash_size; + u32 bce_flash_size; /* Shared Memory base address */ - u32 bce_shmem_base; + u32 bce_shmem_base; /* Name string */ - char * bce_name; + char *bce_name; /* Tracks the version of bootcode firmware. */ - char bce_bc_ver[32]; + char bce_bc_ver[32]; /* Tracks the version of management firmware. */ - char bce_mfw_ver[32]; + char bce_mfw_ver[32]; - /* + /* * Tracks the state of the firmware. 0 = Running while any * other value indicates that the firmware is not responding. */ - u16 bce_fw_timed_out; + u16 bce_fw_timed_out; - /* + /* * An incrementing sequence used to coordinate messages passed * from the driver to the firmware. - */ - u16 bce_fw_wr_seq; + */ + u16 bce_fw_wr_seq; - /* + /* * An incrementing sequence used to let the firmware know that * the driver is still operating. Without the pulse, management * firmware such as IPMI or UMP will operate in OS absent state. - */ - u16 bce_fw_drv_pulse_wr_seq; + */ + u16 bce_fw_drv_pulse_wr_seq; /* Tracks whether firmware has lost the driver's pulse. */ - u16 bce_drv_cardiac_arrest; + u16 bce_drv_cardiac_arrest; /* Ethernet MAC address. */ - u_char eaddr[6]; + u_char eaddr[6]; - /* + /* * These setting are used by the host coalescing (HC) block to * to control how often the status block, statistics block and * interrupts are generated. - */ - u16 bce_tx_quick_cons_trip_int; - u16 bce_tx_quick_cons_trip; - u16 bce_rx_quick_cons_trip_int; - u16 bce_rx_quick_cons_trip; - u16 bce_tx_ticks_int; - u16 bce_tx_ticks; - u16 bce_rx_ticks_int; - u16 bce_rx_ticks; - u32 bce_stats_ticks; + */ + u16 bce_tx_quick_cons_trip_int; + u16 bce_tx_quick_cons_trip; + u16 bce_rx_quick_cons_trip_int; + u16 bce_rx_quick_cons_trip; + u16 bce_tx_ticks_int; + u16 bce_tx_ticks; + u16 bce_rx_ticks_int; + u16 bce_rx_ticks; + u32 bce_stats_ticks; /* ToDo: Can these be removed? */ - u16 bce_comp_prod_trip_int; - u16 bce_comp_prod_trip; - u16 bce_com_ticks_int; - u16 bce_com_ticks; - u16 bce_cmd_ticks_int; - u16 bce_cmd_ticks; + u16 bce_comp_prod_trip_int; + u16 bce_comp_prod_trip; + u16 bce_com_ticks_int; + u16 bce_com_ticks; + u16 bce_cmd_ticks_int; + u16 bce_cmd_ticks; /* The address of the integrated PHY on the MII bus. */ - int bce_phy_addr; + int bce_phy_addr; /* The device handle for the MII bus child device. */ - device_t bce_miibus; + device_t bce_miibus; /* Driver maintained TX chain pointers and byte counter. */ - u16 rx_prod; - u16 rx_cons; + u16 rx_prod; + u16 rx_cons; /* Counts the bytes used in the RX chain. */ - u32 rx_prod_bseq; - u16 tx_prod; - u16 tx_cons; + u32 rx_prod_bseq; + u16 tx_prod; + u16 tx_cons; /* Counts the bytes used in the TX chain. */ - u32 tx_prod_bseq; + u32 tx_prod_bseq; #ifdef BCE_JUMBO_HDRSPLIT - u16 pg_prod; - u16 pg_cons; + u16 pg_prod; + u16 pg_cons; #endif - int bce_link_up; - struct callout bce_tick_callout; - struct callout bce_pulse_callout; + int bce_link_up; + struct callout bce_tick_callout; + struct callout bce_pulse_callout; /* Ticks until chip reset */ - int watchdog_timer; + int watchdog_timer; /* Frame size and mbuf allocation size for RX frames. */ - u32 max_frame_size; - int rx_bd_mbuf_alloc_size; - int rx_bd_mbuf_data_len; - int rx_bd_mbuf_align_pad; + u32 max_frame_size; + int rx_bd_mbuf_alloc_size; + int rx_bd_mbuf_data_len; + int rx_bd_mbuf_align_pad; #ifdef BCE_JUMBO_HDRSPLIT - int pg_bd_mbuf_alloc_size; + int pg_bd_mbuf_alloc_size; #endif /* Receive mode settings (i.e promiscuous, multicast, etc.). */ - u32 rx_mode; + u32 rx_mode; /* Bus tag for the bce controller. */ bus_dma_tag_t parent_tag; @@ -6595,9 +6596,9 @@ struct bce_softc bus_addr_t status_block_paddr; /* Driver maintained status block values. */ - u16 last_status_idx; - u16 hw_rx_cons; - u16 hw_tx_cons; + u16 last_status_idx; + u16 hw_rx_cons; + u16 hw_tx_cons; /* H/W maintained statistics block. */ bus_dma_tag_t stats_tag; @@ -6606,7 +6607,7 @@ struct bce_softc bus_addr_t stats_block_paddr; /* H/W maintained context block. */ - int ctx_pages; + int ctx_pages; bus_dma_tag_t ctx_tag; /* BCM5709/16 use host memory for context. */ @@ -6637,139 +6638,156 @@ struct bce_softc #endif /* Track the number of buffer descriptors in use. */ - u16 free_rx_bd; - u16 max_rx_bd; - u16 used_tx_bd; - u16 max_tx_bd; + u16 free_rx_bd; + u16 max_rx_bd; + u16 used_tx_bd; + u16 max_tx_bd; #ifdef BCE_JUMBO_HDRSPLIT - u16 free_pg_bd; - u16 max_pg_bd; + u16 free_pg_bd; + u16 max_pg_bd; #endif /* Provides access to hardware statistics through sysctl. */ - u64 stat_IfHCInOctets; - u64 stat_IfHCInBadOctets; - u64 stat_IfHCOutOctets; - u64 stat_IfHCOutBadOctets; - u64 stat_IfHCInUcastPkts; - u64 stat_IfHCInMulticastPkts; - u64 stat_IfHCInBroadcastPkts; - u64 stat_IfHCOutUcastPkts; - u64 stat_IfHCOutMulticastPkts; - u64 stat_IfHCOutBroadcastPkts; - - u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors; - u32 stat_Dot3StatsCarrierSenseErrors; - u32 stat_Dot3StatsFCSErrors; - u32 stat_Dot3StatsAlignmentErrors; - u32 stat_Dot3StatsSingleCollisionFrames; - u32 stat_Dot3StatsMultipleCollisionFrames; - u32 stat_Dot3StatsDeferredTransmissions; - u32 stat_Dot3StatsExcessiveCollisions; - u32 stat_Dot3StatsLateCollisions; - u32 stat_EtherStatsCollisions; - u32 stat_EtherStatsFragments; - u32 stat_EtherStatsJabbers; - u32 stat_EtherStatsUndersizePkts; - u32 stat_EtherStatsOversizePkts; - u32 stat_EtherStatsPktsRx64Octets; - u32 stat_EtherStatsPktsRx65Octetsto127Octets; - u32 stat_EtherStatsPktsRx128Octetsto255Octets; - u32 stat_EtherStatsPktsRx256Octetsto511Octets; - u32 stat_EtherStatsPktsRx512Octetsto1023Octets; - u32 stat_EtherStatsPktsRx1024Octetsto1522Octets; - u32 stat_EtherStatsPktsRx1523Octetsto9022Octets; - u32 stat_EtherStatsPktsTx64Octets; - u32 stat_EtherStatsPktsTx65Octetsto127Octets; - u32 stat_EtherStatsPktsTx128Octetsto255Octets; - u32 stat_EtherStatsPktsTx256Octetsto511Octets; - u32 stat_EtherStatsPktsTx512Octetsto1023Octets; - u32 stat_EtherStatsPktsTx1024Octetsto1522Octets; - u32 stat_EtherStatsPktsTx1523Octetsto9022Octets; - u32 stat_XonPauseFramesReceived; - u32 stat_XoffPauseFramesReceived; - u32 stat_OutXonSent; - u32 stat_OutXoffSent; - u32 stat_FlowControlDone; - u32 stat_MacControlFramesReceived; - u32 stat_XoffStateEntered; - u32 stat_IfInFramesL2FilterDiscards; - u32 stat_IfInRuleCheckerDiscards; - u32 stat_IfInFTQDiscards; - u32 stat_IfInMBUFDiscards; - u32 stat_IfInRuleCheckerP4Hit; - u32 stat_CatchupInRuleCheckerDiscards; - u32 stat_CatchupInFTQDiscards; - u32 stat_CatchupInMBUFDiscards; - u32 stat_CatchupInRuleCheckerP4Hit; + u64 stat_IfHCInOctets; + u64 stat_IfHCInBadOctets; + u64 stat_IfHCOutOctets; + u64 stat_IfHCOutBadOctets; + u64 stat_IfHCInUcastPkts; + u64 stat_IfHCInMulticastPkts; + u64 stat_IfHCInBroadcastPkts; + u64 stat_IfHCOutUcastPkts; + u64 stat_IfHCOutMulticastPkts; + u64 stat_IfHCOutBroadcastPkts; + + u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors; + u32 stat_Dot3StatsCarrierSenseErrors; + u32 stat_Dot3StatsFCSErrors; + u32 stat_Dot3StatsAlignmentErrors; + u32 stat_Dot3StatsSingleCollisionFrames; + u32 stat_Dot3StatsMultipleCollisionFrames; + u32 stat_Dot3StatsDeferredTransmissions; + u32 stat_Dot3StatsExcessiveCollisions; + u32 stat_Dot3StatsLateCollisions; + u32 stat_EtherStatsCollisions; + u32 stat_EtherStatsFragments; + u32 stat_EtherStatsJabbers; + u32 stat_EtherStatsUndersizePkts; + u32 stat_EtherStatsOversizePkts; + u32 stat_EtherStatsPktsRx64Octets; + u32 stat_EtherStatsPktsRx65Octetsto127Octets; + u32 stat_EtherStatsPktsRx128Octetsto255Octets; + u32 stat_EtherStatsPktsRx256Octetsto511Octets; + u32 stat_EtherStatsPktsRx512Octetsto1023Octets; + u32 stat_EtherStatsPktsRx1024Octetsto1522Octets; + u32 stat_EtherStatsPktsRx1523Octetsto9022Octets; + u32 stat_EtherStatsPktsTx64Octets; + u32 stat_EtherStatsPktsTx65Octetsto127Octets; + u32 stat_EtherStatsPktsTx128Octetsto255Octets; + u32 stat_EtherStatsPktsTx256Octetsto511Octets; + u32 stat_EtherStatsPktsTx512Octetsto1023Octets; + u32 stat_EtherStatsPktsTx1024Octetsto1522Octets; + u32 stat_EtherStatsPktsTx1523Octetsto9022Octets; + u32 stat_XonPauseFramesReceived; + u32 stat_XoffPauseFramesReceived; + u32 stat_OutXonSent; + u32 stat_OutXoffSent; + u32 stat_FlowControlDone; + u32 stat_MacControlFramesReceived; + u32 stat_XoffStateEntered; + u32 stat_IfInFramesL2FilterDiscards; + u32 stat_IfInRuleCheckerDiscards; + u32 stat_IfInFTQDiscards; + u32 stat_IfInMBUFDiscards; + u32 stat_IfInRuleCheckerP4Hit; + u32 stat_CatchupInRuleCheckerDiscards; + u32 stat_CatchupInFTQDiscards; + u32 stat_CatchupInMBUFDiscards; + u32 stat_CatchupInRuleCheckerP4Hit; /* Provides access to certain firmware statistics. */ - u32 com_no_buffers; + u32 com_no_buffers; /* Recoverable failure counters. */ - u32 mbuf_alloc_failed_count; - u32 fragmented_mbuf_count; - u32 unexpected_attention_count; - u32 l2fhdr_error_count; - u32 dma_map_addr_tx_failed_count; - u32 dma_map_addr_rx_failed_count; + u32 mbuf_alloc_failed_count; + u32 mbuf_frag_count; + u32 unexpected_attention_count; + u32 l2fhdr_error_count; + u32 dma_map_addr_tx_failed_count; + u32 dma_map_addr_rx_failed_count; /* Host coalescing block command register */ - u32 hc_command; + u32 hc_command; /* Bootcode state */ - u32 bc_state; + u32 bc_state; #ifdef BCE_DEBUG /* Simulated recoverable failure counters. */ - u32 mbuf_alloc_failed_sim_count; - u32 unexpected_attention_sim_count; - u32 l2fhdr_error_sim_count; - u32 dma_map_addr_failed_sim_count; + u32 mbuf_alloc_failed_sim_count; + u32 unexpected_attention_sim_count; + u32 l2fhdr_error_sim_count; + u32 dma_map_addr_failed_sim_count; /* Track the number of enqueued mbufs. */ - int debug_tx_mbuf_alloc; - int debug_rx_mbuf_alloc; + int debug_tx_mbuf_alloc; + int debug_rx_mbuf_alloc; #ifdef BCE_JUMBO_HDRSPLIT - int debug_pg_mbuf_alloc; + int debug_pg_mbuf_alloc; #endif /* Track how many and what type of interrupts are generated. */ - u32 interrupts_generated; - u32 interrupts_handled; - u32 rx_interrupts; - u32 tx_interrupts; - u32 phy_interrupts; + u32 interrupts_generated; + u32 interrupts_handled; + u32 interrupts_rx; + u32 interrupts_tx; + u32 phy_interrupts; /* Track interrupt time (25MHz clock). */ - u64 rx_intr_time; - u64 tx_intr_time; + u64 rx_intr_time; + u64 tx_intr_time; /* Lowest number of rx_bd's free. */ - u32 rx_low_watermark; + u32 rx_low_watermark; /* Number of times the RX chain was empty. */ - u32 rx_empty_count; + u32 rx_empty_count; #ifdef BCE_JUMBO_HDRSPLIT - /* Lowest number of pages free. */ - u32 pg_low_watermark; + u32 pg_low_watermark; /* Number of times the page chain was empty. */ - u32 pg_empty_count; + u32 pg_empty_count; #endif /* Greatest number of tx_bd's used. */ - u32 tx_hi_watermark; + u32 tx_hi_watermark; /* Number of times the TX chain was full. */ - u32 tx_full_count; + u32 tx_full_count; + + /* Number of TSO frames requested. */ + u32 tso_frames_requested; + + /* Number of TSO frames completed. */ + u32 tso_frames_completed; + + /* Number of TSO frames failed. */ + u32 tso_frames_failed; + + /* Number of IP checksum offload frames.*/ + u32 csum_offload_ip; + + /* Number of TCP/UDP checksum offload frames.*/ + u32 csum_offload_tcp_udp; + + /* Number of VLAN tagged frames received. */ + u32 vlan_tagged_frames_rcvd; - /* Number of TSO frames enqueued. */ - u32 requested_tso_frames; + /* Number of VLAN tagged frames stripped. */ + u32 vlan_tagged_frames_stripped; #endif }; -- cgit v1.1 From c53b44ae5109b43866ee75858b45950f4870b2d5 Mon Sep 17 00:00:00 2001 From: kmacy Date: Fri, 30 Apr 2010 02:46:49 +0000 Subject: don't allow unsynchronized free in vm_page_unhold --- sys/vm/vm_page.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 4c0d385..fb0950e 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -563,8 +563,11 @@ vm_page_unhold(vm_page_t mem) vm_page_lock_assert(mem, MA_OWNED); --mem->hold_count; KASSERT(mem->hold_count >= 0, ("vm_page_unhold: hold count < 0!!!")); - if (mem->hold_count == 0 && VM_PAGE_INQUEUE2(mem, PQ_HOLD)) + if (mem->hold_count == 0 && VM_PAGE_INQUEUE2(mem, PQ_HOLD)) { + vm_page_lock_queues(); vm_page_free_toq(mem); + vm_page_unlock_queues(); + } } /* -- cgit v1.1 From 20fdc94b9e6b94282e3e136276daf05c45b18edb Mon Sep 17 00:00:00 2001 From: alfred Date: Fri, 30 Apr 2010 03:10:53 +0000 Subject: Do not set IO_NODELOCKED while writing to vnodes as our consumers do not lock the vnodes. Obtained from: Juniper Networks Reviewed by: jhb --- sys/kern/kern_gzio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/kern/kern_gzio.c b/sys/kern/kern_gzio.c index 1f9c387..c1b2b3f 100644 --- a/sys/kern/kern_gzio.c +++ b/sys/kern/kern_gzio.c @@ -166,7 +166,7 @@ gzFile gz_open (path, mode, vp) 0 /*xflags*/, OS_CODE); if ((error = vn_rdwr(UIO_WRITE, s->file, buf, GZ_HEADER_LEN, s->outoff, - UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, curproc->p_ucred, + UIO_SYSSPACE, IO_UNIT, curproc->p_ucred, NOCRED, &resid, curthread))) { s->outoff += GZ_HEADER_LEN - resid; return destroy(s), (gzFile)Z_NULL; @@ -234,7 +234,7 @@ int ZEXPORT gzwrite (file, buf, len) s->stream.next_out = s->outbuf; vfslocked = VFS_LOCK_GIANT(s->file->v_mount); error = vn_rdwr_inchunks(UIO_WRITE, s->file, s->outbuf, Z_BUFSIZE, - curoff, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, + curoff, UIO_SYSSPACE, IO_UNIT, curproc->p_ucred, NOCRED, &resid, curthread); VFS_UNLOCK_GIANT(vfslocked); if (error) { @@ -291,7 +291,7 @@ local int do_flush (file, flush) if (len != 0) { vfslocked = VFS_LOCK_GIANT(s->file->v_mount); error = vn_rdwr_inchunks(UIO_WRITE, s->file, s->outbuf, len, curoff, - UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, curproc->p_ucred, + UIO_SYSSPACE, IO_UNIT, curproc->p_ucred, NOCRED, &resid, curthread); VFS_UNLOCK_GIANT(vfslocked); if (error) { @@ -350,7 +350,7 @@ local void putU32 (s, x) xx = x; #endif vn_rdwr(UIO_WRITE, s->file, (caddr_t)&xx, sizeof(xx), curoff, - UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, curproc->p_ucred, + UIO_SYSSPACE, IO_UNIT, curproc->p_ucred, NOCRED, &resid, curthread); s->outoff += sizeof(xx) - resid; } -- cgit v1.1 From 993bf6ff365b34234950ca83a90ffc5c04d5ca1a Mon Sep 17 00:00:00 2001 From: alfred Date: Fri, 30 Apr 2010 03:13:24 +0000 Subject: Don't leak core_buf or gzfile if doing a compressed core file and we hit an error condition. Obtained from: Juniper Networks --- sys/kern/imgact_elf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 236894f..c48e0f5 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -1088,8 +1088,10 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) hdrsize = 0; __elfN(puthdr)(td, (void *)NULL, &hdrsize, seginfo.count); - if (hdrsize + seginfo.size >= limit) - return (EFAULT); + if (hdrsize + seginfo.size >= limit) { + error = EFAULT; + goto done; + } /* * Allocate memory for building the header, fill it up, @@ -1097,7 +1099,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) */ hdr = malloc(hdrsize, M_TEMP, M_WAITOK); if (hdr == NULL) { - return (EINVAL); + error = EINVAL; + goto done; } error = __elfN(corehdr)(td, vp, cred, seginfo.count, hdr, hdrsize, gzfile); @@ -1125,8 +1128,8 @@ __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags) curproc->p_comm, error); } -#ifdef COMPRESS_USER_CORES done: +#ifdef COMPRESS_USER_CORES if (core_buf) free(core_buf, M_TEMP); if (gzfile) -- cgit v1.1 From 12d5232340181b7d414b4b9204f9fdc091f11e30 Mon Sep 17 00:00:00 2001 From: alfred Date: Fri, 30 Apr 2010 03:15:00 +0000 Subject: Avoid allocating MAXHOSTNAMELEN bytes on the stack in expand_name(), use the heap instead. Obtained from: Juniper Networks Reviewed by: jhb --- sys/kern/kern_sig.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 706433d..789bb61 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -3004,8 +3004,9 @@ expand_name(const char *name, uid_t uid, pid_t pid, struct thread *td, char *temp; size_t i; int indexpos; - char hostname[MAXHOSTNAMELEN]; + char *hostname; + hostname = NULL; format = corefilename; temp = malloc(MAXPATHLEN, M_TEMP, M_NOWAIT | M_ZERO); if (temp == NULL) @@ -3021,8 +3022,21 @@ expand_name(const char *name, uid_t uid, pid_t pid, struct thread *td, sbuf_putc(&sb, '%'); break; case 'H': /* hostname */ + if (hostname == NULL) { + hostname = malloc(MAXHOSTNAMELEN, + M_TEMP, M_NOWAIT); + if (hostname == NULL) { + log(LOG_ERR, + "pid %ld (%s), uid (%lu): " + "unable to alloc memory " + "for corefile hostname\n", + (long)pid, name, + (u_long)uid); + goto nomem; + } + } getcredhostname(td->td_ucred, hostname, - sizeof(hostname)); + MAXHOSTNAMELEN); sbuf_printf(&sb, "%s", hostname); break; case 'I': /* autoincrementing index */ @@ -3048,15 +3062,17 @@ expand_name(const char *name, uid_t uid, pid_t pid, struct thread *td, sbuf_putc(&sb, format[i]); } } + free(hostname, M_TEMP); #ifdef COMPRESS_USER_CORES if (compress) { sbuf_printf(&sb, GZ_SUFFIX); } #endif if (sbuf_overflowed(&sb)) { - sbuf_delete(&sb); log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too " "long\n", (long)pid, name, (u_long)uid); +nomem: + sbuf_delete(&sb); free(temp, M_TEMP); return (NULL); } -- cgit v1.1 From 1b686893cdbadb33e1155983d5c48f4ec91e6cd1 Mon Sep 17 00:00:00 2001 From: kmacy Date: Fri, 30 Apr 2010 03:26:12 +0000 Subject: merge 194209 in to the i386/xen pmap requested by: alc@ --- sys/i386/xen/pmap.c | 93 +++++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index ec96ef0..1bd081f 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -289,6 +289,12 @@ SYSCTL_INT(_vm_pmap, OID_AUTO, pv_entry_max, CTLFLAG_RD, &pv_entry_max, 0, "Max number of PV entries"); SYSCTL_INT(_vm_pmap, OID_AUTO, shpgperproc, CTLFLAG_RD, &shpgperproc, 0, "Page share factor per proc"); +SYSCTL_NODE(_vm_pmap, OID_AUTO, pde, CTLFLAG_RD, 0, + "2/4MB page mapping counters"); + +static u_long pmap_pde_mappings; +SYSCTL_ULONG(_vm_pmap_pde, OID_AUTO, mappings, CTLFLAG_RD, + &pmap_pde_mappings, 0, "2/4MB page mappings"); static void free_pv_entry(pmap_t pmap, pv_entry_t pv); static pv_entry_t get_pv_entry(pmap_t locked_pmap, int try); @@ -3130,64 +3136,59 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, vm_pindex_t pindex, vm_size_t size) { + pd_entry_t *pde; + vm_paddr_t pa, ptepa; vm_page_t p; + int pat_mode; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); KASSERT(object->type == OBJT_DEVICE || object->type == OBJT_SG, ("pmap_object_init_pt: non-device object")); if (pseflag && - ((addr & (NBPDR - 1)) == 0) && ((size & (NBPDR - 1)) == 0)) { - int i; - vm_page_t m[1]; - unsigned int ptepindex; - int npdes; - pd_entry_t ptepa; - - PMAP_LOCK(pmap); - if (pmap->pm_pdir[ptepindex = (addr >> PDRSHIFT)]) - goto out; - PMAP_UNLOCK(pmap); -retry: + (addr & (NBPDR - 1)) == 0 && (size & (NBPDR - 1)) == 0) { + if (!vm_object_populate(object, pindex, pindex + atop(size))) + return; p = vm_page_lookup(object, pindex); - if (p != NULL) { - if (vm_page_sleep_if_busy(p, FALSE, "init4p")) - goto retry; - } else { - p = vm_page_alloc(object, pindex, VM_ALLOC_NORMAL); - if (p == NULL) - return; - m[0] = p; - - if (vm_pager_get_pages(object, m, 1, 0) != VM_PAGER_OK) { - vm_page_lock_queues(); - vm_page_free(p); - vm_page_unlock_queues(); - return; - } - - p = vm_page_lookup(object, pindex); - vm_page_wakeup(p); - } - + KASSERT(p->valid == VM_PAGE_BITS_ALL, + ("pmap_object_init_pt: invalid page %p", p)); + pat_mode = p->md.pat_mode; + /* + * Abort the mapping if the first page is not physically + * aligned to a 2/4MB page boundary. + */ ptepa = VM_PAGE_TO_PHYS(p); if (ptepa & (NBPDR - 1)) return; - - p->valid = VM_PAGE_BITS_ALL; - + /* + * Skip the first page. Abort the mapping if the rest of + * the pages are not physically contiguous or have differing + * memory attributes. + */ + p = TAILQ_NEXT(p, listq); + for (pa = ptepa + PAGE_SIZE; pa < ptepa + size; + pa += PAGE_SIZE) { + KASSERT(p->valid == VM_PAGE_BITS_ALL, + ("pmap_object_init_pt: invalid page %p", p)); + if (pa != VM_PAGE_TO_PHYS(p) || + pat_mode != p->md.pat_mode) + return; + p = TAILQ_NEXT(p, listq); + } + /* Map using 2/4MB pages. */ PMAP_LOCK(pmap); - pmap->pm_stats.resident_count += size >> PAGE_SHIFT; - npdes = size >> PDRSHIFT; - critical_enter(); - for(i = 0; i < npdes; i++) { - PD_SET_VA(pmap, ptepindex, - ptepa | PG_U | PG_M | PG_RW | PG_V | PG_PS, FALSE); - ptepa += NBPDR; - ptepindex += 1; + for (pa = ptepa | pmap_cache_bits(pat_mode, 1); pa < ptepa + + size; pa += NBPDR) { + pde = pmap_pde(pmap, addr); + if (*pde == 0) { + pde_store(pde, pa | PG_PS | PG_M | PG_A | + PG_U | PG_RW | PG_V); + pmap->pm_stats.resident_count += NBPDR / + PAGE_SIZE; + pmap_pde_mappings++; + } + /* Else continue on if the PDE is already valid. */ + addr += NBPDR; } - pmap_invalidate_all(pmap); - critical_exit(); -out: PMAP_UNLOCK(pmap); } } -- cgit v1.1 From ae5c8abad9e011d84fbe6f903242c206fb4d5e5d Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 30 Apr 2010 04:21:22 +0000 Subject: - Use the path to the filesystem mountpoint to look up the statfs structure so that we correctly reload. Note that tunefs doesn't properly detect the need to reload if the disk device is specified for a read-only mounted filesystem. - Lessen the contiguity requirement for the journal so that it is more likely to succeed. --- sbin/tunefs/tunefs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c index a10b35d..7987620 100644 --- a/sbin/tunefs/tunefs.c +++ b/sbin/tunefs/tunefs.c @@ -280,9 +280,9 @@ main(int argc, char *argv[]) if (ufs_disk_fillout(&disk, special) == -1) goto err; if (disk.d_name != special) { - special = disk.d_name; - if (statfs(special, &stfs) == 0 && - strcmp(special, stfs.f_mntonname) == 0) + if (statfs(special, &stfs) != 0) + warn("Can't stat %s", special); + if (strcmp(special, stfs.f_mntonname) == 0) active = 1; } @@ -546,7 +546,7 @@ journal_balloc(void) * Try to minimize fragmentation by requiring a minimum * number of blocks present. */ - if (cgp->cg_cs.cs_nbfree > blocks / 8) + if (cgp->cg_cs.cs_nbfree > 128 * 1024 * 1024) break; if (contig == 0 && cgp->cg_cs.cs_nbfree) break; -- cgit v1.1 From 86ba030e212082976c91dd5151f22b3d40b7dec0 Mon Sep 17 00:00:00 2001 From: trasz Date: Fri, 30 Apr 2010 07:09:13 +0000 Subject: Avoid undefined behaviour. Reviewed by: zec@ --- sys/netgraph/ng_pipe.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sys/netgraph/ng_pipe.c b/sys/netgraph/ng_pipe.c index a094646..a454624 100644 --- a/sys/netgraph/ng_pipe.c +++ b/sys/netgraph/ng_pipe.c @@ -816,14 +816,17 @@ pipe_dequeue(struct hookinfo *hinfo, struct timeval *now) { } /* Randomly discard the frame, according to BER setting */ - if (hinfo->cfg.ber && - ((oldrand = rand) ^ (rand = random())<<17) >= - hinfo->ber_p[priv->overhead + m->m_pkthdr.len] ) { - hinfo->stats.out_disc_frames++; - hinfo->stats.out_disc_octets += m->m_pkthdr.len; - uma_zfree(ngp_zone, ngp_h); - m_freem(m); - continue; + if (hinfo->cfg.ber) { + oldrand = rand; + rand = random(); + if (((oldrand ^ rand) << 17) >= + hinfo->ber_p[priv->overhead + m->m_pkthdr.len]) { + hinfo->stats.out_disc_frames++; + hinfo->stats.out_disc_octets += m->m_pkthdr.len; + uma_zfree(ngp_zone, ngp_h); + m_freem(m); + continue; + } } /* Discard frame if outbound queue size limit exceeded */ -- cgit v1.1 From d524410a5a600b3476f0f4fee4bc985c85ca2ee6 Mon Sep 17 00:00:00 2001 From: mm Date: Fri, 30 Apr 2010 07:48:29 +0000 Subject: Fix improper pool write throughput calculation. OpenSolaris onnv revision: 9366:17553395a745 PR: kern/146108 Approved by: pjd, delphij (mentor) Obtained from: OpenSolaris, Bug ID 6817339 MFC after: 2 weeks --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c index 03af3d1..58a79ca 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c @@ -300,6 +300,7 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg) tx = dmu_tx_create_assigned(dp, txg); dp->dp_read_overhead = 0; + start = gethrtime(); zio = zio_root(dp->dp_spa, NULL, NULL, ZIO_FLAG_MUSTSUCCEED); while (ds = txg_list_remove(&dp->dp_dirty_datasets, txg)) { if (!list_link_active(&ds->ds_synced_link)) @@ -310,7 +311,6 @@ dsl_pool_sync(dsl_pool_t *dp, uint64_t txg) } DTRACE_PROBE(pool_sync__1setup); - start = gethrtime(); err = zio_wait(zio); write_time = gethrtime() - start; ASSERT(err == 0); -- cgit v1.1 From 828890193b9780d1a0af04d39628b97d99311d00 Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 30 Apr 2010 07:56:21 +0000 Subject: Report PMP absence using target 15, same as for precence (not a wildcard), to not confuse target ID checks at SIMs. --- sys/cam/ata/ata_xpt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c index 10e6182..bd748cd 100644 --- a/sys/cam/ata/ata_xpt.c +++ b/sys/cam/ata/ata_xpt.c @@ -1118,13 +1118,13 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) work_ccb = request_ccb; /* Reuse the same CCB to query if a device was really found */ scan_info = (ata_scan_bus_info *)work_ccb->ccb_h.ppriv_ptr0; - /* Free the current request path- we're done with it. */ - xpt_free_path(work_ccb->ccb_h.path); /* If there is PMP... */ if ((scan_info->cpi->hba_inquiry & PI_SATAPM) && (scan_info->counter == scan_info->cpi->max_target)) { if (work_ccb->ccb_h.status == CAM_REQ_CMP) { - /* everything else willbe probed by it */ + /* everything else will be probed by it */ + /* Free the current request path- we're done with it. */ + xpt_free_path(work_ccb->ccb_h.path); goto done; } else { struct ccb_trans_settings cts; @@ -1132,7 +1132,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) /* Report SIM that PM is absent. */ bzero(&cts, sizeof(cts)); xpt_setup_ccb(&cts.ccb_h, - scan_info->request_ccb->ccb_h.path, 1); + work_ccb->ccb_h.path, CAM_PRIORITY_NONE); cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; cts.type = CTS_TYPE_CURRENT_SETTINGS; cts.xport_specific.sata.pm_present = 0; @@ -1140,6 +1140,8 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb) xpt_action((union ccb *)&cts); } } + /* Free the current request path- we're done with it. */ + xpt_free_path(work_ccb->ccb_h.path); if (scan_info->counter == ((scan_info->cpi->hba_inquiry & PI_SATAPM) ? 0 : scan_info->cpi->max_target)) { -- cgit v1.1 From 295ded74b5ac2fe3cda912075510e8e010fc592a Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 30 Apr 2010 08:02:12 +0000 Subject: Add Target/LUN ID checks and deny access to targets 1-14 when PMP absent. Enforce PMA bit clearing when PMP detached to avoid further scan timeouts. --- sys/dev/ahci/ahci.c | 69 +++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 5d39968..34f1be4 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -2083,6 +2083,7 @@ ahci_start(device_t dev, int fbs) } /* Start operations on this channel */ cmd = ATA_INL(ch->r_mem, AHCI_P_CMD); + cmd &= ~AHCI_P_CMD_PMA; ATA_OUTL(ch->r_mem, AHCI_P_CMD, cmd | AHCI_P_CMD_ST | (ch->pm_present ? AHCI_P_CMD_PMA : 0)); } @@ -2381,6 +2382,24 @@ ahci_sata_phy_reset(device_t dev) return (1); } +static int +ahci_check_ids(device_t dev, union ccb *ccb) +{ + struct ahci_channel *ch = device_get_softc(dev); + + if (ccb->ccb_h.target_id > ((ch->caps & AHCI_CAP_SPM) ? 15 : 0)) { + ccb->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return (-1); + } + if (ccb->ccb_h.target_lun != 0) { + ccb->ccb_h.status = CAM_LUN_INVALID; + xpt_done(ccb); + return (-1); + } + return (0); +} + static void ahciaction(struct cam_sim *sim, union ccb *ccb) { @@ -2396,9 +2415,12 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) /* Common cases first */ case XPT_ATA_IO: /* Execute the requested I/O operation */ case XPT_SCSI_IO: - if (ch->devices == 0) { + if (ahci_check_ids(dev, ccb)) + return; + if (ch->devices == 0 || + (ch->pm_present == 0 && + ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) { ccb->ccb_h.status = CAM_SEL_TIMEOUT; - xpt_done(ccb); break; } /* Check for command collision. */ @@ -2410,7 +2432,7 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) return; } ahci_begin_transaction(dev, ccb); - break; + return; case XPT_EN_LUN: /* Enable LUN as a target */ case XPT_TARGET_IO: /* Execute target I/O request */ case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ @@ -2418,13 +2440,14 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) case XPT_ABORT: /* Abort the specified CCB */ /* XXX Implement */ ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; case XPT_SET_TRAN_SETTINGS: { struct ccb_trans_settings *cts = &ccb->cts; struct ahci_device *d; + if (ahci_check_ids(dev, ccb)) + return; if (cts->type == CTS_TYPE_CURRENT_SETTINGS) d = &ch->curr[ccb->ccb_h.target_id]; else @@ -2442,7 +2465,6 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI) d->atapi = cts->xport_specific.sata.atapi; ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } case XPT_GET_TRAN_SETTINGS: @@ -2452,6 +2474,8 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) struct ahci_device *d; uint32_t status; + if (ahci_check_ids(dev, ccb)) + return; if (cts->type == CTS_TYPE_CURRENT_SETTINGS) d = &ch->curr[ccb->ccb_h.target_id]; else @@ -2487,48 +2511,16 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) cts->xport_specific.sata.atapi = d->atapi; cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI; ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } -#if 0 - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg; - uint32_t size_mb; - uint32_t secs_per_cylinder; - - ccg = &ccb->ccg; - size_mb = ccg->volume_size - / ((1024L * 1024L) / ccg->block_size); - if (size_mb >= 1024 && (aha->extended_trans != 0)) { - if (size_mb >= 2048) { - ccg->heads = 255; - ccg->secs_per_track = 63; - } else { - ccg->heads = 128; - ccg->secs_per_track = 32; - } - } else { - ccg->heads = 64; - ccg->secs_per_track = 32; - } - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } -#endif case XPT_RESET_BUS: /* Reset the specified SCSI bus */ case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ ahci_reset(dev); ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; case XPT_TERM_IO: /* Terminate the I/O process */ /* XXX Implement */ ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; case XPT_PATH_INQ: /* Path routing inquiry */ { @@ -2564,14 +2556,13 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) if (pci_get_devid(device_get_parent(dev)) == 0x43801002) cpi->maxio = min(cpi->maxio, 128 * 512); cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } default: ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; } + xpt_done(ccb); } static void -- cgit v1.1 From 4137ab7278be374a5f49e3baea52bbb5c8e7543f Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 30 Apr 2010 08:22:47 +0000 Subject: Add Target/LUN ID checks and deny access to targets 1-14 when PMP absent. --- sys/dev/siis/siis.c | 67 ++++++++++++++++++++++------------------------------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c index c9c1572..c60d8e4 100644 --- a/sys/dev/siis/siis.c +++ b/sys/dev/siis/siis.c @@ -1610,6 +1610,23 @@ siis_sata_connect(struct siis_channel *ch) return (1); } +static int +siis_check_ids(device_t dev, union ccb *ccb) +{ + + if (ccb->ccb_h.target_id > 15) { + ccb->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return (-1); + } + if (ccb->ccb_h.target_lun != 0) { + ccb->ccb_h.status = CAM_LUN_INVALID; + xpt_done(ccb); + return (-1); + } + return (0); +} + static void siisaction(struct cam_sim *sim, union ccb *ccb) { @@ -1626,9 +1643,12 @@ siisaction(struct cam_sim *sim, union ccb *ccb) /* Common cases first */ case XPT_ATA_IO: /* Execute the requested I/O operation */ case XPT_SCSI_IO: - if (ch->devices == 0) { + if (siis_check_ids(dev, ccb)) + return; + if (ch->devices == 0 || + (ch->pm_present == 0 && + ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) { ccb->ccb_h.status = CAM_SEL_TIMEOUT; - xpt_done(ccb); break; } /* Check for command collision. */ @@ -1640,7 +1660,7 @@ siisaction(struct cam_sim *sim, union ccb *ccb) return; } siis_begin_transaction(dev, ccb); - break; + return; case XPT_EN_LUN: /* Enable LUN as a target */ case XPT_TARGET_IO: /* Execute target I/O request */ case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ @@ -1648,13 +1668,14 @@ siisaction(struct cam_sim *sim, union ccb *ccb) case XPT_ABORT: /* Abort the specified CCB */ /* XXX Implement */ ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; case XPT_SET_TRAN_SETTINGS: { struct ccb_trans_settings *cts = &ccb->cts; struct siis_device *d; + if (siis_check_ids(dev, ccb)) + return; if (cts->type == CTS_TYPE_CURRENT_SETTINGS) d = &ch->curr[ccb->ccb_h.target_id]; else @@ -1677,7 +1698,6 @@ siisaction(struct cam_sim *sim, union ccb *ccb) if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS) d->atapi = cts->xport_specific.sata.atapi; ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } case XPT_GET_TRAN_SETTINGS: @@ -1687,6 +1707,8 @@ siisaction(struct cam_sim *sim, union ccb *ccb) struct siis_device *d; uint32_t status; + if (siis_check_ids(dev, ccb)) + return; if (cts->type == CTS_TYPE_CURRENT_SETTINGS) d = &ch->curr[ccb->ccb_h.target_id]; else @@ -1722,48 +1744,16 @@ siisaction(struct cam_sim *sim, union ccb *ccb) cts->xport_specific.sata.atapi = d->atapi; cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI; ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } -#if 0 - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg; - uint32_t size_mb; - uint32_t secs_per_cylinder; - - ccg = &ccb->ccg; - size_mb = ccg->volume_size - / ((1024L * 1024L) / ccg->block_size); - if (size_mb >= 1024 && (aha->extended_trans != 0)) { - if (size_mb >= 2048) { - ccg->heads = 255; - ccg->secs_per_track = 63; - } else { - ccg->heads = 128; - ccg->secs_per_track = 32; - } - } else { - ccg->heads = 64; - ccg->secs_per_track = 32; - } - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } -#endif case XPT_RESET_BUS: /* Reset the specified SCSI bus */ case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ siis_reset(dev); ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; case XPT_TERM_IO: /* Terminate the I/O process */ /* XXX Implement */ ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; case XPT_PATH_INQ: /* Path routing inquiry */ { @@ -1790,14 +1780,13 @@ siisaction(struct cam_sim *sim, union ccb *ccb) cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; cpi->ccb_h.status = CAM_REQ_CMP; cpi->maxio = MAXPHYS; - xpt_done(ccb); break; } default: ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; } + xpt_done(ccb); } static void -- cgit v1.1 From 1c92d062edb474dafbad2b4ddc7290843cbfe8f9 Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 30 Apr 2010 08:37:00 +0000 Subject: Add Target/LUN ID checks. --- sys/dev/ata/ata-all.c | 65 +++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 73dfa94..5c6f0db 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -1430,6 +1430,24 @@ ata_cam_end_transaction(device_t dev, struct ata_request *request) ata_reinit(dev); } +static int +ata_check_ids(device_t dev, union ccb *ccb) +{ + struct ata_channel *ch = device_get_softc(dev); + + if (ccb->ccb_h.target_id > ((ch->flags & ATA_NO_SLAVE) ? 0 : 1)) { + ccb->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return (-1); + } + if (ccb->ccb_h.target_lun != 0) { + ccb->ccb_h.status = CAM_LUN_INVALID; + xpt_done(ccb); + return (-1); + } + return (0); +} + static void ataaction(struct cam_sim *sim, union ccb *ccb) { @@ -1445,10 +1463,11 @@ ataaction(struct cam_sim *sim, union ccb *ccb) /* Common cases first */ case XPT_ATA_IO: /* Execute the requested I/O operation */ case XPT_SCSI_IO: + if (ata_check_ids(dev, ccb)) + return; if ((ch->devices & ((ATA_ATA_MASTER | ATA_ATAPI_MASTER) << ccb->ccb_h.target_id)) == 0) { ccb->ccb_h.status = CAM_SEL_TIMEOUT; - xpt_done(ccb); break; } if (ch->running) @@ -1467,11 +1486,10 @@ ataaction(struct cam_sim *sim, union ccb *ccb) res->lba_mid = 0x14; } ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } ata_cam_begin_transaction(dev, ccb); - break; + return; case XPT_EN_LUN: /* Enable LUN as a target */ case XPT_TARGET_IO: /* Execute target I/O request */ case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ @@ -1479,13 +1497,14 @@ ataaction(struct cam_sim *sim, union ccb *ccb) case XPT_ABORT: /* Abort the specified CCB */ /* XXX Implement */ ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; case XPT_SET_TRAN_SETTINGS: { struct ccb_trans_settings *cts = &ccb->cts; struct ata_cam_device *d; + if (ata_check_ids(dev, ccb)) + return; if (cts->type == CTS_TYPE_CURRENT_SETTINGS) d = &ch->curr[ccb->ccb_h.target_id]; else @@ -1520,7 +1539,6 @@ ataaction(struct cam_sim *sim, union ccb *ccb) d->atapi = cts->xport_specific.ata.atapi; } ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } case XPT_GET_TRAN_SETTINGS: @@ -1528,6 +1546,8 @@ ataaction(struct cam_sim *sim, union ccb *ccb) struct ccb_trans_settings *cts = &ccb->cts; struct ata_cam_device *d; + if (ata_check_ids(dev, ccb)) + return; if (cts->type == CTS_TYPE_CURRENT_SETTINGS) d = &ch->curr[ccb->ccb_h.target_id]; else @@ -1567,48 +1587,16 @@ ataaction(struct cam_sim *sim, union ccb *ccb) cts->xport_specific.ata.valid |= CTS_ATA_VALID_ATAPI; } ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } -#if 0 - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg; - uint32_t size_mb; - uint32_t secs_per_cylinder; - - ccg = &ccb->ccg; - size_mb = ccg->volume_size - / ((1024L * 1024L) / ccg->block_size); - if (size_mb >= 1024 && (aha->extended_trans != 0)) { - if (size_mb >= 2048) { - ccg->heads = 255; - ccg->secs_per_track = 63; - } else { - ccg->heads = 128; - ccg->secs_per_track = 32; - } - } else { - ccg->heads = 64; - ccg->secs_per_track = 32; - } - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } -#endif case XPT_RESET_BUS: /* Reset the specified SCSI bus */ case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ ata_reinit(dev); ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; case XPT_TERM_IO: /* Terminate the I/O process */ /* XXX Implement */ ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; case XPT_PATH_INQ: /* Path routing inquiry */ { @@ -1643,14 +1631,13 @@ ataaction(struct cam_sim *sim, union ccb *ccb) cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; cpi->maxio = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS; cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); break; } default: ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); break; } + xpt_done(ccb); } static void -- cgit v1.1 From 99446b1a227e6c51f9fb58242a3265e9d32464fc Mon Sep 17 00:00:00 2001 From: mav Date: Fri, 30 Apr 2010 08:57:03 +0000 Subject: Revert r198705. As scottl@ noticed, max_target/max_lun was intended to be only a hint for existing bus scanner. Some FC/SAS SIMs report fake values there, that are smaller then maximum supported IDs. In that case this check makes impossible manual scan outside hinted range. For ATA/SATA SIMs respective check was instead implemented at SIM level. Newer SCSI SIMs expected to have these checks at driver or firmware level. Some older SCSI SIMs have no this check and the issues will get back there. --- sys/cam/cam_xpt.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index 1812edb..ed05c40 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -467,34 +467,7 @@ xptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td ccb = xpt_alloc_ccb(); CAM_SIM_LOCK(bus->sim); - /* Ensure passed in target/lun supported on this bus. */ - if ((inccb->ccb_h.target_id != CAM_TARGET_WILDCARD) || - (inccb->ccb_h.target_lun != CAM_LUN_WILDCARD)) { - if (xpt_create_path(&ccb->ccb_h.path, - xpt_periph, - inccb->ccb_h.path_id, - CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD) != CAM_REQ_CMP) { - error = EINVAL; - CAM_SIM_UNLOCK(bus->sim); - xpt_free_ccb(ccb); - break; - } - xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, - inccb->ccb_h.pinfo.priority); - ccb->ccb_h.func_code = XPT_PATH_INQ; - xpt_action(ccb); - xpt_free_path(ccb->ccb_h.path); - if ((inccb->ccb_h.target_id != CAM_TARGET_WILDCARD && - inccb->ccb_h.target_id > ccb->cpi.max_target) || - (inccb->ccb_h.target_lun != CAM_LUN_WILDCARD && - inccb->ccb_h.target_lun > ccb->cpi.max_lun)) { - error = EINVAL; - CAM_SIM_UNLOCK(bus->sim); - xpt_free_ccb(ccb); - break; - } - } + /* * Create a path using the bus, target, and lun the * user passed in. -- cgit v1.1 From 306735e614e65ae3de67b0c1c1f74dd76e1583f3 Mon Sep 17 00:00:00 2001 From: philip Date: Fri, 30 Apr 2010 15:12:30 +0000 Subject: Fix typo in usage message. Add -n to the list of valid arguments. MFC after: 1 day --- tools/tools/nanobsd/nanobsd.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh index ce518a5..7afb047 100644 --- a/tools/tools/nanobsd/nanobsd.sh +++ b/tools/tools/nanobsd/nanobsd.sh @@ -682,12 +682,12 @@ pprint() { usage () { ( - echo "Usage: $0 [-bikqvw] [-c config_file]" + echo "Usage: $0 [-biknqvw] [-c config_file]" echo " -b suppress builds (both kernel and world)" echo " -i suppress disk image build" echo " -k suppress buildkernel" echo " -n add -DNO_CLEAN to buildworld, buildkernel, etc" - echo " -q make output more quite" + echo " -q make output more quiet" echo " -v make output more verbose" echo " -w suppress buildworld" echo " -c specify config file" -- cgit v1.1 From 5cccf02a9e818719ef70601ab63344bbcdac7286 Mon Sep 17 00:00:00 2001 From: alc Date: Fri, 30 Apr 2010 15:22:52 +0000 Subject: MFamd64/i386 r207205 Clearing a page table entry's accessed bit and setting the page's PG_REFERENCED flag in pmap_protect() can't really be justified, so don't do it. Additionally, two changes that make this pmap behave like the others do: Change pmap_protect() such that it calls vm_page_dirty() only if the page is managed. Change pmap_remove_write() such that it doesn't clear a page table entry's accessed bit. --- sys/powerpc/booke/pmap.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c index 0b0fce4..78e9afb 100644 --- a/sys/powerpc/booke/pmap.c +++ b/sys/powerpc/booke/pmap.c @@ -1915,16 +1915,11 @@ mmu_booke_protect(mmu_t mmu, pmap_t pmap, vm_offset_t sva, vm_offset_t eva, tlb_miss_lock(); /* Handle modified pages. */ - if (PTE_ISMODIFIED(pte)) + if (PTE_ISMODIFIED(pte) && PTE_ISMANAGED(pte)) vm_page_dirty(m); - /* Referenced pages. */ - if (PTE_ISREFERENCED(pte)) - vm_page_flag_set(m, PG_REFERENCED); - tlb0_flush_entry(va); - pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED | - PTE_REFERENCED); + pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED); tlb_miss_unlock(); mtx_unlock_spin(&tlbivax_mutex); @@ -1962,13 +1957,8 @@ mmu_booke_remove_write(mmu_t mmu, vm_page_t m) if (PTE_ISMODIFIED(pte)) vm_page_dirty(m); - /* Referenced pages. */ - if (PTE_ISREFERENCED(pte)) - vm_page_flag_set(m, PG_REFERENCED); - /* Flush mapping from TLB0. */ - pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED | - PTE_REFERENCED); + pte->flags &= ~(PTE_UW | PTE_SW | PTE_MODIFIED); tlb_miss_unlock(); mtx_unlock_spin(&tlbivax_mutex); -- cgit v1.1 From 96ebc710b900ffe0a980b10e539b88278805741c Mon Sep 17 00:00:00 2001 From: kib Date: Fri, 30 Apr 2010 16:20:14 +0000 Subject: Unlock page lock instead of recursively locking it. --- sys/vm/vm_fault.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index de74915..d9cf63e 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -1284,19 +1284,19 @@ vm_fault_copy_entry(vm_map_t dst_map, vm_map_t src_map, vm_page_lock_queues(); vm_page_unwire(src_m, 0); vm_page_unlock_queues(); - vm_page_lock(src_m); + vm_page_unlock(src_m); vm_page_lock(dst_m); vm_page_lock_queues(); vm_page_wire(dst_m); vm_page_unlock_queues(); - vm_page_lock(dst_m); + vm_page_unlock(dst_m); } else { vm_page_lock(dst_m); vm_page_lock_queues(); vm_page_activate(dst_m); vm_page_unlock_queues(); - vm_page_lock(dst_m); + vm_page_unlock(dst_m); } vm_page_wakeup(dst_m); } -- cgit v1.1 From 3eac0000f02cd2cb160464ae01b04fe3415e4b60 Mon Sep 17 00:00:00 2001 From: zml Date: Fri, 30 Apr 2010 16:29:05 +0000 Subject: Handle taskqueue_drain(9) correctly on a threaded taskqueue: taskqueue_drain(9) will not correctly detect whether a task is currently running. The check is against a field in the taskqueue struct, but for a threaded queue with more than one thread, multiple threads can simultaneously be running a task, thus stomping over the tq_running field. Submitted by: Matthew Fleming Reviewed by: jhb Approved by: dfr (mentor) --- sys/kern/subr_taskqueue.c | 11 ++++++----- sys/sys/_task.h | 16 +++++++++++----- sys/sys/taskqueue.h | 1 + 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index 8405b3d..3b18269 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -51,7 +51,6 @@ struct taskqueue { const char *tq_name; taskqueue_enqueue_fn tq_enqueue; void *tq_context; - struct task *tq_running; struct mtx tq_mutex; struct thread **tq_threads; int tq_tcount; @@ -233,13 +232,13 @@ taskqueue_run(struct taskqueue *queue) STAILQ_REMOVE_HEAD(&queue->tq_queue, ta_link); pending = task->ta_pending; task->ta_pending = 0; - queue->tq_running = task; + task->ta_flags |= TA_FLAGS_RUNNING; TQ_UNLOCK(queue); task->ta_func(task->ta_context, pending); TQ_LOCK(queue); - queue->tq_running = NULL; + task->ta_flags &= ~TA_FLAGS_RUNNING; wakeup(task); } @@ -256,14 +255,16 @@ taskqueue_drain(struct taskqueue *queue, struct task *task) { if (queue->tq_spin) { /* XXX */ mtx_lock_spin(&queue->tq_mutex); - while (task->ta_pending != 0 || task == queue->tq_running) + while (task->ta_pending != 0 || + (task->ta_flags & TA_FLAGS_RUNNING) != 0) msleep_spin(task, &queue->tq_mutex, "-", 0); mtx_unlock_spin(&queue->tq_mutex); } else { WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, __func__); mtx_lock(&queue->tq_mutex); - while (task->ta_pending != 0 || task == queue->tq_running) + while (task->ta_pending != 0 || + (task->ta_flags & TA_FLAGS_RUNNING) != 0) msleep(task, &queue->tq_mutex, PWAIT, "-", 0); mtx_unlock(&queue->tq_mutex); } diff --git a/sys/sys/_task.h b/sys/sys/_task.h index 2a51e1b..781cd48 100644 --- a/sys/sys/_task.h +++ b/sys/sys/_task.h @@ -36,15 +36,21 @@ * taskqueue_run(). The first argument is taken from the 'ta_context' * field of struct task and the second argument is a count of how many * times the task was enqueued before the call to taskqueue_run(). + * + * List of locks + * (c) const after init + * (q) taskqueue lock */ typedef void task_fn_t(void *context, int pending); struct task { - STAILQ_ENTRY(task) ta_link; /* link for queue */ - u_short ta_pending; /* count times queued */ - u_short ta_priority; /* Priority */ - task_fn_t *ta_func; /* task handler */ - void *ta_context; /* argument for handler */ + STAILQ_ENTRY(task) ta_link; /* (q) link for queue */ + u_int ta_flags; /* (q) state of this task */ +#define TA_FLAGS_RUNNING 0x01 + u_short ta_pending; /* (q) count times queued */ + u_short ta_priority; /* (c) Priority */ + task_fn_t *ta_func; /* (c) task handler */ + void *ta_context; /* (c) argument for handler */ }; #endif /* !_SYS__TASK_H_ */ diff --git a/sys/sys/taskqueue.h b/sys/sys/taskqueue.h index bf2e4ee..fa8897d 100644 --- a/sys/sys/taskqueue.h +++ b/sys/sys/taskqueue.h @@ -75,6 +75,7 @@ void taskqueue_thread_enqueue(void *context); (task)->ta_priority = (priority); \ (task)->ta_func = (func); \ (task)->ta_context = (context); \ + (task)->ta_flags = 0; \ } while (0) /* -- cgit v1.1 From c5fa73f93d7d28784831dd890d6c32a9a2ba9c32 Mon Sep 17 00:00:00 2001 From: rrs Date: Fri, 30 Apr 2010 17:12:20 +0000 Subject: Bug in the memory mapping module. The wrong physaddr was being used in the macro (1 should be used not 2)... Obtained from: JC --- sys/mips/mips/pmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/mips/mips/pmap.c b/sys/mips/mips/pmap.c index 826177f..af9ef43 100644 --- a/sys/mips/mips/pmap.c +++ b/sys/mips/mips/pmap.c @@ -236,7 +236,7 @@ caddr_t virtual_sys_start = (caddr_t)0; sched_pin(); \ va1 = sysm->base; \ va2 = sysm->base + PAGE_SIZE; \ - npte = mips_paddr_to_tlbpfn(phys2) | \ + npte = mips_paddr_to_tlbpfn(phys1) | \ PTE_RW | PTE_V | PTE_G | PTE_W | PTE_CACHE; \ pte = pmap_pte(kernel_pmap, va1); \ *pte = npte; \ -- cgit v1.1 From 90bf77c71267bf38221fa717f6fac628910d2a8e Mon Sep 17 00:00:00 2001 From: yongari Date: Fri, 30 Apr 2010 18:04:46 +0000 Subject: Disable non-ASF packet flushing on Yukon Extreme as vendor's driver does. Without this change, Yukon Extreme seems to generate lots of RX FIFO overruns even though controller has available RX buffers. These excessive RX FIFO overruns generated lots of pause frames which in turn killed devices plugged into switch. It seems there is still occasional RX frame corruption on Yukon Extreme but this change seems to fix the pause frame storm. Reported by: jhb Tested by: jhb MFC after: 5 days --- sys/dev/msk/if_msk.c | 5 +++++ sys/dev/msk/if_mskreg.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c index 9b92435..fbae30b 100644 --- a/sys/dev/msk/if_msk.c +++ b/sys/dev/msk/if_msk.c @@ -3917,6 +3917,11 @@ msk_init_locked(struct msk_if_softc *sc_if) msk_stop(sc_if); return; } + if (sc->msk_hw_id == CHIP_ID_YUKON_EX) { + /* Disable flushing of non-ASF packets. */ + CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T), + GMF_RX_MACSEC_FLUSH_OFF); + } /* Configure interrupt handling. */ if (sc_if->msk_port == MSK_PORT_A) { diff --git a/sys/dev/msk/if_mskreg.h b/sys/dev/msk/if_mskreg.h index 293ca29..3e8ae47 100644 --- a/sys/dev/msk/if_mskreg.h +++ b/sys/dev/msk/if_mskreg.h @@ -1941,6 +1941,8 @@ #define RX_TRUNC_OFF BIT_26 /* disable packet truncation */ #define RX_VLAN_STRIP_ON BIT_25 /* enable VLAN stripping */ #define RX_VLAN_STRIP_OFF BIT_24 /* disable VLAN stripping */ +#define GMF_RX_MACSEC_FLUSH_ON BIT_23 +#define GMF_RX_MACSEC_FLUSH_OFF BIT_22 #define GMF_RX_OVER_ON BIT_19 /* enable flushing on receive overrun */ #define GMF_RX_OVER_OFF BIT_18 /* disable flushing on receive overrun */ #define GMF_ASF_RX_OVER_ON BIT_17 /* enable flushing of ASF when overrun */ -- cgit v1.1 From 7a0b6f8a32672cdf476aaff405247a7f4a38d97e Mon Sep 17 00:00:00 2001 From: yongari Date: Fri, 30 Apr 2010 18:58:55 +0000 Subject: Add basic support for Marvell 88E8059 Yukon Optima. Tested by: James LaLagna < jameslalagna <> gmail dot com > MFC after: 5 days --- sys/dev/msk/if_msk.c | 20 +++++++++++++++++--- sys/dev/msk/if_mskreg.h | 6 ++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c index fbae30b..e15ccfe 100644 --- a/sys/dev/msk/if_msk.c +++ b/sys/dev/msk/if_msk.c @@ -223,6 +223,8 @@ static struct msk_product { "Marvell Yukon 88E8072 Gigabit Ethernet" }, { VENDORID_MARVELL, DEVICEID_MRVL_4380, "Marvell Yukon 88E8057 Gigabit Ethernet" }, + { VENDORID_MARVELL, DEVICEID_MRVL_4381, + "Marvell Yukon 88E8059 Gigabit Ethernet" }, { VENDORID_DLINK, DEVICEID_DLINK_DGE550SX, "D-Link 550SX Gigabit Ethernet" }, { VENDORID_DLINK, DEVICEID_DLINK_DGE560SX, @@ -239,7 +241,9 @@ static const char *model_name[] = { "Yukon FE", "Yukon FE+", "Yukon Supreme", - "Yukon Ultra 2" + "Yukon Ultra 2", + "Yukon Unknown", + "Yukon Optima", }; static int mskc_probe(device_t); @@ -1229,6 +1233,7 @@ msk_phy_power(struct msk_softc *sc, int mode) case CHIP_ID_YUKON_EX: case CHIP_ID_YUKON_FE_P: case CHIP_ID_YUKON_UL_2: + case CHIP_ID_YUKON_OPT: CSR_WRITE_2(sc, B0_CTST, Y2_HW_WOL_OFF); /* Enable all clocks. */ @@ -1372,6 +1377,10 @@ mskc_reset(struct msk_softc *sc) GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON | GMC_BYP_RETR_ON); } + if (sc->msk_hw_id == CHIP_ID_YUKON_OPT && sc->msk_hw_rev == 0) { + /* Disable PCIe PHY powerdown(reg 0x80, bit7). */ + CSR_WRITE_4(sc, Y2_PEX_PHY_DATA, (0x0080 << 16) | 0x0080); + } CSR_WRITE_1(sc, B2_TST_CTRL1, TST_CFG_WRITE_OFF); /* LED On. */ @@ -1705,8 +1714,9 @@ mskc_attach(device_t dev) sc->msk_hw_rev = (CSR_READ_1(sc, B2_MAC_CFG) >> 4) & 0x0f; /* Bail out if chip is not recognized. */ if (sc->msk_hw_id < CHIP_ID_YUKON_XL || - sc->msk_hw_id > CHIP_ID_YUKON_UL_2 || - sc->msk_hw_id == CHIP_ID_YUKON_SUPR) { + sc->msk_hw_id > CHIP_ID_YUKON_OPT || + sc->msk_hw_id == CHIP_ID_YUKON_SUPR || + sc->msk_hw_id == CHIP_ID_YUKON_UNKNOWN) { device_printf(dev, "unknown device: id=0x%02x, rev=0x%02x\n", sc->msk_hw_id, sc->msk_hw_rev); mtx_destroy(&sc->msk_mtx); @@ -1819,6 +1829,10 @@ mskc_attach(device_t dev) sc->msk_clock = 125; /* 125 MHz */ sc->msk_pflags |= MSK_FLAG_JUMBO; break; + case CHIP_ID_YUKON_OPT: + sc->msk_clock = 125; /* 125 MHz */ + sc->msk_pflags |= MSK_FLAG_JUMBO | MSK_FLAG_DESCV2; + break; default: sc->msk_clock = 156; /* 156 MHz */ break; diff --git a/sys/dev/msk/if_mskreg.h b/sys/dev/msk/if_mskreg.h index 3e8ae47..3b05b9b 100644 --- a/sys/dev/msk/if_mskreg.h +++ b/sys/dev/msk/if_mskreg.h @@ -145,6 +145,7 @@ #define DEVICEID_MRVL_436B 0x436B #define DEVICEID_MRVL_436C 0x436C #define DEVICEID_MRVL_4380 0x4380 +#define DEVICEID_MRVL_4381 0x4381 /* * D-Link gigabit ethernet device ID @@ -828,6 +829,9 @@ #define Y2_IS_CHK_RX2 BIT_10 /* Descriptor error Rx 2 */ #define Y2_IS_CHK_TXS2 BIT_9 /* Descriptor error TXS 2 */ #define Y2_IS_CHK_TXA2 BIT_8 /* Descriptor error TXA 2 */ +#define Y2_IS_PSM_ACK BIT_7 /* PSM Ack (Yukon Optima) */ +#define Y2_IS_PTP_TIST BIT_6 /* PTP TIme Stamp (Yukon Optima) */ +#define Y2_IS_PHY_QLNK BIT_5 /* PHY Quick Link (Yukon Optima) */ #define Y2_IS_IRQ_PHY1 BIT_4 /* Interrupt from PHY 1 */ #define Y2_IS_IRQ_MAC1 BIT_3 /* Interrupt from MAC 1 */ #define Y2_IS_CHK_RX1 BIT_2 /* Descriptor error Rx 1 */ @@ -894,6 +898,8 @@ #define CHIP_ID_YUKON_FE_P 0xb8 /* Chip ID for YUKON-2 FE+ */ #define CHIP_ID_YUKON_SUPR 0xb9 /* Chip ID for YUKON-2 Supreme */ #define CHIP_ID_YUKON_UL_2 0xba /* Chip ID for YUKON-2 Ultra 2 */ +#define CHIP_ID_YUKON_UNKNOWN 0xbb +#define CHIP_ID_YUKON_OPT 0xbc /* Chip ID for YUKON-2 Optima */ #define CHIP_REV_YU_XL_A0 0 /* Chip Rev. for Yukon-2 A0 */ #define CHIP_REV_YU_XL_A1 1 /* Chip Rev. for Yukon-2 A1 */ -- cgit v1.1 From 042dce9b96d452a9cf6a4ce20b58c7c4113ab45d Mon Sep 17 00:00:00 2001 From: yongari Date: Fri, 30 Apr 2010 19:01:55 +0000 Subject: Add Marvell PHYG65G Gigabit PHY which is found on 88E8059 Yukon Optima. Tested by: James LaLagna < jameslalagna <> gmail dot com > MFC after: 5 days --- sys/dev/mii/e1000phy.c | 2 ++ sys/dev/mii/miidevs | 1 + 2 files changed, 3 insertions(+) diff --git a/sys/dev/mii/e1000phy.c b/sys/dev/mii/e1000phy.c index b50eb07..f30f91c 100644 --- a/sys/dev/mii/e1000phy.c +++ b/sys/dev/mii/e1000phy.c @@ -112,6 +112,7 @@ static const struct mii_phydesc e1000phys[] = { MII_PHY_DESC(MARVELL, E1116R), MII_PHY_DESC(MARVELL, E1118), MII_PHY_DESC(MARVELL, E3016), + MII_PHY_DESC(MARVELL, PHYG65G), MII_PHY_DESC(xxMARVELL, E1000), MII_PHY_DESC(xxMARVELL, E1011), MII_PHY_DESC(xxMARVELL, E1000_3), @@ -230,6 +231,7 @@ e1000phy_reset(struct mii_softc *sc) case MII_MODEL_MARVELL_E1116: case MII_MODEL_MARVELL_E1118: case MII_MODEL_MARVELL_E1149: + case MII_MODEL_MARVELL_PHYG65G: /* Disable energy detect mode. */ reg &= ~E1000_SCR_EN_DETECT_MASK; reg |= E1000_SCR_AUTO_X_MODE; diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs index 30cd09c..bbf668b 100644 --- a/sys/dev/mii/miidevs +++ b/sys/dev/mii/miidevs @@ -247,6 +247,7 @@ model MARVELL E1116 0x0021 Marvell 88E1116 Gigabit PHY model MARVELL E1116R 0x0024 Marvell 88E1116R Gigabit PHY model MARVELL E1118 0x0022 Marvell 88E1118 Gigabit PHY model MARVELL E3016 0x0026 Marvell 88E3016 10/100 Fast Ethernet PHY +model MARVELL PHYG65G 0x0027 Marvell PHYG65G Gigabit PHY model xxMARVELL E1000 0x0005 Marvell 88E1000 Gigabit PHY model xxMARVELL E1011 0x0002 Marvell 88E1011 Gigabit PHY model xxMARVELL E1000_3 0x0003 Marvell 88E1000 Gigabit PHY -- cgit v1.1 From f69bf5326357c99ff7f751d0671bc2ecce5e0664 Mon Sep 17 00:00:00 2001 From: yongari Date: Fri, 30 Apr 2010 19:05:01 +0000 Subject: Marvell 88E8059(Yukon Optima) is now supported. --- share/man/man4/msk.4 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/share/man/man4/msk.4 b/share/man/man4/msk.4 index 7a842f5..7ea12dd 100644 --- a/share/man/man4/msk.4 +++ b/share/man/man4/msk.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd March 1, 2010 +.Dd April 30, 2010 .Dt MSK 4 .Os .Sh NAME @@ -208,6 +208,8 @@ Marvell Yukon 88E8057 Gigabit Ethernet .It Marvell Yukon 88E8058 Gigabit Ethernet .It +Marvell Yukon 88E8059 Gigabit Ethernet +.It Marvell Yukon 88E8070 Gigabit Ethernet .It Marvell Yukon 88E8071 Gigabit Ethernet -- cgit v1.1 From 6b22e476a5f920709982cdffed9a2e1b33e847fc Mon Sep 17 00:00:00 2001 From: kmacy Date: Fri, 30 Apr 2010 19:40:37 +0000 Subject: - don't check hold_count without the page lock held - don't leak the page lock if m->object is NULL (assuming that that check will in fact even be valid when m->object is protected by the page lock) --- sys/vm/vm_pageout.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 95517de..73c51b3 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -775,16 +775,17 @@ rescan0: if (m->flags & PG_MARKER) continue; - /* - * A held page may be undergoing I/O, so skip it. - */ - if (m->hold_count) { - vm_page_requeue(m); + if (!vm_page_trylock(m)) { addl_page_shortage++; continue; } - if (!vm_page_trylock(m) || (object = m->object) == NULL) { + /* + * A held page may be undergoing I/O, so skip it. + */ + if (m->hold_count || (object = m->object) == NULL) { + vm_page_unlock(m); + vm_page_requeue(m); addl_page_shortage++; continue; } -- cgit v1.1 From 0637e80406802fa3e7dba2dd901b803b17051606 Mon Sep 17 00:00:00 2001 From: jilles Date: Fri, 30 Apr 2010 19:52:35 +0000 Subject: telnet: Fix infinite loop if local output generates SIGPIPE. Instead of catching SIGPIPE and jumping out of the signal handler with longjmp, ignore it and handle write errors to the local output by exiting from there. I have changed the error message to mention the local output instead of NetBSD's wrong "Connection closed by foreign host". Write errors to the network were already handled by exiting immediately and this now applies to EPIPE too. The code assumed that SIGPIPE could only be generated by the network connection; if it was generated by the local output, it would longjmp out of the signal handler and write an error message which caused another SIGPIPE. PR: 19773 Obtained from: NetBSD MFC after: 1 week --- contrib/telnet/telnet/commands.c | 3 +-- contrib/telnet/telnet/externs.h | 1 - contrib/telnet/telnet/network.c | 2 +- contrib/telnet/telnet/sys_bsd.c | 10 +--------- contrib/telnet/telnet/telnet.c | 1 - contrib/telnet/telnet/terminal.c | 16 ++++++++++++++-- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/contrib/telnet/telnet/commands.c b/contrib/telnet/telnet/commands.c index a64d763..c39b187 100644 --- a/contrib/telnet/telnet/commands.c +++ b/contrib/telnet/telnet/commands.c @@ -2491,8 +2491,7 @@ tn(int argc, char *argv[]) env_export("USER"); } (void) call(status, "status", "notmuch", 0); - if (setjmp(peerdied) == 0) - telnet(user); + telnet(user); (void) NetClose(net); ExitString("Connection closed by foreign host.\n",1); /*NOTREACHED*/ diff --git a/contrib/telnet/telnet/externs.h b/contrib/telnet/telnet/externs.h index cfa1aec..e07aebb 100644 --- a/contrib/telnet/telnet/externs.h +++ b/contrib/telnet/telnet/externs.h @@ -233,7 +233,6 @@ extern void SetNetTrace(char *); /* Function to change where debugging goes */ extern jmp_buf - peerdied, toplevel; /* For error conditions. */ extern void diff --git a/contrib/telnet/telnet/network.c b/contrib/telnet/telnet/network.c index bb75d63..b140d60 100644 --- a/contrib/telnet/telnet/network.c +++ b/contrib/telnet/telnet/network.c @@ -158,7 +158,7 @@ netflush(void) perror(hostname); (void)NetClose(net); ring_clear_mark(&netoring); - longjmp(peerdied, -1); + ExitString("Connection closed by foreign host.\n", 1); /*NOTREACHED*/ } n = 0; diff --git a/contrib/telnet/telnet/sys_bsd.c b/contrib/telnet/telnet/sys_bsd.c index 45ef1e2..9fba74f 100644 --- a/contrib/telnet/telnet/sys_bsd.c +++ b/contrib/telnet/telnet/sys_bsd.c @@ -809,14 +809,6 @@ NetNonblockingIO(int fd, int onoff) */ /* ARGSUSED */ -static SIG_FUNC_RET -deadpeer(int sig __unused) -{ - setcommandmode(); - longjmp(peerdied, -1); -} - -/* ARGSUSED */ SIG_FUNC_RET intr(int sig __unused) { @@ -884,7 +876,7 @@ sys_telnet_init(void) { (void) signal(SIGINT, intr); (void) signal(SIGQUIT, intr2); - (void) signal(SIGPIPE, deadpeer); + (void) signal(SIGPIPE, SIG_IGN); #ifdef SIGWINCH (void) signal(SIGWINCH, sendwin); #endif diff --git a/contrib/telnet/telnet/telnet.c b/contrib/telnet/telnet/telnet.c index 28237bd..8c457cf 100644 --- a/contrib/telnet/telnet/telnet.c +++ b/contrib/telnet/telnet/telnet.c @@ -146,7 +146,6 @@ unsigned char telopt_environ = TELOPT_NEW_ENVIRON; #endif jmp_buf toplevel; -jmp_buf peerdied; int flushline; int linemode; diff --git a/contrib/telnet/telnet/terminal.c b/contrib/telnet/telnet/terminal.c index 3dda1c5..596c2b8 100644 --- a/contrib/telnet/telnet/terminal.c +++ b/contrib/telnet/telnet/terminal.c @@ -111,7 +111,8 @@ init_terminal(void) } /* - * Send as much data as possible to the terminal. + * Send as much data as possible to the terminal, else exits if + * it encounters a permanent failure when writing to the tty. * * Return value: * -1: No useful work done, data waiting to go out. @@ -152,8 +153,19 @@ ttyflush(int drop) } ring_consumed(&ttyoring, n); } - if (n < 0) + if (n < 0) { + if (errno == EAGAIN || errno == EINTR) { + return -1; + } else { + ring_consumed(&ttyoring, ring_full_count(&ttyoring)); + setconnmode(0); + setcommandmode(); + NetClose(net); + fprintf(stderr, "Write error on local output.\n"); + exit(1); + } return -1; + } if (n == n0) { if (n0) return -1; -- cgit v1.1 From bbf4b0c0bf425448cec9b0e1e4f1898f7f07fd38 Mon Sep 17 00:00:00 2001 From: kmacy Date: Fri, 30 Apr 2010 21:20:14 +0000 Subject: - acquire the page lock in vm_contig_launder_page before checking page fields - release page queue lock before calling vm_pageout_flush --- sys/vm/vm_contig.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index 7220055..2c8b8b1 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -96,30 +96,33 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next) vm_page_t m_tmp; struct vnode *vp; struct mount *mp; - int vfslocked; + int vfslocked, dirty; - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock(m); + vm_page_lock_queues(); object = m->object; if (!VM_OBJECT_TRYLOCK(object) && !vm_pageout_fallback_object_lock(m, next)) { VM_OBJECT_UNLOCK(object); + vm_page_unlock_queues(); + vm_page_unlock(m); return (EAGAIN); } if (vm_page_sleep_if_busy(m, TRUE, "vpctw0")) { VM_OBJECT_UNLOCK(object); - vm_page_lock_queues(); return (EBUSY); } vm_page_test_dirty(m); if (m->dirty == 0 && m->hold_count == 0) pmap_remove_all(m); - if (m->dirty) { + if ((dirty = m->dirty) != 0) { + vm_page_unlock_queues(); + vm_page_unlock(m); if ((object->flags & OBJ_DEAD) != 0) { VM_OBJECT_UNLOCK(object); return (EAGAIN); } if (object->type == OBJT_VNODE) { - vm_page_unlock_queues(); vp = object->handle; vm_object_reference_locked(object); VM_OBJECT_UNLOCK(object); @@ -133,7 +136,6 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next) VFS_UNLOCK_GIANT(vfslocked); vm_object_deallocate(object); vn_finished_write(mp); - vm_page_lock_queues(); return (0); } else if (object->type == OBJT_SWAP || object->type == OBJT_DEFAULT) { @@ -144,6 +146,11 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next) } } else if (m->hold_count == 0) vm_page_cache(m); + + if (dirty == 0) { + vm_page_unlock_queues(); + vm_page_unlock(m); + } VM_OBJECT_UNLOCK(object); return (0); } @@ -162,7 +169,9 @@ vm_contig_launder(int queue) KASSERT(VM_PAGE_INQUEUE2(m, queue), ("vm_contig_launder: page %p's queue is not %d", m, queue)); + vm_page_unlock_queues(); error = vm_contig_launder_page(m, &next); + vm_page_lock_queues(); if (error == 0) return (TRUE); if (error == EBUSY) -- cgit v1.1 From 16fdb0146a9c17f1b387b08ba0fcf4c37ef35ba1 Mon Sep 17 00:00:00 2001 From: kmacy Date: Fri, 30 Apr 2010 21:21:21 +0000 Subject: don't call vm_pageout_flush with the page queue mutex held Reported by: Michael Butler --- sys/vm/vm_object.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 47ef973..7e1cc22 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1058,7 +1058,9 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, } runlen = maxb + maxf + 1; + vm_page_unlock_queues(); vm_pageout_flush(ma, runlen, pagerflags); + vm_page_lock_queues(); for (i = 0; i < runlen; i++) { if (ma[i]->dirty) { vm_page_unlock_queues(); -- cgit v1.1 From 94779e71c30c7ed31273bb723318146a4e2288ba Mon Sep 17 00:00:00 2001 From: kmacy Date: Fri, 30 Apr 2010 22:31:37 +0000 Subject: push up dropping of the page queue lock to avoid holding it in vm_pageout_flush --- sys/vm/vm_object.c | 46 +++++++++++++++++----------------------------- sys/vm/vm_pageout.c | 2 ++ 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 7e1cc22..604aa3c 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -774,6 +774,7 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int int pagerflags; int curgeneration; + mtx_assert(&vm_page_queue_mtx, MA_NOTOWNED); VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); if ((object->flags & OBJ_MIGHTBEDIRTY) == 0) return; @@ -830,13 +831,13 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int ++tscan; continue; } + vm_page_unlock_queues(); + vm_page_unlock(p); /* * If we have been asked to skip nosync pages and * this is a nosync page, we can't continue. */ if ((flags & OBJPC_NOSYNC) && (p->oflags & VPO_NOSYNC)) { - vm_page_unlock_queues(); - vm_page_unlock(p); if (--scanlimit == 0) break; ++tscan; @@ -849,8 +850,7 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int * page (i.e. had to sleep). */ tscan += vm_object_page_collect_flush(object, p, curgeneration, pagerflags); - vm_page_unlock_queues(); - vm_page_unlock(p); + } /* @@ -860,7 +860,6 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int * return immediately. */ if (tscan >= tend && (tstart || tend < object->size)) { - vm_page_unlock_queues(); vm_object_clear_flag(object, OBJ_CLEANING); return; } @@ -918,43 +917,33 @@ again: p->oflags &= ~VPO_CLEANCHK; continue; } - + vm_page_unlock_queues(); + vm_page_unlock(p); /* * If we have been asked to skip nosync pages and this is a * nosync page, skip it. Note that the object flags were * not cleared in this case so we do not have to set them. */ if ((flags & OBJPC_NOSYNC) && (p->oflags & VPO_NOSYNC)) { - vm_page_unlock_queues(); - vm_page_unlock(p); p->oflags &= ~VPO_CLEANCHK; continue; } n = vm_object_page_collect_flush(object, p, curgeneration, pagerflags); - if (n == 0) { - vm_page_unlock_queues(); - vm_page_unlock(p); + if (n == 0) goto rescan; - } - if (object->generation != curgeneration) { - vm_page_unlock_queues(); - vm_page_unlock(p); + if (object->generation != curgeneration) goto rescan; - } /* * Try to optimize the next page. If we can't we pick up * our (random) scan where we left off. */ - if (msync_flush_flags & MSYNC_FLUSH_SOFTSEQ) { - vm_page_unlock_queues(); - vm_page_unlock(p); + if (msync_flush_flags & MSYNC_FLUSH_SOFTSEQ) if ((p = vm_page_lookup(object, pi + n)) != NULL) goto again; - } } #if 0 VOP_FSYNC(vp, (pagerflags & VM_PAGER_PUT_SYNC)?MNT_WAIT:0, curproc); @@ -977,12 +966,11 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, vm_page_t mab[vm_pageout_page_count]; vm_page_t ma[vm_pageout_page_count]; - mtx_assert(&vm_page_queue_mtx, MA_OWNED); - vm_page_lock_assert(p, MA_OWNED); + mtx_assert(&vm_page_queue_mtx, MA_NOTOWNED); + vm_page_lock_assert(p, MA_NOTOWNED); + VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); pi = p->pindex; while (vm_page_sleep_if_busy(p, TRUE, "vpcwai")) { - vm_page_lock(p); - vm_page_lock_queues(); if (object->generation != curgeneration) { return(0); } @@ -997,16 +985,17 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, (tp->oflags & VPO_CLEANCHK) == 0) || (tp->busy != 0)) break; - vm_page_unlock_queues(); vm_page_lock(tp); vm_page_lock_queues(); vm_page_test_dirty(tp); if (tp->dirty == 0) { vm_page_unlock(tp); + vm_page_unlock_queues(); tp->oflags &= ~VPO_CLEANCHK; break; } vm_page_unlock(tp); + vm_page_unlock_queues(); maf[ i - 1 ] = tp; maxf++; continue; @@ -1026,15 +1015,16 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, (tp->oflags & VPO_CLEANCHK) == 0) || (tp->busy != 0)) break; - vm_page_unlock_queues(); vm_page_lock(tp); vm_page_lock_queues(); vm_page_test_dirty(tp); if (tp->dirty == 0) { + vm_page_unlock_queues(); vm_page_unlock(tp); tp->oflags &= ~VPO_CLEANCHK; break; } + vm_page_unlock_queues(); vm_page_unlock(tp); mab[ i - 1 ] = tp; maxb++; @@ -1058,15 +1048,13 @@ vm_object_page_collect_flush(vm_object_t object, vm_page_t p, int curgeneration, } runlen = maxb + maxf + 1; - vm_page_unlock_queues(); vm_pageout_flush(ma, runlen, pagerflags); - vm_page_lock_queues(); for (i = 0; i < runlen; i++) { if (ma[i]->dirty) { - vm_page_unlock_queues(); vm_page_lock(ma[i]); vm_page_lock_queues(); pmap_remove_write(ma[i]); + vm_page_unlock_queues(); vm_page_unlock(ma[i]); ma[i]->oflags |= VPO_CLEANCHK; diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 73c51b3..39a06f8 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -433,6 +433,8 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags) int i; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); + mtx_assert(&vm_page_queue_mtx, MA_NOTOWNED); + /* * Initiate I/O. Bump the vm_page_t->busy counter and * mark the pages read-only. -- cgit v1.1 From 83a9d5d7455091b609ad7183f2a3f9216d8982e0 Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 30 Apr 2010 22:33:49 +0000 Subject: Remove WNOHANG flag from wait3(). Because script(1) now reliably terminates when the TTY is closed, it may be the case that the call to wait3() occurs just before the child process exits. This causes error codes to be ignored. Just change script(1) to use waitpid() instead of wait3(). This makes it more portable and prevents the need for a loop, since waitpid() only returns a specified process. PR: bin/146189 Tested by: amdmi3@, older version MFC after: 2 weeks --- usr.bin/script/script.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/usr.bin/script/script.c b/usr.bin/script/script.c index 6c4e0ee..a21785a 100644 --- a/usr.bin/script/script.c +++ b/usr.bin/script/script.c @@ -219,23 +219,17 @@ usage(void) void finish(void) { - pid_t pid; - int die, e, status; + int e, status; - die = e = 0; - while ((pid = wait3(&status, WNOHANG, 0)) > 0) - if (pid == child) { - die = 1; - if (WIFEXITED(status)) - e = WEXITSTATUS(status); - else if (WIFSIGNALED(status)) - e = WTERMSIG(status); - else /* can't happen */ - e = 1; - } - - if (die) + if (waitpid(child, &status, 0) == child) { + if (WIFEXITED(status)) + e = WEXITSTATUS(status); + else if (WIFSIGNALED(status)) + e = WTERMSIG(status); + else /* can't happen */ + e = 1; done(e); + } } void -- cgit v1.1 From b092dfff5962d508bdc6f177675864d37c1e48ff Mon Sep 17 00:00:00 2001 From: jkim Date: Sat, 1 May 2010 00:36:40 +0000 Subject: Do not initialize mutex and return error if it cannot map memory. --- sys/compat/x86bios/x86bios.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sys/compat/x86bios/x86bios.c b/sys/compat/x86bios/x86bios.c index d5512fc..defdbca 100644 --- a/sys/compat/x86bios/x86bios.c +++ b/sys/compat/x86bios/x86bios.c @@ -563,15 +563,15 @@ x86bios_unmap_mem(void) contigfree(x86bios_seg, X86BIOS_SEG_SIZE, M_DEVBUF); } -static void -x86bios_init(void *arg __unused) +static int +x86bios_init(void) { int i; - mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN); - if (x86bios_map_mem() != 0) - return; + return (ENOMEM); + + mtx_init(&x86bios_lock, "x86bios lock", NULL, MTX_SPIN); x86bios_map = malloc(sizeof(*x86bios_map) * X86BIOS_PAGES, M_DEVBUF, M_WAITOK | M_ZERO); @@ -600,10 +600,12 @@ x86bios_init(void *arg __unused) for (i = 0; i < 256; i++) x86bios_emu._x86emu_intrTab[i] = x86bios_emu_get_intr; + + return (0); } -static void -x86bios_uninit(void *arg __unused) +static int +x86bios_uninit(void) { vm_offset_t *map = x86bios_map; @@ -618,6 +620,8 @@ x86bios_uninit(void *arg __unused) x86bios_unmap_mem(); mtx_destroy(&x86bios_lock); + + return (0); } static int @@ -626,16 +630,12 @@ x86bios_modevent(module_t mod __unused, int type, void *data __unused) switch (type) { case MOD_LOAD: - x86bios_init(NULL); - break; + return (x86bios_init()); case MOD_UNLOAD: - x86bios_uninit(NULL); - break; + return (x86bios_uninit()); default: return (ENOTSUP); } - - return (0); } static moduledata_t x86bios_mod = { -- cgit v1.1 From 428aff4f1ca8a3a2156171a5b590288935a7cf5e Mon Sep 17 00:00:00 2001 From: jkim Date: Sat, 1 May 2010 01:05:07 +0000 Subject: Reduce MD code further. At least, it compiles on ia64 now (but it is not connected to build). The idea/code was shamelessly taken from r207329. --- sys/compat/x86bios/x86bios.c | 114 +++++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 36 deletions(-) diff --git a/sys/compat/x86bios/x86bios.c b/sys/compat/x86bios/x86bios.c index defdbca..cb8b85e 100644 --- a/sys/compat/x86bios/x86bios.c +++ b/sys/compat/x86bios/x86bios.c @@ -47,11 +47,15 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include +#if defined(__amd64__) || defined(__i386__) +#define X86BIOS_NATIVE_ARCH +#endif + #define X86BIOS_PAGE_SIZE 0x00001000 /* 4K */ #define X86BIOS_IVT_SIZE 0x00000500 /* 1K + 256 (BDA) */ @@ -236,27 +240,49 @@ x86bios_emu_inb(struct x86emu *emu, uint16_t port) if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); - return (inb(port)); + return (iodev_read_1(port)); } static uint16_t x86bios_emu_inw(struct x86emu *emu, uint16_t port) { + uint16_t val; if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); - return (inw(port)); +#ifndef X86BIOS_NATIVE_ARCH + if ((port & 1) != 0) { + val = iodev_read_1(port); + val |= iodev_read_1(port + 1) << 8; + } else +#endif + val = iodev_read_2(port); + + return (val); } static uint32_t x86bios_emu_inl(struct x86emu *emu, uint16_t port) { + uint32_t val; if (port >= 0x80 && port < 0x88) /* POST status register */ return (0); - return (inl(port)); +#ifndef X86BIOS_NATIVE_ARCH + if ((port & 1) != 0) { + val = iodev_read_1(port); + val |= iodev_read_2(port + 1) << 8; + val |= iodev_read_1(port + 3) << 24; + } else if ((port & 2) != 0) { + val = iodev_read_2(port); + val |= iodev_read_2(port + 2) << 16; + } else +#endif + val = iodev_read_4(port); + + return (val); } static void @@ -268,7 +294,7 @@ x86bios_emu_outb(struct x86emu *emu, uint16_t port, uint8_t val) if (port >= 0x80 && port < 0x88) /* POST status register */ return; - outb(port, val); + iodev_write_1(port, val); } static void @@ -278,7 +304,13 @@ x86bios_emu_outw(struct x86emu *emu, uint16_t port, uint16_t val) if (port >= 0x80 && port < 0x88) /* POST status register */ return; - outw(port, val); +#ifndef X86BIOS_NATIVE_ARCH + if ((port & 1) != 0) { + iodev_write_1(port, val); + iodev_write_1(port + 1, val >> 8); + } else +#endif + iodev_write_2(port, val); } static void @@ -288,7 +320,17 @@ x86bios_emu_outl(struct x86emu *emu, uint16_t port, uint32_t val) if (port >= 0x80 && port < 0x88) /* POST status register */ return; - outl(port, val); +#ifndef X86BIOS_NATIVE_ARCH + if ((port & 1) != 0) { + iodev_write_1(port, val); + iodev_write_2(port + 1, val >> 8); + iodev_write_1(port + 3, val >> 24); + } else if ((port & 2) != 0) { + iodev_write_2(port, val); + iodev_write_2(port + 2, val >> 16); + } else +#endif + iodev_write_4(port, val); } static void @@ -484,45 +526,53 @@ x86bios_match_device(uint32_t offset, device_t dev) return (1); } -#if defined(__amd64__) || (defined(__i386__) && !defined(PC98)) -#define PROBE_EBDA 1 +static __inline void +x86bios_unmap_mem(void) +{ + + if (x86bios_ivt != NULL) +#ifdef X86BIOS_NATIVE_ARCH + pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); #else -#define PROBE_EBDA 0 + free(x86bios_ivt, M_DEVBUF); #endif + if (x86bios_rom != NULL) + pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE); + if (x86bios_seg != NULL) + contigfree(x86bios_seg, X86BIOS_SEG_SIZE, M_DEVBUF); +} static __inline int x86bios_map_mem(void) { +#ifdef X86BIOS_NATIVE_ARCH x86bios_ivt = pmap_mapbios(X86BIOS_IVT_BASE, X86BIOS_IVT_SIZE); - if (x86bios_ivt == NULL) - return (1); -#if PROBE_EBDA +#ifndef PC98 /* Probe EBDA via BDA. */ - x86bios_rom_phys = *(uint16_t *)((vm_offset_t)x86bios_ivt + 0x40e); - x86bios_rom_phys = le16toh(x86bios_rom_phys) << 4; + x86bios_rom_phys = *(uint16_t *)((caddr_t)x86bios_ivt + 0x40e); + x86bios_rom_phys = x86bios_rom_phys << 4; if (x86bios_rom_phys != 0 && x86bios_rom_phys < X86BIOS_ROM_BASE && X86BIOS_ROM_BASE - x86bios_rom_phys <= 128 * 1024) x86bios_rom_phys = rounddown(x86bios_rom_phys, X86BIOS_PAGE_SIZE); else #endif +#else + x86bios_ivt = malloc(X86BIOS_IVT_SIZE, M_DEVBUF, M_ZERO | M_WAITOK); +#endif + x86bios_rom_phys = X86BIOS_ROM_BASE; x86bios_rom = pmap_mapdev(x86bios_rom_phys, X86BIOS_ROM_SIZE); - if (x86bios_rom == NULL) { - pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); - return (1); - } -#if PROBE_EBDA + if (x86bios_rom == NULL) + goto fail; +#if defined(X86BIOS_NATIVE_ARCH) && !defined(PC98) /* Change attribute for EBDA. */ if (x86bios_rom_phys < X86BIOS_ROM_BASE && pmap_change_attr((vm_offset_t)x86bios_rom, - X86BIOS_ROM_BASE - x86bios_rom_phys, PAT_WRITE_BACK) != 0) { - pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); - pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE); - return (1); - } + X86BIOS_ROM_BASE - x86bios_rom_phys, PAT_WRITE_BACK) != 0) + goto fail; #endif x86bios_seg = contigmalloc(X86BIOS_SEG_SIZE, M_DEVBUF, M_WAITOK, @@ -537,12 +587,10 @@ x86bios_map_mem(void) (uint32_t)x86bios_seg_phys, X86BIOS_SEG_SIZE + (uint32_t)x86bios_seg_phys - 1, x86bios_seg); -#if PROBE_EBDA if (x86bios_rom_phys < X86BIOS_ROM_BASE) printf("x86bios: EBDA 0x%06x-0x%06x at %p\n", (uint32_t)x86bios_rom_phys, X86BIOS_ROM_BASE - 1, x86bios_rom); -#endif printf("x86bios: ROM 0x%06x-0x%06x at %p\n", X86BIOS_ROM_BASE, X86BIOS_MEM_SIZE - X86BIOS_SEG_SIZE - 1, (void *)((vm_offset_t)x86bios_rom + X86BIOS_ROM_BASE - @@ -550,17 +598,11 @@ x86bios_map_mem(void) } return (0); -} -#undef PROBE_EBDA +fail: + x86bios_unmap_mem(); -static __inline void -x86bios_unmap_mem(void) -{ - - pmap_unmapdev((vm_offset_t)x86bios_ivt, X86BIOS_IVT_SIZE); - pmap_unmapdev((vm_offset_t)x86bios_rom, X86BIOS_ROM_SIZE); - contigfree(x86bios_seg, X86BIOS_SEG_SIZE, M_DEVBUF); + return (1); } static int -- cgit v1.1 From 35842e76ff3f646e76c671a506c359aeeafc3042 Mon Sep 17 00:00:00 2001 From: kmacy Date: Sat, 1 May 2010 03:41:21 +0000 Subject: Update locking comment above vm_page: - re-assign page queue lock "Q" - assign page lock "P" - update several uncommented fields - observe that hold_count is now protected by the page lock "P" --- sys/vm/vm_page.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 35a81f8..51a896f 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -90,20 +90,21 @@ * and sundry status bits. * * Fields in this structure are locked either by the lock on the - * object that the page belongs to (O) or by the lock on the page - * queues (P). + * object that the page belongs to (O), its corresponding page lock (P), + * or by the lock on the page queues (Q). + * */ TAILQ_HEAD(pglist, vm_page); struct vm_page { - TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO queue or free list (P) */ + TAILQ_ENTRY(vm_page) pageq; /* queue info for FIFO queue or free list (Q) */ TAILQ_ENTRY(vm_page) listq; /* pages in same object (O) */ struct vm_page *left; /* splay tree link (O) */ struct vm_page *right; /* splay tree link (O) */ - vm_object_t object; /* which object am I in (O,P)*/ - vm_pindex_t pindex; /* offset into object (O,P) */ + vm_object_t object; /* which object am I in (O,Q)*/ + vm_pindex_t pindex; /* offset into object (O,Q) */ vm_paddr_t phys_addr; /* physical address of page */ struct md_page md; /* machine dependant stuff */ uint8_t queue; /* page queue index */ @@ -111,11 +112,11 @@ struct vm_page { u_short flags; /* see below */ uint8_t order; /* index of the buddy queue */ uint8_t pool; - u_short cow; /* page cow mapping count */ - u_int wire_count; /* wired down maps refs (P) */ - short hold_count; /* page hold count */ + u_short cow; /* page cow mapping count (Q) */ + u_int wire_count; /* wired down maps refs (Q) */ + short hold_count; /* page hold count (P) */ u_short oflags; /* page flags (O) */ - u_char act_count; /* page usage count */ + u_char act_count; /* page usage count (Q) */ u_char busy; /* page busy count (O) */ /* NOTE that these must support one bit per DEV_BSIZE in a page!!! */ /* so, on normal X86 kernels, they must be at least 8 bits wide */ -- cgit v1.1 From 354b097e927c5fd63fbe48bd68629779dbd40d1f Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 1 May 2010 07:25:28 +0000 Subject: sparc64, and possibly other architectures, pads the length of the section holding the config file to sh_addralign bytes using NULs. This bogusly triggers an assert. Break out of the loop when we hit an NUL within that many bytes of the end. MFC after: 3 days --- usr.sbin/config/main.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c index 5cffed2..e63e6ab 100644 --- a/usr.sbin/config/main.c +++ b/usr.sbin/config/main.c @@ -670,7 +670,7 @@ kernconfdump(const char *file) struct stat st; FILE *fp, *pp; int error, len, osz, r; - unsigned int i, off, size; + unsigned int i, off, size, t1, t2, align; char *cmd, *o; r = open(file, O_RDONLY); @@ -689,8 +689,8 @@ kernconfdump(const char *file) if (o == NULL) err(EXIT_FAILURE, "Couldn't allocate memory"); /* ELF note section header. */ - asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 kern_conf" - "| tail -2 | cut -d ' ' -f 2 | paste - - -", file); + asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 8 kern_conf" + "| tail -5 | cut -d ' ' -f 2 | paste - - - - -", file); if (cmd == NULL) errx(EXIT_FAILURE, "asprintf() failed"); pp = popen(cmd, "r"); @@ -699,24 +699,28 @@ kernconfdump(const char *file) free(cmd); len = fread(o, osz, 1, pp); pclose(pp); - r = sscanf(o, "%d\t%d", &off, &size); + r = sscanf(o, "%d%d%d%d%d", &off, &size, &t1, &t2, &align); free(o); - if (r != 2) + if (r != 5) errx(EXIT_FAILURE, "File %s doesn't contain configuration " "file. Either unsupported, or not compiled with " "INCLUDE_CONFIG_FILE", file); r = fseek(fp, off, SEEK_CUR); if (r != 0) err(EXIT_FAILURE, "fseek() failed"); - for (i = 0; i < size - 1; i++) { + for (i = 0; i < size; i++) { r = fgetc(fp); if (r == EOF) break; /* * If '\0' is present in the middle of the configuration * string, this means something very weird is happening. - * Make such case very visible. + * Make such case very visible. However, some architectures + * pad the length of the section with NULs to a multiple of + * sh_addralign, allow a NUL in that part of the section. */ + if (r == '\0' && (size - i) < align) + break; assert(r != '\0' && ("Char present in the configuration " "string mustn't be equal to 0")); fputc(r, stdout); -- cgit v1.1 From 2cdb1b2f9189bf5a1f9e6952d1be8e816e82fd26 Mon Sep 17 00:00:00 2001 From: edwin Date: Sat, 1 May 2010 09:05:06 +0000 Subject: Improve usage of tunefs: Document -j switch in usage() to reflect recent SUJ work. Submitted by: Alastair Hogge MFC after: 1 week --- sbin/tunefs/tunefs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c index 7987620..dc2492f 100644 --- a/sbin/tunefs/tunefs.c +++ b/sbin/tunefs/tunefs.c @@ -1007,10 +1007,11 @@ out: void usage(void) { - fprintf(stderr, "%s\n%s\n%s\n%s\n", + fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]", -" [-J enable | disable ] [-L volname] [-l enable | disable]", -" [-m minfree] [-N enable | disable] [-n enable | disable]", +" [-J enable | disable] [-j enable | disable]", +" [-L volname] [-l enable | disable] [-m minfree]", +" [-N enable | disable] [-n enable | disable]", " [-o space | time] [-p] [-s avgfpdir] special | filesystem"); exit(2); } -- cgit v1.1 From 669b45b7b848b53778c18e8686a6f206f65e6034 Mon Sep 17 00:00:00 2001 From: kib Date: Sat, 1 May 2010 13:15:35 +0000 Subject: Remove debugging code that was not used once since commit. Suggested by: bde MFC after: 1 week --- sys/amd64/amd64/trap.c | 86 +------------------------------------------------- 1 file changed, 1 insertion(+), 85 deletions(-) diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c index 8acde03..f3dba94 100644 --- a/sys/amd64/amd64/trap.c +++ b/sys/amd64/amd64/trap.c @@ -172,52 +172,6 @@ SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW, extern char *syscallnames[]; -/* #define DEBUG 1 */ -#ifdef DEBUG -static void -report_seg_fault(const char *segn, struct trapframe *frame) -{ - struct proc_ldt *pldt; - struct trapframe *pf; - - pldt = curproc->p_md.md_ldt; - printf("%d: %s load fault %lx %p %d\n", - curproc->p_pid, segn, frame->tf_err, - pldt != NULL ? pldt->ldt_base : NULL, - pldt != NULL ? pldt->ldt_refcnt : 0); - kdb_backtrace(); - pf = (struct trapframe *)frame->tf_rsp; - printf("rdi %lx\n", pf->tf_rdi); - printf("rsi %lx\n", pf->tf_rsi); - printf("rdx %lx\n", pf->tf_rdx); - printf("rcx %lx\n", pf->tf_rcx); - printf("r8 %lx\n", pf->tf_r8); - printf("r9 %lx\n", pf->tf_r9); - printf("rax %lx\n", pf->tf_rax); - printf("rbx %lx\n", pf->tf_rbx); - printf("rbp %lx\n", pf->tf_rbp); - printf("r10 %lx\n", pf->tf_r10); - printf("r11 %lx\n", pf->tf_r11); - printf("r12 %lx\n", pf->tf_r12); - printf("r13 %lx\n", pf->tf_r13); - printf("r14 %lx\n", pf->tf_r14); - printf("r15 %lx\n", pf->tf_r15); - printf("fs %x\n", pf->tf_fs); - printf("gs %x\n", pf->tf_gs); - printf("es %x\n", pf->tf_es); - printf("ds %x\n", pf->tf_ds); - printf("tno %x\n", pf->tf_trapno); - printf("adr %lx\n", pf->tf_addr); - printf("flg %x\n", pf->tf_flags); - printf("err %lx\n", pf->tf_err); - printf("rip %lx\n", pf->tf_rip); - printf("cs %lx\n", pf->tf_cs); - printf("rfl %lx\n", pf->tf_rflags); - printf("rsp %lx\n", pf->tf_rsp); - printf("ss %lx\n", pf->tf_ss); -} -#endif - /* * Exception, fault, and trap interface to the FreeBSD kernel. * This common code is called from assembly language IDT gate entry @@ -314,9 +268,7 @@ trap(struct trapframe *frame) */ printf("kernel trap %d with interrupts disabled\n", type); -#ifdef DEBUG - report_seg_fault("hlt", frame); -#endif + /* * We shouldn't enable interrupts while holding a * spin lock or servicing an NMI. @@ -535,33 +487,21 @@ trap(struct trapframe *frame) goto out; } if (frame->tf_rip == (long)ld_ds) { -#ifdef DEBUG - report_seg_fault("ds", frame); -#endif frame->tf_rip = (long)ds_load_fault; frame->tf_ds = _udatasel; goto out; } if (frame->tf_rip == (long)ld_es) { -#ifdef DEBUG - report_seg_fault("es", frame); -#endif frame->tf_rip = (long)es_load_fault; frame->tf_es = _udatasel; goto out; } if (frame->tf_rip == (long)ld_fs) { -#ifdef DEBUG - report_seg_fault("fs", frame); -#endif frame->tf_rip = (long)fs_load_fault; frame->tf_fs = _ufssel; goto out; } if (frame->tf_rip == (long)ld_gs) { -#ifdef DEBUG - report_seg_fault("gs", frame); -#endif frame->tf_rip = (long)gs_load_fault; frame->tf_gs = _ugssel; goto out; @@ -667,30 +607,6 @@ trap(struct trapframe *frame) ksi.ksi_addr = (void *)addr; trapsignal(td, &ksi); -#ifdef DEBUG -{ - register_t rg,rgk, rf; - - if (type <= MAX_TRAP_MSG) { - uprintf("fatal process exception: %s", - trap_msg[type]); - if ((type == T_PAGEFLT) || (type == T_PROTFLT)) - uprintf(", fault VA = 0x%lx", frame->tf_addr); - uprintf("\n"); - } - rf = rdmsr(0xc0000100); - rg = rdmsr(0xc0000101); - rgk = rdmsr(0xc0000102); - uprintf("pid %d TRAP %d rip %lx err %lx addr %lx cs %lx ss %lx ds %x " - "es %x fs %x fsbase %lx %lx gs %x gsbase %lx %lx %lx\n", - curproc->p_pid, type, frame->tf_rip, frame->tf_err, - frame->tf_addr, - frame->tf_cs, frame->tf_ss, frame->tf_ds, frame->tf_es, - frame->tf_fs, td->td_pcb->pcb_fsbase, rf, - frame->tf_gs, td->td_pcb->pcb_gsbase, rg, rgk); -} -#endif - user: userret(td, frame); mtx_assert(&Giant, MA_NOTOWNED); -- cgit v1.1 From 64dab823a098725e6392493bd0fa3d2f356d41fe Mon Sep 17 00:00:00 2001 From: kib Date: Sat, 1 May 2010 14:46:17 +0000 Subject: Extract thread_lock()/ruxagg()/thread_unlock() fragment into utility function ruxagg_tlock(). Convert the definition of kern_getrusage() to ANSI C. Submitted by: Alexander Krizhanovsky MFC after: 1 week --- sys/kern/kern_resource.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index f867839..a3ed75d 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -76,6 +76,7 @@ static void calcru1(struct proc *p, struct rusage_ext *ruxp, struct timeval *up, struct timeval *sp); static int donice(struct thread *td, struct proc *chgp, int n); static struct uidinfo *uilookup(uid_t uid); +static void ruxagg_tlock(struct proc *p, struct thread *td); /* * Resource controls and accounting. @@ -629,9 +630,7 @@ lim_cb(void *arg) return; PROC_SLOCK(p); FOREACH_THREAD_IN_PROC(p, td) { - thread_lock(td); - ruxagg(&p->p_rux, td); - thread_unlock(td); + ruxagg_tlock(p, td); } PROC_SUNLOCK(p); if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) { @@ -842,9 +841,7 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp) FOREACH_THREAD_IN_PROC(p, td) { if (td->td_incruntime == 0) continue; - thread_lock(td); - ruxagg(&p->p_rux, td); - thread_unlock(td); + ruxagg_tlock(p, td); } calcru1(p, &p->p_rux, up, sp); } @@ -945,10 +942,7 @@ getrusage(td, uap) } int -kern_getrusage(td, who, rup) - struct thread *td; - int who; - struct rusage *rup; +kern_getrusage(struct thread *td, int who, struct rusage *rup) { struct proc *p; int error; @@ -1022,6 +1016,15 @@ ruxagg(struct rusage_ext *rux, struct thread *td) td->td_sticks = 0; } +static void +ruxagg_tlock(struct proc *p, struct thread *td) +{ + + thread_lock(td); + ruxagg(&p->p_rux, td); + thread_unlock(td); +} + /* * Update the rusage_ext structure and fetch a valid aggregate rusage * for proc p if storage for one is supplied. @@ -1036,9 +1039,7 @@ rufetch(struct proc *p, struct rusage *ru) *ru = p->p_ru; if (p->p_numthreads > 0) { FOREACH_THREAD_IN_PROC(p, td) { - thread_lock(td); - ruxagg(&p->p_rux, td); - thread_unlock(td); + ruxagg_tlock(p, td); rucollect(ru, &td->td_ru); } } -- cgit v1.1 From e75188d9b5c3fb085de1e1c21c2e5c699f479bcd Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 1 May 2010 16:36:14 +0000 Subject: The Atheros AR71xx CPUs, when paired with the AR5212 parts, has a bug that generates a fatal bus trap. Normally, the chips are setup to do 128 byte DMA bursts, but when on this CPU, they can only safely due 4-byte DMA bursts due to this bug. Details of the exact nature of the bug are sketchy, but some can be found at https://forum.openwrt.org/viewtopic.php?pid=70060 on pages 4, 5 and 6. There's a small performance penalty associated with this workaround, so it is only enabled when needed on the Atheros AR71xx platforms. Unfortunately, this condition is impossible to detect at runtime without MIPS specific ifdefs. Rather than cast an overly-broad net like Linux/OpenWRT dues (which enables this workaround all the time on MIPS32 platforms), we put this option in the kernel for just the affected machines. Sam didn't like this aspect of the patch when he reviewed it, and I'd love to hear sane proposals on how to fix it :) Reviewed by: sam@ --- sys/conf/NOTES | 9 +++++++++ sys/conf/options | 1 + sys/dev/ath/ath_hal/ar5212/ar5212_reset.c | 8 ++++++++ 3 files changed, 18 insertions(+) diff --git a/sys/conf/NOTES b/sys/conf/NOTES index f0cc9a0..cc1964d 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2091,6 +2091,15 @@ device ath_hal # pci/cardbus chip support #device ath_rf5413 #device ath_ar5416 # AR5416 chips options AH_SUPPORT_AR5416 # enable AR5416 tx/rx descriptors +# All of the AR5212 parts have a problem when paired with the AR71xx +# CPUS. These parts have a bug that triggers a fatal bus error on the AR71xx +# only. Details of the exact nature of the bug are sketchy, but some can be +# found at https://forum.openwrt.org/viewtopic.php?pid=70060 on pages 4, 5 and +# 6. This option enables this workaround. There is a performance penalty +# for this work around, but without it things don't work at all. The DMA +# from the card usually bursts 128 bytes, but on the affected CPUs, only +# 4 are safe. +options AH_RXCFG_SDMAMW_4BYTES #device ath_ar9160 # AR9160 chips #device ath_ar9280 # AR9280 chips #device ath_ar9285 # AR9285 chips diff --git a/sys/conf/options b/sys/conf/options index fabc0bf..8f1dcaa 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -771,6 +771,7 @@ AH_PRIVATE_DIAG opt_ah.h AH_NEED_DESC_SWAP opt_ah.h AH_USE_INIPDGAIN opt_ah.h AH_MAXCHAN opt_ah.h +AH_RXCFG_SDMAMW_4BYTES opt_ah.h # options for the Broadcom BCM43xx driver (bwi) BWI_DEBUG opt_bwi.h diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c index fc937ea..8e6341a 100644 --- a/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c +++ b/sys/dev/ath/ath_hal/ar5212/ar5212_reset.c @@ -283,6 +283,14 @@ ar5212Reset(struct ath_hal *ah, HAL_OPMODE opmode, regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex, 0); regWrites = write_common(ah, &ahp->ah_ini_common, bChannelChange, regWrites); +#ifdef AH_RXCFG_SDMAMW_4BYTES + /* + * Nala doesn't work with 128 byte bursts on pb42(hydra) (ar71xx), + * use 4 instead. Enabling it on all platforms would hurt performance, + * so we only enable it on the ones that are affected by it. + */ + OS_REG_WRITE(ah, AR_RXCFG, 0); +#endif ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites); OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__); -- cgit v1.1 From a54f37f5128fc6dbed611570d1700d7780be4b60 Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 1 May 2010 16:38:40 +0000 Subject: Put the -current debugging options back into AR71XX. --- sys/mips/conf/AR71XX | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/mips/conf/AR71XX b/sys/mips/conf/AR71XX index 4ee6aab..5e9499b 100644 --- a/sys/mips/conf/AR71XX +++ b/sys/mips/conf/AR71XX @@ -29,11 +29,11 @@ options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions # options NFS_LEGACYRPC # Debugging for use in -current -# options DEADLKRES -# options INVARIANTS -# options INVARIANT_SUPPORT -# options WITNESS -# options WITNESS_SKIPSPIN +options DEADLKRES +options INVARIANTS +options INVARIANT_SUPPORT +options WITNESS +options WITNESS_SKIPSPIN options FFS #Berkeley Fast Filesystem options SOFTUPDATES #Enable FFS soft updates support options UFS_ACL #Support for access control lists -- cgit v1.1 From 17cb7ef363ee0a6d9d2f87d1384cbba8aa30f744 Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 1 May 2010 16:39:46 +0000 Subject: Enable AH_RXCFG_SDMAMW_4BYTES option. See NOTES file for why this is workaround (WAR) is needed. --- sys/mips/conf/AR71XX | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/mips/conf/AR71XX b/sys/mips/conf/AR71XX index 5e9499b..12c73da 100644 --- a/sys/mips/conf/AR71XX +++ b/sys/mips/conf/AR71XX @@ -62,6 +62,7 @@ device ath # Atheros pci/cardbus NIC's options ATH_DEBUG device ath_hal option AH_SUPPORT_AR5416 +option AH_RXCFG_SDMAMW_4BYTES # See NOTES for details of this WAR device ath_rate_sample device mii -- cgit v1.1 From 139551016dac32fce225484e2c18443d7a850f88 Mon Sep 17 00:00:00 2001 From: zec Date: Sat, 1 May 2010 18:34:50 +0000 Subject: Remove a redundant variable assignment. Reviewed by: bz, rwatson MFC after: 3 days --- sys/kern/uipc_mbuf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index bc0e88d..85e0e39 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -948,9 +948,8 @@ m_adj(struct mbuf *mp, int req_len) len = 0; } } - m = mp; if (mp->m_flags & M_PKTHDR) - m->m_pkthdr.len -= (req_len - len); + mp->m_pkthdr.len -= (req_len - len); } else { /* * Trim from tail. Scan the mbuf chain, -- cgit v1.1 From 05af89104152f50df570a13c22c93c3db10f3d69 Mon Sep 17 00:00:00 2001 From: emaste Date: Sat, 1 May 2010 18:56:45 +0000 Subject: Search beyond the first 1/8th of inodes. Submitted by: jeff --- lib/libufs/cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libufs/cgroup.c b/lib/libufs/cgroup.c index b0cb4a7..8ab33f7 100644 --- a/lib/libufs/cgroup.c +++ b/lib/libufs/cgroup.c @@ -145,7 +145,7 @@ cgialloc(struct uufsd *disk) fs = &disk->d_fs; cgp = &disk->d_cg; inosused = cg_inosused(cgp); - for (ino = 0; ino < fs->fs_ipg / NBBY; ino++) + for (ino = 0; ino < fs->fs_ipg; ino++) if (isclr(inosused, ino)) goto gotit; return (0); -- cgit v1.1 From 54fb849ffcadd6a10a0953a595fd69fbc9693fea Mon Sep 17 00:00:00 2001 From: mm Date: Sat, 1 May 2010 19:53:15 +0000 Subject: Change description of tunable group vfs.zfs.txg to be more understandable. Approved by: pjd, delphij (mentor) MFC after: 3 days --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c index 040e4d7..143b4b8 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c @@ -40,7 +40,8 @@ int zfs_txg_timeout = 30; /* max seconds worth of delta per txg */ extern int zfs_txg_synctime; SYSCTL_DECL(_vfs_zfs); -SYSCTL_NODE(_vfs_zfs, OID_AUTO, txg, CTLFLAG_RW, 0, "ZFS TXG"); +SYSCTL_NODE(_vfs_zfs, OID_AUTO, txg, CTLFLAG_RW, 0, + "ZFS transaction groups (TXG)"); TUNABLE_INT("vfs.zfs.txg.timeout", &zfs_txg_timeout); SYSCTL_INT(_vfs_zfs_txg, OID_AUTO, timeout, CTLFLAG_RDTUN, &zfs_txg_timeout, 0, "Maximum seconds worth of delta per txg"); -- cgit v1.1 From 65cf7aac0b30cb9fd2148329b46e43e6f9c6f382 Mon Sep 17 00:00:00 2001 From: mm Date: Sat, 1 May 2010 20:44:37 +0000 Subject: Add sysctl and loader tunable vfs.zfs.txg.write_limit_override. This tunable improves fine-tuning of ZFS write throttling. PR: kern/146108 Suggested by: Nikolay Denev Approved by: pjd, delphij (mentor) MFC after: 2 weeks --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c index 143b4b8..8650fa1 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c @@ -38,6 +38,7 @@ static void txg_quiesce_thread(void *arg); int zfs_txg_timeout = 30; /* max seconds worth of delta per txg */ extern int zfs_txg_synctime; +extern uint64_t zfs_write_limit_override; SYSCTL_DECL(_vfs_zfs); SYSCTL_NODE(_vfs_zfs, OID_AUTO, txg, CTLFLAG_RW, 0, @@ -48,6 +49,11 @@ SYSCTL_INT(_vfs_zfs_txg, OID_AUTO, timeout, CTLFLAG_RDTUN, &zfs_txg_timeout, 0, TUNABLE_INT("vfs.zfs.txg.synctime", &zfs_txg_synctime); SYSCTL_INT(_vfs_zfs_txg, OID_AUTO, synctime, CTLFLAG_RDTUN, &zfs_txg_synctime, 0, "Target seconds to sync a txg"); +TUNABLE_QUAD("vfs.zfs.txg.write_limit_override", &zfs_write_limit_override); +SYSCTL_QUAD(_vfs_zfs_txg, OID_AUTO, write_limit_override, CTLFLAG_RW, + &zfs_write_limit_override, 0, + "Override maximum size of a txg to this size in bytes, " + "value of 0 means don't override"); /* * Prepare the txg subsystem. -- cgit v1.1 From 01a827bd910a0e0a956fa132ab9ab657527ec788 Mon Sep 17 00:00:00 2001 From: rstone Date: Sat, 1 May 2010 21:59:06 +0000 Subject: When configuring hwpmc to use the EXT_SNOOP event, only send a default cachestate qualifier on the Atom processor. Other Intel processors do not accept a cachestate qualifier and currently hwpmc will return EINVAL if you try to use the EXT_SNOOP event on those processors Approved by: jkoshy (mentor) MFC after: 2 weeks --- lib/libpmc/libpmc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c index c440aa8..8922dd8 100644 --- a/lib/libpmc/libpmc.c +++ b/lib/libpmc/libpmc.c @@ -737,9 +737,16 @@ iap_allocate_pmc(enum pmc_event pe, char *ctrspec, case PMC_EV_IAP_EVENT_40H: /* Core */ case PMC_EV_IAP_EVENT_41H: /* Core */ case PMC_EV_IAP_EVENT_42H: /* Core, Core2, Atom */ - case PMC_EV_IAP_EVENT_77H: /* Core */ if (cachestate == 0) cachestate = (0xF << 8); + break; + case PMC_EV_IAP_EVENT_77H: /* Atom */ + /* IAP_EVENT_77H only accepts a cachestate qualifier on the + * Atom processor + */ + if(cpu_info.pm_cputype == PMC_CPU_INTEL_ATOM && cachestate == 0) + cachestate = (0xF << 8); + break; default: break; } -- cgit v1.1 From b1c9a3a8211c0dc64b4ed5f2b5da177736dff1ae Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 1 May 2010 22:00:28 +0000 Subject: pathchk: Add the new POSIX -P option. This option checks for empty pathnames and components starting with '-'. Our -p option also checks for the latter, which remains the case. MFC after: 1 week --- usr.bin/pathchk/pathchk.1 | 14 ++++++++++++-- usr.bin/pathchk/pathchk.c | 18 ++++++++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/usr.bin/pathchk/pathchk.1 b/usr.bin/pathchk/pathchk.1 index e863955..fb50e84 100644 --- a/usr.bin/pathchk/pathchk.1 +++ b/usr.bin/pathchk/pathchk.1 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd May 21, 2002 +.Dd May 1, 2010 .Dt PATHCHK 1 .Os .Sh NAME @@ -35,7 +35,7 @@ .Nd check pathnames .Sh SYNOPSIS .Nm -.Op Fl p +.Op Fl pP .Ar pathname ... .Sh DESCRIPTION The @@ -95,6 +95,16 @@ No component may start with the hyphen .Pq Ql \&- character. .El +.It Fl P +In addition to the default or +.Fl p +checks, write a diagnostic for each argument that: +.Bl -bullet +.It +Is empty. +.It +Contains a component that starts with a hyphen. +.El .El .Sh EXIT STATUS .Ex -std diff --git a/usr.bin/pathchk/pathchk.c b/usr.bin/pathchk/pathchk.c index dd9768a..2d8fa59 100644 --- a/usr.bin/pathchk/pathchk.c +++ b/usr.bin/pathchk/pathchk.c @@ -51,6 +51,7 @@ static int portable(const char *); static void usage(void); static int pflag; /* Perform portability checks */ +static int Pflag; /* Check for empty paths, leading '-' */ int main(int argc, char *argv[]) @@ -58,11 +59,14 @@ main(int argc, char *argv[]) int ch, rval; const char *arg; - while ((ch = getopt(argc, argv, "p")) > 0) { + while ((ch = getopt(argc, argv, "pP")) > 0) { switch (ch) { case 'p': pflag = 1; break; + case 'P': + Pflag = 1; + break; default: usage(); /*NOTREACHED*/ @@ -102,6 +106,15 @@ check(const char *path) p = pathd; + if (Pflag && *p == '\0') { + warnx("%s: empty pathname", path); + goto bad; + } + if ((Pflag || pflag) && (*p == '-' || strstr(p, "/-") != NULL)) { + warnx("%s: contains a component starting with '-'", path); + goto bad; + } + if (!pflag) { errno = 0; namemax = pathconf(*p == '/' ? "/" : ".", _PC_NAME_MAX); @@ -182,9 +195,6 @@ portable(const char *path) "0123456789._-"; long s; - if (*path == '-') - return (*path); - s = strspn(path, charset); if (path[s] != '\0') return (path[s]); -- cgit v1.1 From 5baa2ffd766629886fc7d864f4c82fad76ab87e3 Mon Sep 17 00:00:00 2001 From: rstone Date: Sat, 1 May 2010 22:04:58 +0000 Subject: When configuring a system-wide couting PMC, hwpmc was incorrectly logging process mappings for that PMC. Nothing ever reads pmc logs out of a counting PMC, so the log buffers were leaked when the PMC was deconfigured. The process mappings are only useful for sampling PMCs anyway, so only log the mappings if the PMC is a sampling PMC. This bug would cause allocating sample-mode PMCs to fail with ENOMEM after allocating several counting-mode PMCs. Approved by: jkoshy (mentor) MFC after: 2 weeks --- sys/dev/hwpmc/hwpmc_mod.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index e33b431..a19c85e 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -2675,16 +2675,16 @@ pmc_start(struct pmc *pm) PMCDBG(PMC,OPS,1, "po=%p in global list", po); } po->po_sscount++; - } - /* - * Log mapping information for all existing processes in the - * system. Subsequent mappings are logged as they happen; - * see pmc_process_mmap(). - */ - if (po->po_logprocmaps == 0) { - pmc_log_all_process_mappings(po); - po->po_logprocmaps = 1; + /* + * Log mapping information for all existing processes in the + * system. Subsequent mappings are logged as they happen; + * see pmc_process_mmap(). + */ + if (po->po_logprocmaps == 0) { + pmc_log_all_process_mappings(po); + po->po_logprocmaps = 1; + } } /* -- cgit v1.1 From c25bdaf47df3c910b4b3511585bdd5e99d004fe9 Mon Sep 17 00:00:00 2001 From: jilles Date: Sat, 1 May 2010 22:10:45 +0000 Subject: pathchk(1): Fix the example so it allows arbitrary pathnames. Spaces and various other characters in pathnames are not passed through literally by xargs in its default mode. Instead, use find . -exec ... {} + Although the -- argument is not strictly required here, add it anyway to avoid surprises when modifying the code to find -f -somedir ... MFC after: 1 week --- usr.bin/pathchk/pathchk.1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.bin/pathchk/pathchk.1 b/usr.bin/pathchk/pathchk.1 index fb50e84..931f82f 100644 --- a/usr.bin/pathchk/pathchk.1 +++ b/usr.bin/pathchk/pathchk.1 @@ -114,7 +114,7 @@ other .Tn POSIX systems: .Pp -.Dl "find . -print | xargs pathchk -p" +.Dl "find . -exec pathchk -p -- {} +" .Sh SEE ALSO .Xr getconf 1 , .Xr pathconf 2 , -- cgit v1.1 From 69cbedb734d7c872998529ff2946d9822f59b825 Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 01:25:03 +0000 Subject: Correct an error of omission in r206819. If VMFS_TLB_ALIGNED_SPACE is specified to vm_map_find(), then retry the vm_map_findspace() if vm_map_insert() fails because the aligned space is already partly used. Reported by: Neel Natu --- sys/vm/vm_map.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 1d22fa6..2a57e33 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -1412,7 +1412,11 @@ vm_map_find(vm_map_t map, vm_object_t object, vm_ooffset_t offset, } result = vm_map_insert(map, object, offset, start, start + length, prot, max, cow); - } while (result == KERN_NO_SPACE && find_space == VMFS_ALIGNED_SPACE); + } while (result == KERN_NO_SPACE && (find_space == VMFS_ALIGNED_SPACE +#ifdef VMFS_TLB_ALIGNED_SPACE + || find_space == VMFS_TLB_ALIGNED_SPACE +#endif + )); vm_map_unlock(map); return (result); } -- cgit v1.1 From 113965a783486fa0bfab880cc7a2209285511195 Mon Sep 17 00:00:00 2001 From: mav Date: Sun, 2 May 2010 04:16:39 +0000 Subject: Add xpt_schedule_dev_sendq() call, lost at r203108. It is not needed in usual operation, but required in some conditions to make queue running after being shrinked. MFC after: 3 days --- sys/cam/cam_xpt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c index ed05c40..5d83539 100644 --- a/sys/cam/cam_xpt.c +++ b/sys/cam/cam_xpt.c @@ -4874,6 +4874,8 @@ camisr_runqueue(void *V_queue) if ((dev->flags & CAM_DEV_TAG_AFTER_COUNT) != 0 && (--dev->tag_delay_count == 0)) xpt_start_tags(ccb_h->path); + if (!device_is_send_queued(dev)) + xpt_schedule_dev_sendq(ccb_h->path->bus, dev); } if (ccb_h->status & CAM_RELEASE_SIMQ) { -- cgit v1.1 From 4e502e1ceb65ddf828e427fe014e2a31cff0307a Mon Sep 17 00:00:00 2001 From: mav Date: Sun, 2 May 2010 11:36:27 +0000 Subject: Add -d and -f arguments to `camcontrol cmd`, to execute DMA ATA commands. --- sbin/camcontrol/camcontrol.8 | 8 +++++++- sbin/camcontrol/camcontrol.c | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index d1e9587..1a075b3 100644 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 20, 2010 +.Dd May 2, 2010 .Dt CAMCONTROL 8 .Os .Sh NAME @@ -123,6 +123,8 @@ .Op generic args .Aq Fl a Ar cmd Op args .Aq Fl c Ar cmd Op args +.Op Fl d +.Op Fl f .Op Fl i Ar len Ar fmt .Bk -words .Op Fl o Ar len Ar fmt Op args @@ -530,6 +532,10 @@ lba_high_exp, features_exp, sector_count, sector_count_exp). .It Fl c Ar cmd Op args This specifies the SCSI CDB. SCSI CDBs may be 6, 10, 12 or 16 bytes. +.It Fl d +Specifies DMA protocol to be used for ATA command. +.It Fl f +Specifies FPDMA (NCQ) protocol to be used for ATA command. .It Fl i Ar len Ar fmt This specifies the amount of data to read, and how it should be displayed. If the format is diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 8e0605f..9136cbe 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -123,7 +123,7 @@ struct camcontrol_opts { }; #ifndef MINIMALISTIC -static const char scsicmd_opts[] = "a:c:i:o:r"; +static const char scsicmd_opts[] = "a:c:dfi:o:r"; static const char readdefect_opts[] = "f:GP"; static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; #endif @@ -2184,6 +2184,8 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, int c, data_bytes = 0; int cdb_len = 0; int atacmd_len = 0; + int dmacmd = 0; + int fpdmacmd = 0; int need_res = 0; char *datastr = NULL, *tstr, *resstr = NULL; int error = 0; @@ -2246,6 +2248,12 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, */ optind += hook.got; break; + case 'd': + dmacmd = 1; + break; + case 'f': + fpdmacmd = 1; + break; case 'i': if (arglist & CAM_ARG_CMD_OUT) { warnx("command must either be " @@ -2422,6 +2430,10 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt, bcopy(atacmd, &ccb->ataio.cmd.command, atacmd_len); if (need_res) ccb->ataio.cmd.flags |= CAM_ATAIO_NEEDRESULT; + if (dmacmd) + ccb->ataio.cmd.flags |= CAM_ATAIO_DMA; + if (fpdmacmd) + ccb->ataio.cmd.flags |= CAM_ATAIO_FPDMA; cam_fill_ataio(&ccb->ataio, /*retries*/ retry_count, @@ -4353,7 +4365,7 @@ usage(int verbose) " [-P pagectl][-e | -b][-d]\n" " camcontrol cmd [dev_id][generic args]\n" " <-a cmd [args] | -c cmd [args]>\n" -" [-i len fmt|-o len fmt [args]] [-r fmt]\n" +" [-d] [-f] [-i len fmt|-o len fmt [args]] [-r fmt]\n" " camcontrol debug [-I][-P][-T][-S][-X][-c]\n" " \n" " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n" -- cgit v1.1 From 90843ddc5c2afced3e89219701abb4384aba3190 Mon Sep 17 00:00:00 2001 From: mav Date: Sun, 2 May 2010 12:07:47 +0000 Subject: Make SATA XPT negotiate and enable some additional SATA features, such as: - device initiated power management (some devices support only this way); - Automatic Partial to Slumber Transition (more power saving); - DMA auto-activation (expected to slightly improve performance). More features could be added later, when hardware supports. --- sbin/camcontrol/camcontrol.c | 4 ++ sys/cam/ata/ata_pmp.c | 20 +++++- sys/cam/ata/ata_xpt.c | 137 +++++++++++++++++++++++++++++++++++ sys/cam/cam_ccb.h | 9 +++ sys/dev/ahci/ahci.c | 166 +++++++++++++++++++++++++------------------ sys/dev/ahci/ahci.h | 1 + sys/dev/siis/siis.c | 12 ++++ sys/dev/siis/siis.h | 1 + 8 files changed, 277 insertions(+), 73 deletions(-) diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 9136cbe..c39d7ba 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -2855,6 +2855,10 @@ cts_print(struct cam_device *device, struct ccb_trans_settings *cts) fprintf(stdout, "%sNumber of tags: %d\n", pathstr, sata->tags); } + if ((sata->valid & CTS_SATA_VALID_CAPS) != 0) { + fprintf(stdout, "%sSATA capabilities: %08x\n", pathstr, + sata->caps); + } } if (cts->protocol == PROTO_SCSI) { struct ccb_trans_settings_scsi *scsi= diff --git a/sys/cam/ata/ata_pmp.c b/sys/cam/ata/ata_pmp.c index b60a4a7..0835a2b 100644 --- a/sys/cam/ata/ata_pmp.c +++ b/sys/cam/ata/ata_pmp.c @@ -101,6 +101,7 @@ struct pmp_softc { int events; #define PMP_EV_RESET 1 #define PMP_EV_RESCAN 2 + u_int caps; struct task sysctl_task; struct sysctl_ctx_list sysctl_ctx; struct sysctl_oid *sysctl_tree; @@ -457,6 +458,14 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb) ata_pm_read_cmd(ataio, 2, 15); break; case PMP_STATE_PRECONFIG: + /* Get/update host SATA capabilities. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE); + cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; + cts.type = CTS_TYPE_CURRENT_SETTINGS; + xpt_action((union ccb *)&cts); + if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) + softc->caps = cts.xport_specific.sata.caps; cam_fill_ataio(ataio, pmp_retry_count, pmpdone, @@ -644,14 +653,16 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb) (done_ccb->ataio.res.lba_mid << 16) + (done_ccb->ataio.res.lba_low << 8) + done_ccb->ataio.res.sector_count; - if ((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) { + if (((res & 0xf0f) == 0x103 && (res & 0x0f0) != 0) || + (res & 0x600) != 0) { if (bootverbose) { printf("%s%d: port %d status: %08x\n", periph->periph_name, periph->unit_number, softc->pm_step, res); } - /* Report device speed. */ - if (xpt_create_path(&dpath, periph, + /* Report device speed if it is online. */ + if ((res & 0xf0f) == 0x103 && + xpt_create_path(&dpath, periph, xpt_path_path_id(periph->path), softc->pm_step, 0) == CAM_REQ_CMP) { bzero(&cts, sizeof(cts)); @@ -660,6 +671,9 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb) cts.type = CTS_TYPE_CURRENT_SETTINGS; cts.xport_specific.sata.revision = (res & 0x0f0) >> 4; cts.xport_specific.sata.valid = CTS_SATA_VALID_REVISION; + cts.xport_specific.sata.caps = softc->caps & + (CTS_SATA_CAPS_H_PMREQ | CTS_SATA_CAPS_H_DMAAA); + cts.xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; xpt_action((union ccb *)&cts); xpt_free_path(dpath); } diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c index bd748cd..478b006 100644 --- a/sys/cam/ata/ata_xpt.c +++ b/sys/cam/ata/ata_xpt.c @@ -88,6 +88,9 @@ typedef enum { PROBE_IDENTIFY, PROBE_SPINUP, PROBE_SETMODE, + PROBE_SETPM, + PROBE_SETAPST, + PROBE_SETDMAAA, PROBE_SET_MULTI, PROBE_INQUIRY, PROBE_FULL_INQUIRY, @@ -101,6 +104,9 @@ static char *probe_action_text[] = { "PROBE_IDENTIFY", "PROBE_SPINUP", "PROBE_SETMODE", + "PROBE_SETPM", + "PROBE_SETAPST", + "PROBE_SETDMAAA", "PROBE_SET_MULTI", "PROBE_INQUIRY", "PROBE_FULL_INQUIRY", @@ -132,6 +138,7 @@ typedef struct { uint32_t pm_prv; int restart; int spinup; + u_int caps; struct cam_periph *periph; } probe_softc; @@ -393,6 +400,45 @@ negotiate: ata_28bit_cmd(ataio, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode); break; } + case PROBE_SETPM: + cam_fill_ataio(ataio, + 1, + probedone, + CAM_DIR_NONE, + 0, + NULL, + 0, + 30*1000); + ata_28bit_cmd(ataio, ATA_SETFEATURES, + (softc->caps & CTS_SATA_CAPS_H_PMREQ) ? 0x10 : 0x90, + 0, 0x03); + break; + case PROBE_SETAPST: + cam_fill_ataio(ataio, + 1, + probedone, + CAM_DIR_NONE, + 0, + NULL, + 0, + 30*1000); + ata_28bit_cmd(ataio, ATA_SETFEATURES, + (softc->caps & CTS_SATA_CAPS_H_APST) ? 0x10 : 0x90, + 0, 0x07); + break; + case PROBE_SETDMAAA: + cam_fill_ataio(ataio, + 1, + probedone, + CAM_DIR_NONE, + 0, + NULL, + 0, + 30*1000); + ata_28bit_cmd(ataio, ATA_SETFEATURES, + (softc->caps & CTS_SATA_CAPS_H_DMAAA) ? 0x10 : 0x90, + 0, 0x02); + break; case PROBE_SET_MULTI: { u_int sectors, bytecount; @@ -685,6 +731,7 @@ probedone(struct cam_periph *periph, union ccb *done_ccb) probe_softc *softc; struct cam_path *path; u_int32_t priority; + u_int caps; int found = 1; CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("probedone\n")); @@ -879,6 +926,67 @@ noerror: xpt_schedule(periph, priority); return; case PROBE_SETMODE: + if (path->device->transport != XPORT_SATA) + goto notsata; + /* Set supported bits. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); + cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; + cts.type = CTS_TYPE_CURRENT_SETTINGS; + xpt_action((union ccb *)&cts); + if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) + caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; + else + caps = 0; + if (ident_buf->satacapabilities != 0xffff) { + if (ident_buf->satacapabilities & ATA_SUPPORT_IFPWRMNGTRCV) + caps |= CTS_SATA_CAPS_D_PMREQ; + if (ident_buf->satacapabilities & ATA_SUPPORT_HAPST) + caps |= CTS_SATA_CAPS_D_APST; + } + /* Mask unwanted bits. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); + cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; + cts.type = CTS_TYPE_USER_SETTINGS; + xpt_action((union ccb *)&cts); + if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) + caps &= cts.xport_specific.sata.caps; + /* Store result to SIM. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); + cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; + cts.type = CTS_TYPE_CURRENT_SETTINGS; + cts.xport_specific.sata.caps = caps; + cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; + xpt_action((union ccb *)&cts); + softc->caps = caps; + if (ident_buf->satasupport & ATA_SUPPORT_IFPWRMNGT) { + PROBE_SET_ACTION(softc, PROBE_SETPM); + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + /* FALLTHROUGH */ + case PROBE_SETPM: + if (ident_buf->satacapabilities != 0xffff && + ident_buf->satacapabilities & ATA_SUPPORT_DAPST) { + PROBE_SET_ACTION(softc, PROBE_SETAPST); + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + /* FALLTHROUGH */ + case PROBE_SETAPST: + if (ident_buf->satasupport & ATA_SUPPORT_AUTOACTIVATE) { + PROBE_SET_ACTION(softc, PROBE_SETDMAAA); + xpt_release_ccb(done_ccb); + xpt_schedule(periph, priority); + return; + } + /* FALLTHROUGH */ + case PROBE_SETDMAAA: +notsata: if (path->device->protocol == PROTO_ATA) { PROBE_SET_ACTION(softc, PROBE_SET_MULTI); } else { @@ -964,6 +1072,35 @@ noerror: snprintf(ident_buf->revision, sizeof(ident_buf->revision), "%04x", softc->pm_prv); path->device->flags |= CAM_DEV_IDENTIFY_DATA_VALID; + /* Set supported bits. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); + cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; + cts.type = CTS_TYPE_CURRENT_SETTINGS; + xpt_action((union ccb *)&cts); + if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) + caps = cts.xport_specific.sata.caps & CTS_SATA_CAPS_H; + else + caps = 0; + /* All PMPs must support PM requests. */ + caps |= CTS_SATA_CAPS_D_PMREQ; + /* Mask unwanted bits. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); + cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; + cts.type = CTS_TYPE_USER_SETTINGS; + xpt_action((union ccb *)&cts); + if (cts.xport_specific.sata.valid & CTS_SATA_VALID_CAPS) + caps &= cts.xport_specific.sata.caps; + /* Store result to SIM. */ + bzero(&cts, sizeof(cts)); + xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE); + cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS; + cts.type = CTS_TYPE_CURRENT_SETTINGS; + cts.xport_specific.sata.caps = caps; + cts.xport_specific.sata.valid = CTS_SATA_VALID_CAPS; + xpt_action((union ccb *)&cts); + softc->caps = caps; if (periph->path->device->flags & CAM_DEV_UNCONFIGURED) { path->device->flags &= ~CAM_DEV_UNCONFIGURED; xpt_acquire_device(path->device); diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h index 2810c54..c5ac35e 100644 --- a/sys/cam/cam_ccb.h +++ b/sys/cam/cam_ccb.h @@ -837,12 +837,21 @@ struct ccb_trans_settings_sata { #define CTS_SATA_VALID_PM 0x08 #define CTS_SATA_VALID_TAGS 0x10 #define CTS_SATA_VALID_ATAPI 0x20 +#define CTS_SATA_VALID_CAPS 0x40 int mode; /* Legacy PATA mode */ u_int bytecount; /* Length of PIO transaction */ int revision; /* SATA revision */ u_int pm_present; /* PM is present (XPT->SIM) */ u_int tags; /* Number of allowed tags */ u_int atapi; /* Length of ATAPI CDB */ + u_int caps; /* Device and host SATA caps. */ +#define CTS_SATA_CAPS_H 0x0000ffff +#define CTS_SATA_CAPS_H_PMREQ 0x00000001 +#define CTS_SATA_CAPS_H_APST 0x00000002 +#define CTS_SATA_CAPS_H_DMAAA 0x00000010 /* Auto-activation */ +#define CTS_SATA_CAPS_D 0xffff0000 +#define CTS_SATA_CAPS_D_PMREQ 0x00010000 +#define CTS_SATA_CAPS_D_APST 0x00020000 }; /* Get/Set transfer rate/width/disconnection/tag queueing settings */ diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 34f1be4..60fb851 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -111,6 +111,7 @@ static struct { #define AHCI_Q_EDGEIS 64 #define AHCI_Q_SATA2 128 #define AHCI_Q_NOBSYRES 256 +#define AHCI_Q_NOAA 512 } ahci_ids[] = { {0x43801002, 0x00, "ATI IXP600", 0}, {0x43901002, 0x00, "ATI IXP700", 0}, @@ -167,75 +168,75 @@ static struct { {0x614511ab, 0x00, "Marvell 88SX6145", AHCI_Q_NOFORCE|AHCI_Q_4CH|AHCI_Q_EDGEIS}, {0x91231b4b, 0x11, "Marvell 88SE912x", AHCI_Q_NOBSYRES}, {0x91231b4b, 0x00, "Marvell 88SE912x", AHCI_Q_EDGEIS|AHCI_Q_SATA2|AHCI_Q_NOBSYRES}, - {0x044c10de, 0x00, "NVIDIA MCP65", 0}, - {0x044d10de, 0x00, "NVIDIA MCP65", 0}, - {0x044e10de, 0x00, "NVIDIA MCP65", 0}, - {0x044f10de, 0x00, "NVIDIA MCP65", 0}, - {0x045c10de, 0x00, "NVIDIA MCP65", 0}, - {0x045d10de, 0x00, "NVIDIA MCP65", 0}, - {0x045e10de, 0x00, "NVIDIA MCP65", 0}, - {0x045f10de, 0x00, "NVIDIA MCP65", 0}, - {0x055010de, 0x00, "NVIDIA MCP67", 0}, - {0x055110de, 0x00, "NVIDIA MCP67", 0}, - {0x055210de, 0x00, "NVIDIA MCP67", 0}, - {0x055310de, 0x00, "NVIDIA MCP67", 0}, - {0x055410de, 0x00, "NVIDIA MCP67", 0}, - {0x055510de, 0x00, "NVIDIA MCP67", 0}, - {0x055610de, 0x00, "NVIDIA MCP67", 0}, - {0x055710de, 0x00, "NVIDIA MCP67", 0}, - {0x055810de, 0x00, "NVIDIA MCP67", 0}, - {0x055910de, 0x00, "NVIDIA MCP67", 0}, - {0x055A10de, 0x00, "NVIDIA MCP67", 0}, - {0x055B10de, 0x00, "NVIDIA MCP67", 0}, - {0x058410de, 0x00, "NVIDIA MCP67", 0}, - {0x07f010de, 0x00, "NVIDIA MCP73", 0}, - {0x07f110de, 0x00, "NVIDIA MCP73", 0}, - {0x07f210de, 0x00, "NVIDIA MCP73", 0}, - {0x07f310de, 0x00, "NVIDIA MCP73", 0}, - {0x07f410de, 0x00, "NVIDIA MCP73", 0}, - {0x07f510de, 0x00, "NVIDIA MCP73", 0}, - {0x07f610de, 0x00, "NVIDIA MCP73", 0}, - {0x07f710de, 0x00, "NVIDIA MCP73", 0}, - {0x07f810de, 0x00, "NVIDIA MCP73", 0}, - {0x07f910de, 0x00, "NVIDIA MCP73", 0}, - {0x07fa10de, 0x00, "NVIDIA MCP73", 0}, - {0x07fb10de, 0x00, "NVIDIA MCP73", 0}, - {0x0ad010de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad110de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad210de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad310de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad410de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad510de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad610de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad710de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad810de, 0x00, "NVIDIA MCP77", 0}, - {0x0ad910de, 0x00, "NVIDIA MCP77", 0}, - {0x0ada10de, 0x00, "NVIDIA MCP77", 0}, - {0x0adb10de, 0x00, "NVIDIA MCP77", 0}, - {0x0ab410de, 0x00, "NVIDIA MCP79", 0}, - {0x0ab510de, 0x00, "NVIDIA MCP79", 0}, - {0x0ab610de, 0x00, "NVIDIA MCP79", 0}, - {0x0ab710de, 0x00, "NVIDIA MCP79", 0}, - {0x0ab810de, 0x00, "NVIDIA MCP79", 0}, - {0x0ab910de, 0x00, "NVIDIA MCP79", 0}, - {0x0aba10de, 0x00, "NVIDIA MCP79", 0}, - {0x0abb10de, 0x00, "NVIDIA MCP79", 0}, - {0x0abc10de, 0x00, "NVIDIA MCP79", 0}, - {0x0abd10de, 0x00, "NVIDIA MCP79", 0}, - {0x0abe10de, 0x00, "NVIDIA MCP79", 0}, - {0x0abf10de, 0x00, "NVIDIA MCP79", 0}, - {0x0d8410de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8510de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8610de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8710de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8810de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8910de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8a10de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8b10de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8c10de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8d10de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8e10de, 0x00, "NVIDIA MCP89", 0}, - {0x0d8f10de, 0x00, "NVIDIA MCP89", 0}, + {0x044c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA}, + {0x044d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA}, + {0x044e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA}, + {0x044f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA}, + {0x045c10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA}, + {0x045d10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA}, + {0x045e10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA}, + {0x045f10de, 0x00, "NVIDIA MCP65", AHCI_Q_NOAA}, + {0x055010de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055110de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055210de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055310de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055510de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055610de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055710de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055810de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055910de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055A10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x055B10de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x058410de, 0x00, "NVIDIA MCP67", AHCI_Q_NOAA}, + {0x07f010de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f110de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f210de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f310de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f410de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f510de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f610de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f710de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f810de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07f910de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07fa10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x07fb10de, 0x00, "NVIDIA MCP73", AHCI_Q_NOAA}, + {0x0ad010de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad110de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad210de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad310de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad410de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad510de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad610de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad710de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad810de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ad910de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ada10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0adb10de, 0x00, "NVIDIA MCP77", AHCI_Q_NOAA}, + {0x0ab410de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0ab510de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0ab610de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0ab710de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0ab810de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0ab910de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0aba10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0abb10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0abc10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0abd10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0abe10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0abf10de, 0x00, "NVIDIA MCP79", AHCI_Q_NOAA}, + {0x0d8410de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8510de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8610de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8710de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8810de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8910de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8a10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8b10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8c10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8d10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8e10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, + {0x0d8f10de, 0x00, "NVIDIA MCP89", AHCI_Q_NOAA}, {0x33491106, 0x00, "VIA VT8251", 0}, {0x62871106, 0x00, "VIA VT8251", 0}, {0x11841039, 0x00, "SiS 966", 0}, @@ -860,7 +861,14 @@ ahci_ch_attach(device_t dev) ch->user[i].mode = 0; ch->user[i].bytecount = 8192; ch->user[i].tags = ch->numslots; + ch->user[i].caps = 0; ch->curr[i] = ch->user[i]; + if (ch->pm_level) { + ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ | + CTS_SATA_CAPS_H_APST | + CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST; + } + ch->user[i].caps |= CTS_SATA_CAPS_H_DMAAA; } rid = ch->unit; if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, @@ -1960,7 +1968,8 @@ ahci_end_transaction(struct ahci_slot *slot, enum ahci_err_type et) et != AHCI_ERR_TIMEOUT) ahci_rearm_timeout(dev); /* Start PM timer. */ - if (ch->numrslots == 0 && ch->pm_level > 3) { + if (ch->numrslots == 0 && ch->pm_level > 3 && + (ch->curr[ch->pm_present ? 15 : 0].caps & CTS_SATA_CAPS_D_PMREQ)) { callout_schedule(&ch->pm_timer, (ch->pm_level == 4) ? hz / 1000 : hz / 8); } @@ -2464,6 +2473,8 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) ch->pm_present = cts->xport_specific.sata.pm_present; if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI) d->atapi = cts->xport_specific.sata.atapi; + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS) + d->caps = cts->xport_specific.sata.caps; ccb->ccb_h.status = CAM_REQ_CMP; break; } @@ -2496,9 +2507,24 @@ ahciaction(struct cam_sim *sim, union ccb *ccb) cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION; } + cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D; + if (ch->pm_level) { + if (ch->caps & (AHCI_CAP_PSC | AHCI_CAP_SSC)) + cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ; + if (ch->caps2 & AHCI_CAP2_APST) + cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_APST; + } + if ((ch->caps & AHCI_CAP_SNCQ) && + (ch->quirks & AHCI_Q_NOAA) == 0) + cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_DMAAA; + cts->xport_specific.sata.caps &= + ch->user[ccb->ccb_h.target_id].caps; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; } else { cts->xport_specific.sata.revision = d->revision; cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION; + cts->xport_specific.sata.caps = d->caps; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; } cts->xport_specific.sata.mode = d->mode; cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE; diff --git a/sys/dev/ahci/ahci.h b/sys/dev/ahci/ahci.h index d4c73c9..1473962 100644 --- a/sys/dev/ahci/ahci.h +++ b/sys/dev/ahci/ahci.h @@ -372,6 +372,7 @@ struct ahci_device { u_int bytecount; u_int atapi; u_int tags; + u_int caps; }; /* structure describing an ATA channel */ diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c index c60d8e4..937d04c 100644 --- a/sys/dev/siis/siis.c +++ b/sys/dev/siis/siis.c @@ -448,6 +448,8 @@ siis_ch_attach(device_t dev) ch->user[i].bytecount = 8192; ch->user[i].tags = SIIS_MAX_SLOTS; ch->curr[i] = ch->user[i]; + if (ch->pm_level) + ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ; } mtx_init(&ch->mtx, "SIIS channel lock", NULL, MTX_DEF); rid = ch->unit; @@ -1697,6 +1699,8 @@ siisaction(struct cam_sim *sim, union ccb *ccb) } if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS) d->atapi = cts->xport_specific.sata.atapi; + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS) + d->caps = cts->xport_specific.sata.caps; ccb->ccb_h.status = CAM_REQ_CMP; break; } @@ -1729,9 +1733,17 @@ siisaction(struct cam_sim *sim, union ccb *ccb) cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION; } + cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D; + if (ch->pm_level) + cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ; + cts->xport_specific.sata.caps &= + ch->user[ccb->ccb_h.target_id].caps; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; } else { cts->xport_specific.sata.revision = d->revision; cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION; + cts->xport_specific.sata.caps = d->caps; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; } cts->xport_specific.sata.mode = d->mode; cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE; diff --git a/sys/dev/siis/siis.h b/sys/dev/siis/siis.h index 92b4e26..5317628 100644 --- a/sys/dev/siis/siis.h +++ b/sys/dev/siis/siis.h @@ -358,6 +358,7 @@ struct siis_device { u_int bytecount; u_int atapi; u_int tags; + u_int caps; }; /* structure describing an ATA channel */ -- cgit v1.1 From d5713c1a661261bc94fc6cb2d001d097809354b4 Mon Sep 17 00:00:00 2001 From: marius Date: Sun, 2 May 2010 12:08:15 +0000 Subject: Add a hack for SPARC64 V CPUs, which set some undocumented bits in the first data word. --- sys/sparc64/sparc64/interrupt.S | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sys/sparc64/sparc64/interrupt.S b/sys/sparc64/sparc64/interrupt.S index 75a9727..b71a05d 100644 --- a/sys/sparc64/sparc64/interrupt.S +++ b/sys/sparc64/sparc64/interrupt.S @@ -83,8 +83,11 @@ ENTRY(intr_vector) * The 2nd word points to code to execute and the 3rd is an argument * to pass. Jump to it. */ - brnz,a,pt %g3, 1f - nop + brnz,pt %g3, 1f + /* + * NB: Zeus CPUs set some undocumented bits in the first data word. + */ + and %g3, IV_MAX - 1, %g3 jmpl %g4, %g0 nop /* NOTREACHED */ -- cgit v1.1 From 0291fae9147177c16138f9331e693fabb1c2658b Mon Sep 17 00:00:00 2001 From: mav Date: Sun, 2 May 2010 14:46:05 +0000 Subject: Enable PCI busmastering explicitly to be sure. --- sys/dev/ahci/ahci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/dev/ahci/ahci.c b/sys/dev/ahci/ahci.c index 60fb851..1aa719e 100644 --- a/sys/dev/ahci/ahci.c +++ b/sys/dev/ahci/ahci.c @@ -340,6 +340,7 @@ ahci_attach(device_t dev) rman_fini(&ctlr->sc_iomem); return (error); } + pci_enable_busmaster(dev); /* Reset controller */ if ((error = ahci_ctlr_reset(dev)) != 0) { bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); -- cgit v1.1 From 1b4eb78965d8d551d4997edd6125fd401a212f5b Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 16:44:06 +0000 Subject: This change addresses the race condition that was introduced by the previous revision, r207450, to this file. Specifically, between dropping the page queues lock in vm_contig_launder() and reacquiring it in vm_contig_launder_page(), the page may be removed from the active or inactive queue. It could be wired, freed, cached, etc. None of which vm_contig_launder_page() is prepared for. Reviewed by: kib, kmacy --- sys/vm/vm_contig.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index 2c8b8b1..e6a9b78 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -96,33 +96,33 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next) vm_page_t m_tmp; struct vnode *vp; struct mount *mp; - int vfslocked, dirty; + int vfslocked; - vm_page_lock(m); - vm_page_lock_queues(); + mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); object = m->object; if (!VM_OBJECT_TRYLOCK(object) && !vm_pageout_fallback_object_lock(m, next)) { - VM_OBJECT_UNLOCK(object); - vm_page_unlock_queues(); vm_page_unlock(m); + VM_OBJECT_UNLOCK(object); return (EAGAIN); } if (vm_page_sleep_if_busy(m, TRUE, "vpctw0")) { VM_OBJECT_UNLOCK(object); + vm_page_lock_queues(); return (EBUSY); } vm_page_test_dirty(m); if (m->dirty == 0 && m->hold_count == 0) pmap_remove_all(m); - if ((dirty = m->dirty) != 0) { - vm_page_unlock_queues(); + if (m->dirty != 0) { vm_page_unlock(m); if ((object->flags & OBJ_DEAD) != 0) { VM_OBJECT_UNLOCK(object); return (EAGAIN); } if (object->type == OBJT_VNODE) { + vm_page_unlock_queues(); vp = object->handle; vm_object_reference_locked(object); VM_OBJECT_UNLOCK(object); @@ -136,19 +136,20 @@ vm_contig_launder_page(vm_page_t m, vm_page_t *next) VFS_UNLOCK_GIANT(vfslocked); vm_object_deallocate(object); vn_finished_write(mp); + vm_page_lock_queues(); return (0); } else if (object->type == OBJT_SWAP || object->type == OBJT_DEFAULT) { + vm_page_unlock_queues(); m_tmp = m; vm_pageout_flush(&m_tmp, 1, VM_PAGER_PUT_SYNC); VM_OBJECT_UNLOCK(object); + vm_page_lock_queues(); return (0); } - } else if (m->hold_count == 0) - vm_page_cache(m); - - if (dirty == 0) { - vm_page_unlock_queues(); + } else { + if (m->hold_count == 0) + vm_page_cache(m); vm_page_unlock(m); } VM_OBJECT_UNLOCK(object); @@ -167,11 +168,12 @@ vm_contig_launder(int queue) if ((m->flags & PG_MARKER) != 0) continue; + if (!vm_page_trylock(m)) + continue; KASSERT(VM_PAGE_INQUEUE2(m, queue), ("vm_contig_launder: page %p's queue is not %d", m, queue)); - vm_page_unlock_queues(); error = vm_contig_launder_page(m, &next); - vm_page_lock_queues(); + vm_page_lock_assert(m, MA_NOTOWNED); if (error == 0) return (TRUE); if (error == EBUSY) -- cgit v1.1 From f35e97166b133de28351ffee3f6de3407d0272b7 Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 17:33:46 +0000 Subject: It makes no sense for vm_page_sleep_if_busy()'s helper, vm_page_sleep(), to unconditionally set PG_REFERENCED on a page before sleeping. In many cases, it's perfectly ok for the page to disappear, i.e., be reclaimed by the page daemon, before the caller to vm_page_sleep() is reawakened. Instead, we now explicitly set PG_REFERENCED in those cases where having the page persist until the caller is awakened is clearly desirable. Note, however, that setting PG_REFERENCED on the page is still only a hint, and not a guarantee that the page should persist. --- sys/fs/tmpfs/tmpfs_vnops.c | 30 +++++++++++++++++++++++++++--- sys/kern/vfs_bio.c | 11 ++++++++++- sys/vm/vm_fault.c | 6 ++++++ sys/vm/vm_page.c | 25 ++++++++++++++++--------- 4 files changed, 59 insertions(+), 13 deletions(-) diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index c17efff..3d3755d 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -516,8 +516,16 @@ tmpfs_mappedread(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *uio lookupvpg: if (((m = vm_page_lookup(vobj, idx)) != NULL) && vm_page_is_valid(m, offset, tlen)) { - if (vm_page_sleep_if_busy(m, FALSE, "tmfsmr")) + if ((m->oflags & VPO_BUSY) != 0) { + /* + * Reference the page before unlocking and sleeping so + * that the page daemon is less likely to reclaim it. + */ + vm_page_lock_queues(); + vm_page_flag_set(m, PG_REFERENCED); + vm_page_sleep(m, "tmfsmr"); goto lookupvpg; + } vm_page_busy(m); VM_OBJECT_UNLOCK(vobj); error = uiomove_fromphys(&m, offset, tlen, uio); @@ -526,8 +534,16 @@ lookupvpg: VM_OBJECT_UNLOCK(vobj); return (error); } else if (m != NULL && uio->uio_segflg == UIO_NOCOPY) { - if (vm_page_sleep_if_busy(m, FALSE, "tmfsmr")) + if ((m->oflags & VPO_BUSY) != 0) { + /* + * Reference the page before unlocking and sleeping so + * that the page daemon is less likely to reclaim it. + */ + vm_page_lock_queues(); + vm_page_flag_set(m, PG_REFERENCED); + vm_page_sleep(m, "tmfsmr"); goto lookupvpg; + } vm_page_busy(m); VM_OBJECT_UNLOCK(vobj); sched_pin(); @@ -627,8 +643,16 @@ tmpfs_mappedwrite(vm_object_t vobj, vm_object_t tobj, size_t len, struct uio *ui lookupvpg: if (((vpg = vm_page_lookup(vobj, idx)) != NULL) && vm_page_is_valid(vpg, offset, tlen)) { - if (vm_page_sleep_if_busy(vpg, FALSE, "tmfsmw")) + if ((vpg->oflags & VPO_BUSY) != 0) { + /* + * Reference the page before unlocking and sleeping so + * that the page daemon is less likely to reclaim it. + */ + vm_page_lock_queues(); + vm_page_flag_set(vpg, PG_REFERENCED); + vm_page_sleep(vpg, "tmfsmw"); goto lookupvpg; + } vm_page_busy(vpg); vm_page_lock_queues(); vm_page_undirty(vpg); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index ea846a5..dbcd6e8 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -3024,8 +3024,17 @@ allocbuf(struct buf *bp, int size) * vm_fault->getpages->cluster_read->allocbuf * */ - if (vm_page_sleep_if_busy(m, FALSE, "pgtblk")) + if ((m->oflags & VPO_BUSY) != 0) { + /* + * Reference the page before unlocking + * and sleeping so that the page daemon + * is less likely to reclaim it. + */ + vm_page_lock_queues(); + vm_page_flag_set(m, PG_REFERENCED); + vm_page_sleep(m, "pgtblk"); continue; + } /* * We have a good page. diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index d9cf63e..5ee4ab4 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -338,6 +338,12 @@ RetryFault:; * to pmap it. */ if ((fs.m->oflags & VPO_BUSY) || fs.m->busy) { + /* + * Reference the page before unlocking and + * sleeping so that the page daemon is less + * likely to reclaim it. + */ + vm_page_flag_set(fs.m, PG_REFERENCED); vm_page_unlock_queues(); vm_page_unlock(fs.m); VM_OBJECT_UNLOCK(fs.object); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index fb0950e..e73586a 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -599,7 +599,7 @@ vm_page_free_zero(vm_page_t m) /* * vm_page_sleep: * - * Sleep and release the page queues lock. + * Sleep and release the page and page queues locks. * * The object containing the given page must be locked. */ @@ -608,13 +608,10 @@ vm_page_sleep(vm_page_t m, const char *msg) { VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED); - if (!mtx_owned(vm_page_lockptr(m))) - vm_page_lock(m); - if (!mtx_owned(&vm_page_queue_mtx)) - vm_page_lock_queues(); - vm_page_flag_set(m, PG_REFERENCED); - vm_page_unlock_queues(); - vm_page_unlock(m); + if (mtx_owned(&vm_page_queue_mtx)) + vm_page_unlock_queues(); + if (mtx_owned(vm_page_lockptr(m))) + vm_page_unlock(m); /* * It's possible that while we sleep, the page will get @@ -1896,7 +1893,17 @@ vm_page_grab(vm_object_t object, vm_pindex_t pindex, int allocflags) VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); retrylookup: if ((m = vm_page_lookup(object, pindex)) != NULL) { - if (vm_page_sleep_if_busy(m, TRUE, "pgrbwt")) { + if ((m->oflags & VPO_BUSY) != 0 || m->busy != 0) { + if ((allocflags & VM_ALLOC_RETRY) != 0) { + /* + * Reference the page before unlocking and + * sleeping so that the page daemon is less + * likely to reclaim it. + */ + vm_page_lock_queues(); + vm_page_flag_set(m, PG_REFERENCED); + } + vm_page_sleep(m, "pgrbwt"); if ((allocflags & VM_ALLOC_RETRY) == 0) return (NULL); goto retrylookup; -- cgit v1.1 From 222e69a75f76187cc43cdcd0c8c825664956ce78 Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 18:09:33 +0000 Subject: Correct an error in r207410: Remove an unlock of a lock that is no longer held. --- sys/vm/vm_object.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 604aa3c..b5f246c 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1454,7 +1454,6 @@ retry: * not be changed by this operation. */ if ((m->oflags & VPO_BUSY) || m->busy) { - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(new_object); m->oflags |= VPO_WANTED; msleep(m, VM_OBJECT_MTX(orig_object), PVM, "spltwt", 0); -- cgit v1.1 From 5af1cc0b3d39d86988e33262f6c84b4609244a9a Mon Sep 17 00:00:00 2001 From: marius Date: Sun, 2 May 2010 19:05:57 +0000 Subject: Remove a soft member which was never used. Approved by: marcel --- sys/dev/quicc/quicc_bfe.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/quicc/quicc_bfe.h b/sys/dev/quicc/quicc_bfe.h index 9ba622c..5c58914 100644 --- a/sys/dev/quicc/quicc_bfe.h +++ b/sys/dev/quicc/quicc_bfe.h @@ -50,7 +50,6 @@ struct quicc_softc { u_int sc_clock; int sc_fastintr:1; - int sc_leaving:1; int sc_polled:1; }; -- cgit v1.1 From 6637c2369d116e42113a80f7912a0b5a2d9e7fbf Mon Sep 17 00:00:00 2001 From: marius Date: Sun, 2 May 2010 19:07:19 +0000 Subject: Remove redundant checking of sc_leaving (uart_intr() already handles this). Approved by: marcel --- sys/dev/uart/uart_dev_ns8250.c | 2 +- sys/mips/cavium/uart_dev_oct16550.c | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index c01fd61..b93e254 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -604,7 +604,7 @@ ns8250_bus_ipend(struct uart_softc *sc) if (ipend == 0) ns8250_clrint(bas); uart_unlock(sc->sc_hwmtx); - return ((sc->sc_leaving) ? 0 : ipend); + return (ipend); } static int diff --git a/sys/mips/cavium/uart_dev_oct16550.c b/sys/mips/cavium/uart_dev_oct16550.c index 3e6d7c7..5c6e11e 100644 --- a/sys/mips/cavium/uart_dev_oct16550.c +++ b/sys/mips/cavium/uart_dev_oct16550.c @@ -644,12 +644,9 @@ oct16550_bus_ipend(struct uart_softc *sc) if (ipend) octeon_led_run_wheel(&where1, 6 + device_get_unit(sc->sc_dev)); #endif - return ((sc->sc_leaving) ? 0 : ipend); + return (ipend); } - - - static int oct16550_bus_param (struct uart_softc *sc, int baudrate, int databits, int stopbits, int parity) -- cgit v1.1 From 299c89c6fb0cdd9e93b22b9aed707322f2846c8a Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 19:10:27 +0000 Subject: Properly synchronize access to the page's hold_count in vfs_vmio_release(). Reviewed by: kib --- sys/kern/vfs_bio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index dbcd6e8..1048998 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -1563,7 +1563,6 @@ vfs_vmio_release(struct buf *bp) vm_page_t m; VM_OBJECT_LOCK(bp->b_bufobj->bo_object); - vm_page_lock_queues(); for (i = 0; i < bp->b_npages; i++) { m = bp->b_pages[i]; bp->b_pages[i] = NULL; @@ -1571,16 +1570,16 @@ vfs_vmio_release(struct buf *bp) * In order to keep page LRU ordering consistent, put * everything on the inactive queue. */ + vm_page_lock(m); + vm_page_lock_queues(); vm_page_unwire(m, 0); /* * We don't mess with busy pages, it is * the responsibility of the process that * busied the pages to deal with them. */ - if ((m->oflags & VPO_BUSY) || (m->busy != 0)) - continue; - - if (m->wire_count == 0) { + if ((m->oflags & VPO_BUSY) == 0 && m->busy == 0 && + m->wire_count == 0) { /* * Might as well free the page if we can and it has * no valid data. We also free the page if the @@ -1595,8 +1594,9 @@ vfs_vmio_release(struct buf *bp) vm_page_try_to_cache(m); } } + vm_page_unlock_queues(); + vm_page_unlock(m); } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object); pmap_qremove(trunc_page((vm_offset_t) bp->b_data), bp->b_npages); -- cgit v1.1 From 9c4f2e9ab2c6f540192e135b002316c170d45a76 Mon Sep 17 00:00:00 2001 From: kib Date: Sun, 2 May 2010 19:25:22 +0000 Subject: Lock the page around hold_count access. Reviewed by: alc --- sys/kern/uipc_syscalls.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index a14be72..3271235 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -2108,6 +2108,7 @@ retry_space: mbstat.sf_iocnt++; } if (error) { + vm_page_lock(pg); vm_page_lock_queues(); vm_page_unwire(pg, 0); /* @@ -2121,6 +2122,7 @@ retry_space: vm_page_free(pg); } vm_page_unlock_queues(); + vm_page_unlock(pg); VM_OBJECT_UNLOCK(obj); if (error == EAGAIN) error = 0; /* not a real error */ -- cgit v1.1 From 071496a9c757550fc1834fc2cbdd8d6d142ca23b Mon Sep 17 00:00:00 2001 From: mav Date: Sun, 2 May 2010 19:28:30 +0000 Subject: Import mvs(4) - Marvell 88SX50XX/88SX60XX/88SX70XX/SoC SATA controllers driver for CAM ATA subsystem. This driver supports same hardware as atamarvell, ataadaptec and atamvsata drivers from ata(4), but provides many additional features, such as NCQ, PMP, etc. --- share/man/man4/Makefile | 1 + share/man/man4/mvs.4 | 176 ++++ sys/arm/mv/files.mv | 1 + sys/conf/NOTES | 2 + sys/conf/files | 3 + sys/conf/kmod.mk | 2 +- sys/dev/mvs/mvs.c | 2173 ++++++++++++++++++++++++++++++++++++++++++++++ sys/dev/mvs/mvs.h | 650 ++++++++++++++ sys/dev/mvs/mvs_if.m | 34 + sys/dev/mvs/mvs_pci.c | 507 +++++++++++ sys/dev/mvs/mvs_soc.c | 437 ++++++++++ sys/modules/Makefile | 1 + sys/modules/mvs/Makefile | 10 + 13 files changed, 3996 insertions(+), 1 deletion(-) create mode 100644 share/man/man4/mvs.4 create mode 100644 sys/dev/mvs/mvs.c create mode 100644 sys/dev/mvs/mvs.h create mode 100644 sys/dev/mvs/mvs_if.m create mode 100644 sys/dev/mvs/mvs_pci.c create mode 100644 sys/dev/mvs/mvs_soc.c create mode 100644 sys/modules/mvs/Makefile diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index c71a097..b1282da 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -220,6 +220,7 @@ MAN= aac.4 \ msk.4 \ mtio.4 \ multicast.4 \ + mvs.4 \ mwl.4 \ mwlfw.4 \ mxge.4 \ diff --git a/share/man/man4/mvs.4 b/share/man/man4/mvs.4 new file mode 100644 index 0000000..5999335 --- /dev/null +++ b/share/man/man4/mvs.4 @@ -0,0 +1,176 @@ +.\" Copyright (c) 2009 Alexander Motin +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 27, 2010 +.Dt MVS 4 +.Os +.Sh NAME +.Nm mvs +.Nd Marvell Serial ATA Host Controller driver +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device pci" +.Cd "device scbus" +.Cd "device mvs" +.Ed +.Pp +Alternatively, to load the driver as a +module at boot time, place the following line in +.Xr loader.conf 5 : +.Bd -literal -offset indent +mvs_load="YES" +.Ed +.Pp +The following tunables are settable from the +.Xr loader 8 : +.Bl -ohang +.It Va hint.mvs. Ns Ar X Ns Va .msi +controls Message Signaled Interrupts (MSI) usage by the specified controller. +.It Va hint.mvs. Ns Ar X Ns Va .ccc +controls Command Completion Coalescing (CCC) usage by the specified controller. +Non-zero value enables CCC and defines maximum time (in us), request can wait +for interrupt. +CCC reduces number of context switches on systems with many parallel requests, +but it can decrease disk performance on some workloads due to additional +command latency. +.It Va hint.mvs. Ns Ar X Ns Va .cccc +defines number of completed commands for CCC, which trigger interrupt without +waiting for specified coalescing timeout. +.It Va hint.mvs. Ns Ar X Ns Va .pm_level +controls SATA interface Power Management for the specified channel, +allowing some power to be saved at the cost of additional command +latency. +Possible values: +.Bl -tag -compact +.It 0 +interface Power Management is disabled (default); +.It 1 +device is allowed to initiate PM state change, host is passive; +.It 4 +driver initiates PARTIAL PM state transition 1ms after port becomes idle; +.It 5 +driver initiates SLUMBER PM state transition 125ms after port becomes idle. +.El +.Pp +Note that interface Power Management is not compatible with +device presence detection. +A manual bus reset is needed on device hot-plug. +.It Va hint.mvs. Ns Ar X Ns Va .sata_rev +setting to nonzero value limits maximum SATA revision (speed). +Values 1, 2 and 3 are respectively 1.5, 3 and 6Gbps. +.El +.Sh DESCRIPTION +This driver provides the +.Xr CAM 4 +subsystem with native access to the +.Tn SATA +ports of several generations (Gen-I/II/IIe) of Marvell SATA controllers. +Each SATA port found is represented to CAM as a separate bus with one +target, or, if HBA supports Port Multipliers (Gen-II/IIe), 16 targets. +Most of the bus-management details are handled by the SATA-specific +transport of CAM. +Connected ATA disks are handled by the ATA protocol disk peripheral driver +.Xr ada 4 . +ATAPI devices are handled by the SCSI protocol peripheral drivers +.Xr cd 4 , +.Xr da 4 , +.Xr sa 4 , +etc. +.Pp +Driver features include support for Serial ATA and ATAPI devices, +Port Multipliers (including FIS-based switching, when supported), +hardware command queues (up to 31 command per port), +Native Command Queuing, SATA interface Power Management, device hot-plug +and Message Signaled Interrupts. +.Pp +Same hardware is also supported by atamarvell and ataadaptec drivers from +.Xr ata 4 +subsystem. +If both drivers are loaded at the same time, this one will be +given precedence as the more functional of the two. +.Sh HARDWARE +The +.Nm +driver supports the following controllers: +.Bl -tag -compact +.It Gen-I (SATA 1.5Gbps): +.Bl -bullet -compact +.It +88SX5040 +.It +88SX5041 +.It +88SX5080 +.It +88SX5081 +.El +.It Gen-II (SATA 3Gbps, NCQ, PMP): +.Bl -bullet -compact +.It +88SX6040 +.It +88SX6041 (including Adaptec 1420SA) +.It +88SX6080 +.It +88SX6081 +.El +.It Gen-IIe (SATA 3Gbps, NCQ, PMP with FBS): +.Bl -bullet -compact +.It +88SX6042 +.It +88SX7042 (including Adaptec 1430SA) +.It +88F5182 SoC +.It +88F6281 SoC +.It +MV78100 SoC +.El +.El +Note, that this hardware supports command queueing and FIS-based switching +only for ATA DMA commands. ATAPI and non-DMA ATA commands executed one by one +for each port. +.Pp +.Sh SEE ALSO +.Xr ada 4 , +.Xr ata 4 , +.Xr cam 4 , +.Xr cd 4 , +.Xr da 4 , +.Xr sa 4 +.Sh HISTORY +The +.Nm +driver first appeared in +.Fx 9.0 . +.Sh AUTHORS +.An Alexander Motin Aq mav@FreeBSD.org . diff --git a/sys/arm/mv/files.mv b/sys/arm/mv/files.mv index 36be745..d7352b7 100644 --- a/sys/arm/mv/files.mv +++ b/sys/arm/mv/files.mv @@ -30,6 +30,7 @@ arm/mv/timer.c standard arm/mv/twsi.c optional iicbus dev/mge/if_mge.c optional mge +dev/mvs/mvs_soc.c optional mvs dev/uart/uart_bus_mbus.c optional uart dev/uart/uart_cpu_mv.c optional uart dev/uart/uart_dev_ns8250.c optional uart diff --git a/sys/conf/NOTES b/sys/conf/NOTES index cc1964d..1ec82a9 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1660,12 +1660,14 @@ device twe # 3ware ATA RAID # Serial ATA host controllers: # # ahci: Advanced Host Controller Interface (AHCI) compatible +# mvs: Marvell 88SX50XX/88SX60XX/88SX70XX/SoC controllers # siis: SiliconImage SiI3124/SiI3132/SiI3531 controllers # # These drivers are part of cam(4) subsystem. They supersede less featured # ata(4) subsystem drivers, supporting same hardware. device ahci +device mvs device siis # diff --git a/sys/conf/files b/sys/conf/files index f4bb062..a485f2f 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1293,6 +1293,9 @@ dev/mpt/mpt_pci.c optional mpt pci dev/mpt/mpt_raid.c optional mpt dev/mpt/mpt_user.c optional mpt dev/msk/if_msk.c optional msk inet +dev/mvs/mvs.c optional mvs +dev/mvs/mvs_if.m standard +dev/mvs/mvs_pci.c optional mvs pci dev/mwl/if_mwl.c optional mwl dev/mwl/if_mwl_pci.c optional mwl pci dev/mwl/mwlhal.c optional mwl diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 18bfbb1..c6413d7 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -342,7 +342,7 @@ MFILES?= dev/acpica/acpi_if.m dev/acpi_support/acpi_wmi_if.m \ dev/agp/agp_if.m dev/ata/ata_if.m dev/eisa/eisa_if.m \ dev/iicbus/iicbb_if.m dev/iicbus/iicbus_if.m \ dev/mmc/mmcbr_if.m dev/mmc/mmcbus_if.m \ - dev/mii/miibus_if.m dev/ofw/ofw_bus_if.m \ + dev/mii/miibus_if.m dev/mvs/mvs_if.m dev/ofw/ofw_bus_if.m \ dev/pccard/card_if.m dev/pccard/power_if.m dev/pci/pci_if.m \ dev/pci/pcib_if.m dev/ppbus/ppbus_if.m dev/smbus/smbus_if.m \ dev/sound/pcm/ac97_if.m dev/sound/pcm/channel_if.m \ diff --git a/sys/dev/mvs/mvs.c b/sys/dev/mvs/mvs.c new file mode 100644 index 0000000..038e9f21 --- /dev/null +++ b/sys/dev/mvs/mvs.c @@ -0,0 +1,2173 @@ +/*- + * Copyright (c) 2010 Alexander Motin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mvs.h" + +#include +#include +#include +#include +#include + +/* local prototypes */ +static int mvs_ch_suspend(device_t dev); +static int mvs_ch_resume(device_t dev); +static void mvs_dmainit(device_t dev); +static void mvs_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error); +static void mvs_dmafini(device_t dev); +static void mvs_slotsalloc(device_t dev); +static void mvs_slotsfree(device_t dev); +static void mvs_setup_edma_queues(device_t dev); +static void mvs_set_edma_mode(device_t dev, enum mvs_edma_mode mode); +static void mvs_ch_pm(void *arg); +static void mvs_ch_intr_locked(void *data); +static void mvs_ch_intr(void *data); +static void mvs_reset(device_t dev); +static void mvs_softreset(device_t dev, union ccb *ccb); + +static int mvs_sata_connect(struct mvs_channel *ch); +static int mvs_sata_phy_reset(device_t dev); +static int mvs_wait(device_t dev, u_int s, u_int c, int t); +static void mvs_tfd_read(device_t dev, union ccb *ccb); +static void mvs_tfd_write(device_t dev, union ccb *ccb); +static void mvs_legacy_intr(device_t dev); +static void mvs_crbq_intr(device_t dev); +static void mvs_begin_transaction(device_t dev, union ccb *ccb); +static void mvs_legacy_execute_transaction(struct mvs_slot *slot); +static void mvs_timeout(struct mvs_slot *slot); +static void mvs_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error); +static void mvs_requeue_frozen(device_t dev); +static void mvs_execute_transaction(struct mvs_slot *slot); +static void mvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et); + +static void mvs_issue_read_log(device_t dev); +static void mvs_process_read_log(device_t dev, union ccb *ccb); + +static void mvsaction(struct cam_sim *sim, union ccb *ccb); +static void mvspoll(struct cam_sim *sim); + +MALLOC_DEFINE(M_MVS, "MVS driver", "MVS driver data buffers"); + +static int +mvs_ch_probe(device_t dev) +{ + + device_set_desc_copy(dev, "Marvell SATA channel"); + return (0); +} + +static int +mvs_ch_attach(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(device_get_parent(dev)); + struct mvs_channel *ch = device_get_softc(dev); + struct cam_devq *devq; + int rid, error, i, sata_rev = 0; + + ch->dev = dev; + ch->unit = (intptr_t)device_get_ivars(dev); + ch->quirks = ctlr->quirks; + mtx_init(&ch->mtx, "MVS channel lock", NULL, MTX_DEF); + resource_int_value(device_get_name(dev), + device_get_unit(dev), "pm_level", &ch->pm_level); + if (ch->pm_level > 3) + callout_init_mtx(&ch->pm_timer, &ch->mtx, 0); + resource_int_value(device_get_name(dev), + device_get_unit(dev), "sata_rev", &sata_rev); + for (i = 0; i < 16; i++) { + ch->user[i].revision = sata_rev; + ch->user[i].mode = 0; + ch->user[i].bytecount = (ch->quirks & MVS_Q_GENIIE) ? 8192 : 2048; + ch->user[i].tags = MVS_MAX_SLOTS; + ch->curr[i] = ch->user[i]; + if (ch->pm_level) { + ch->user[i].caps = CTS_SATA_CAPS_H_PMREQ | + CTS_SATA_CAPS_H_APST | + CTS_SATA_CAPS_D_PMREQ | CTS_SATA_CAPS_D_APST; + } + } + rid = ch->unit; + if (!(ch->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &rid, RF_ACTIVE))) + return (ENXIO); + mvs_dmainit(dev); + mvs_slotsalloc(dev); + mvs_ch_resume(dev); + mtx_lock(&ch->mtx); + rid = ATA_IRQ_RID; + if (!(ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &rid, RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "Unable to map interrupt\n"); + error = ENXIO; + goto err0; + } + if ((bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL, + mvs_ch_intr_locked, dev, &ch->ih))) { + device_printf(dev, "Unable to setup interrupt\n"); + error = ENXIO; + goto err1; + } + /* Create the device queue for our SIM. */ + devq = cam_simq_alloc(MVS_MAX_SLOTS - 1); + if (devq == NULL) { + device_printf(dev, "Unable to allocate simq\n"); + error = ENOMEM; + goto err1; + } + /* Construct SIM entry */ + ch->sim = cam_sim_alloc(mvsaction, mvspoll, "mvsch", ch, + device_get_unit(dev), &ch->mtx, + 2, (ch->quirks & MVS_Q_GENI) ? 0 : MVS_MAX_SLOTS - 1, + devq); + if (ch->sim == NULL) { + cam_simq_free(devq); + device_printf(dev, "unable to allocate sim\n"); + error = ENOMEM; + goto err1; + } + if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) { + device_printf(dev, "unable to register xpt bus\n"); + error = ENXIO; + goto err2; + } + if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim), + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + device_printf(dev, "unable to create path\n"); + error = ENXIO; + goto err3; + } + if (ch->pm_level > 3) { + callout_reset(&ch->pm_timer, + (ch->pm_level == 4) ? hz / 1000 : hz / 8, + mvs_ch_pm, dev); + } + mtx_unlock(&ch->mtx); + return (0); + +err3: + xpt_bus_deregister(cam_sim_path(ch->sim)); +err2: + cam_sim_free(ch->sim, /*free_devq*/TRUE); +err1: + bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); +err0: + bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem); + mtx_unlock(&ch->mtx); + mtx_destroy(&ch->mtx); + return (error); +} + +static int +mvs_ch_detach(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + + mtx_lock(&ch->mtx); + xpt_async(AC_LOST_DEVICE, ch->path, NULL); + xpt_free_path(ch->path); + xpt_bus_deregister(cam_sim_path(ch->sim)); + cam_sim_free(ch->sim, /*free_devq*/TRUE); + mtx_unlock(&ch->mtx); + + if (ch->pm_level > 3) + callout_drain(&ch->pm_timer); + bus_teardown_intr(dev, ch->r_irq, ch->ih); + bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ch->r_irq); + + mvs_ch_suspend(dev); + mvs_slotsfree(dev); + mvs_dmafini(dev); + + bus_release_resource(dev, SYS_RES_MEMORY, ch->unit, ch->r_mem); + mtx_destroy(&ch->mtx); + return (0); +} + +static int +mvs_ch_suspend(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + + /* Stop EDMA */ + mvs_set_edma_mode(dev, MVS_EDMA_OFF); + /* Disable port interrupts. */ + ATA_OUTL(ch->r_mem, EDMA_IEM, 0); + return (0); +} + +static int +mvs_ch_resume(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + uint32_t reg; + + /* Disable port interrupts */ + ATA_OUTL(ch->r_mem, EDMA_IEM, 0); + /* Stop EDMA */ + ch->curr_mode = MVS_EDMA_UNKNOWN; + mvs_set_edma_mode(dev, MVS_EDMA_OFF); + /* Clear and configure FIS interrupts. */ + ATA_OUTL(ch->r_mem, SATA_FISIC, 0); + reg = ATA_INL(ch->r_mem, SATA_FISC); + reg |= SATA_FISC_FISWAIT4HOSTRDYEN_B1; + ATA_OUTL(ch->r_mem, SATA_FISC, reg); + reg = ATA_INL(ch->r_mem, SATA_FISIM); + reg |= SATA_FISC_FISWAIT4HOSTRDYEN_B1; + ATA_OUTL(ch->r_mem, SATA_FISC, reg); + /* Clear SATA error register. */ + ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); + /* Clear any outstanding error interrupts. */ + ATA_OUTL(ch->r_mem, EDMA_IEC, 0); + /* Unmask all error interrupts */ + ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); + return (0); +} + +struct mvs_dc_cb_args { + bus_addr_t maddr; + int error; +}; + +static void +mvs_dmainit(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + struct mvs_dc_cb_args dcba; + + /* EDMA command request area. */ + if (bus_dma_tag_create(bus_get_dma_tag(dev), 1024, 0, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, MVS_WORKRQ_SIZE, 1, MVS_WORKRQ_SIZE, + 0, NULL, NULL, &ch->dma.workrq_tag)) + goto error; + if (bus_dmamem_alloc(ch->dma.workrq_tag, (void **)&ch->dma.workrq, 0, + &ch->dma.workrq_map)) + goto error; + if (bus_dmamap_load(ch->dma.workrq_tag, ch->dma.workrq_map, ch->dma.workrq, + MVS_WORKRQ_SIZE, mvs_dmasetupc_cb, &dcba, 0) || dcba.error) { + bus_dmamem_free(ch->dma.workrq_tag, ch->dma.workrq, ch->dma.workrq_map); + goto error; + } + ch->dma.workrq_bus = dcba.maddr; + /* EDMA command response area. */ + if (bus_dma_tag_create(bus_get_dma_tag(dev), 256, 0, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, MVS_WORKRP_SIZE, 1, MVS_WORKRP_SIZE, + 0, NULL, NULL, &ch->dma.workrp_tag)) + goto error; + if (bus_dmamem_alloc(ch->dma.workrp_tag, (void **)&ch->dma.workrp, 0, + &ch->dma.workrp_map)) + goto error; + if (bus_dmamap_load(ch->dma.workrp_tag, ch->dma.workrp_map, ch->dma.workrp, + MVS_WORKRP_SIZE, mvs_dmasetupc_cb, &dcba, 0) || dcba.error) { + bus_dmamem_free(ch->dma.workrp_tag, ch->dma.workrp, ch->dma.workrp_map); + goto error; + } + ch->dma.workrp_bus = dcba.maddr; + /* Data area. */ + if (bus_dma_tag_create(bus_get_dma_tag(dev), 2, MVS_EPRD_MAX, + BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, + NULL, NULL, + MVS_SG_ENTRIES * PAGE_SIZE * MVS_MAX_SLOTS, + MVS_SG_ENTRIES, MVS_EPRD_MAX, + 0, busdma_lock_mutex, &ch->mtx, &ch->dma.data_tag)) { + goto error; + } + return; + +error: + device_printf(dev, "WARNING - DMA initialization failed\n"); + mvs_dmafini(dev); +} + +static void +mvs_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct mvs_dc_cb_args *dcba = (struct mvs_dc_cb_args *)xsc; + + if (!(dcba->error = error)) + dcba->maddr = segs[0].ds_addr; +} + +static void +mvs_dmafini(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + + if (ch->dma.data_tag) { + bus_dma_tag_destroy(ch->dma.data_tag); + ch->dma.data_tag = NULL; + } + if (ch->dma.workrp_bus) { + bus_dmamap_unload(ch->dma.workrp_tag, ch->dma.workrp_map); + bus_dmamem_free(ch->dma.workrp_tag, ch->dma.workrp, ch->dma.workrp_map); + ch->dma.workrp_bus = 0; + ch->dma.workrp_map = NULL; + ch->dma.workrp = NULL; + } + if (ch->dma.workrp_tag) { + bus_dma_tag_destroy(ch->dma.workrp_tag); + ch->dma.workrp_tag = NULL; + } + if (ch->dma.workrq_bus) { + bus_dmamap_unload(ch->dma.workrq_tag, ch->dma.workrq_map); + bus_dmamem_free(ch->dma.workrq_tag, ch->dma.workrq, ch->dma.workrq_map); + ch->dma.workrq_bus = 0; + ch->dma.workrq_map = NULL; + ch->dma.workrq = NULL; + } + if (ch->dma.workrq_tag) { + bus_dma_tag_destroy(ch->dma.workrq_tag); + ch->dma.workrq_tag = NULL; + } +} + +static void +mvs_slotsalloc(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + int i; + + /* Alloc and setup command/dma slots */ + bzero(ch->slot, sizeof(ch->slot)); + for (i = 0; i < MVS_MAX_SLOTS; i++) { + struct mvs_slot *slot = &ch->slot[i]; + + slot->dev = dev; + slot->slot = i; + slot->state = MVS_SLOT_EMPTY; + slot->ccb = NULL; + callout_init_mtx(&slot->timeout, &ch->mtx, 0); + + if (bus_dmamap_create(ch->dma.data_tag, 0, &slot->dma.data_map)) + device_printf(ch->dev, "FAILURE - create data_map\n"); + } +} + +static void +mvs_slotsfree(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + int i; + + /* Free all dma slots */ + for (i = 0; i < MVS_MAX_SLOTS; i++) { + struct mvs_slot *slot = &ch->slot[i]; + + callout_drain(&slot->timeout); + if (slot->dma.data_map) { + bus_dmamap_destroy(ch->dma.data_tag, slot->dma.data_map); + slot->dma.data_map = NULL; + } + } +} + +static void +mvs_setup_edma_queues(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + uint64_t work; + + /* Requests queue. */ + work = ch->dma.workrq_bus; + ATA_OUTL(ch->r_mem, EDMA_REQQBAH, work >> 32); + ATA_OUTL(ch->r_mem, EDMA_REQQIP, work & 0xffffffff); + ATA_OUTL(ch->r_mem, EDMA_REQQOP, work & 0xffffffff); + bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, BUS_DMASYNC_PREWRITE); + /* Reponses queue. */ + bzero(ch->dma.workrp, 256); + work = ch->dma.workrp_bus; + ATA_OUTL(ch->r_mem, EDMA_RESQBAH, work >> 32); + ATA_OUTL(ch->r_mem, EDMA_RESQIP, work & 0xffffffff); + ATA_OUTL(ch->r_mem, EDMA_RESQOP, work & 0xffffffff); + bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, BUS_DMASYNC_PREREAD); + ch->out_idx = 0; + ch->in_idx = 0; +} + +static void +mvs_set_edma_mode(device_t dev, enum mvs_edma_mode mode) +{ + struct mvs_channel *ch = device_get_softc(dev); + int timeout; + uint32_t ecfg, fcfg, hc, ltm, unkn; + + if (mode == ch->curr_mode) + return; + /* If we are running, we should stop first. */ + if (ch->curr_mode != MVS_EDMA_OFF) { + ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EDSEDMA); + timeout = 0; + while (ATA_INL(ch->r_mem, EDMA_CMD) & EDMA_CMD_EENEDMA) { + DELAY(1000); + if (timeout++ > 1000) { + device_printf(dev, "stopping EDMA engine failed\n"); + break; + } + }; + } + ch->curr_mode = mode; + ch->fbs_enabled = 0; + ch->fake_busy = 0; + /* Report mode to controller. Needed for correct CCC operation. */ + MVS_EDMA(device_get_parent(dev), dev, mode); + /* Configure new mode. */ + ecfg = EDMA_CFG_RESERVED | EDMA_CFG_RESERVED2 | EDMA_CFG_EHOSTQUEUECACHEEN; + if (ch->pm_present) { + ecfg |= EDMA_CFG_EMASKRXPM; + if (ch->quirks & MVS_Q_GENIIE) { + ecfg |= EDMA_CFG_EEDMAFBS; + ch->fbs_enabled = 1; + } + } + if (ch->quirks & MVS_Q_GENI) + ecfg |= EDMA_CFG_ERDBSZ; + else if (ch->quirks & MVS_Q_GENII) + ecfg |= EDMA_CFG_ERDBSZEXT | EDMA_CFG_EWRBUFFERLEN; + if (ch->quirks & MVS_Q_CT) + ecfg |= EDMA_CFG_ECUTTHROUGHEN; + if (mode != MVS_EDMA_OFF) + ecfg |= EDMA_CFG_EEARLYCOMPLETIONEN; + if (mode == MVS_EDMA_QUEUED) + ecfg |= EDMA_CFG_EQUE; + else if (mode == MVS_EDMA_NCQ) + ecfg |= EDMA_CFG_ESATANATVCMDQUE; + ATA_OUTL(ch->r_mem, EDMA_CFG, ecfg); + mvs_setup_edma_queues(dev); + if (ch->quirks & MVS_Q_GENIIE) { + /* Configure FBS-related registers */ + fcfg = ATA_INL(ch->r_mem, SATA_FISC); + ltm = ATA_INL(ch->r_mem, SATA_LTM); + hc = ATA_INL(ch->r_mem, EDMA_HC); + if (ch->fbs_enabled) { + fcfg |= SATA_FISC_FISDMAACTIVATESYNCRESP; + if (mode == MVS_EDMA_NCQ) { + fcfg &= ~SATA_FISC_FISWAIT4HOSTRDYEN_B0; + hc &= ~EDMA_IE_EDEVERR; + } else { + fcfg |= SATA_FISC_FISWAIT4HOSTRDYEN_B0; + hc |= EDMA_IE_EDEVERR; + } + ltm |= (1 << 8); + } else { + fcfg &= ~SATA_FISC_FISDMAACTIVATESYNCRESP; + fcfg &= ~SATA_FISC_FISWAIT4HOSTRDYEN_B0; + hc |= EDMA_IE_EDEVERR; + ltm &= ~(1 << 8); + } + ATA_OUTL(ch->r_mem, SATA_FISC, fcfg); + ATA_OUTL(ch->r_mem, SATA_LTM, ltm); + ATA_OUTL(ch->r_mem, EDMA_HC, hc); + /* This is some magic, required to handle several DRQs + * with basic DMA. */ + unkn = ATA_INL(ch->r_mem, EDMA_UNKN_RESD); + if (mode == MVS_EDMA_OFF) + unkn |= 1; + else + unkn &= ~1; + ATA_OUTL(ch->r_mem, EDMA_UNKN_RESD, unkn); + } + /* Run EDMA. */ + if (mode != MVS_EDMA_OFF) + ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EENEDMA); +} + +devclass_t mvs_devclass; +devclass_t mvsch_devclass; +static device_method_t mvsch_methods[] = { + DEVMETHOD(device_probe, mvs_ch_probe), + DEVMETHOD(device_attach, mvs_ch_attach), + DEVMETHOD(device_detach, mvs_ch_detach), + DEVMETHOD(device_suspend, mvs_ch_suspend), + DEVMETHOD(device_resume, mvs_ch_resume), + { 0, 0 } +}; +static driver_t mvsch_driver = { + "mvsch", + mvsch_methods, + sizeof(struct mvs_channel) +}; +DRIVER_MODULE(mvsch, mvs, mvsch_driver, mvsch_devclass, 0, 0); +DRIVER_MODULE(mvsch, sata, mvsch_driver, mvsch_devclass, 0, 0); + +static void +mvs_phy_check_events(device_t dev, u_int32_t serr) +{ + struct mvs_channel *ch = device_get_softc(dev); + + if (ch->pm_level == 0) { + u_int32_t status = ATA_INL(ch->r_mem, SATA_SS); + union ccb *ccb; + + if (bootverbose) { + if (((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_ONLINE) && + ((status & SATA_SS_SPD_MASK) != SATA_SS_SPD_NO_SPEED) && + ((status & SATA_SS_IPM_MASK) == SATA_SS_IPM_ACTIVE)) { + device_printf(dev, "CONNECT requested\n"); + } else + device_printf(dev, "DISCONNECT requested\n"); + } + mvs_reset(dev); + if ((ccb = xpt_alloc_ccb_nowait()) == NULL) + return; + if (xpt_create_path(&ccb->ccb_h.path, NULL, + cam_sim_path(ch->sim), + CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + xpt_free_ccb(ccb); + return; + } + xpt_rescan(ccb); + } +} + +static void +mvs_notify_events(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + struct cam_path *dpath; + uint32_t fis; + int d; + + /* Try to read PMP field from SDB FIS. Present only for Gen-IIe. */ + fis = ATA_INL(ch->r_mem, SATA_FISDW0); + if ((fis & 0x80ff) == 0x80a1) + d = (fis & 0x0f00) >> 8; + else + d = ch->pm_present ? 15 : 0; + if (bootverbose) + device_printf(dev, "SNTF %d\n", d); + if (xpt_create_path(&dpath, NULL, + xpt_path_path_id(ch->path), d, 0) == CAM_REQ_CMP) { + xpt_async(AC_SCSI_AEN, dpath, NULL); + xpt_free_path(dpath); + } +} + +static void +mvs_ch_intr_locked(void *data) +{ + struct mvs_intr_arg *arg = (struct mvs_intr_arg *)data; + device_t dev = (device_t)arg->arg; + struct mvs_channel *ch = device_get_softc(dev); + + mtx_lock(&ch->mtx); + mvs_ch_intr(data); + mtx_unlock(&ch->mtx); +} + +static void +mvs_ch_pm(void *arg) +{ + device_t dev = (device_t)arg; + struct mvs_channel *ch = device_get_softc(dev); + uint32_t work; + + if (ch->numrslots != 0) + return; + /* If we are idle - request power state transition. */ + work = ATA_INL(ch->r_mem, SATA_SC); + work &= ~SATA_SC_SPM_MASK; + if (ch->pm_level == 4) + work |= SATA_SC_SPM_PARTIAL; + else + work |= SATA_SC_SPM_SLUMBER; + ATA_OUTL(ch->r_mem, SATA_SC, work); +} + +static void +mvs_ch_pm_wake(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + uint32_t work; + int timeout = 0; + + work = ATA_INL(ch->r_mem, SATA_SS); + if (work & SATA_SS_IPM_ACTIVE) + return; + /* If we are not in active state - request power state transition. */ + work = ATA_INL(ch->r_mem, SATA_SC); + work &= ~SATA_SC_SPM_MASK; + work |= SATA_SC_SPM_ACTIVE; + ATA_OUTL(ch->r_mem, SATA_SC, work); + /* Wait for transition to happen. */ + while ((ATA_INL(ch->r_mem, SATA_SS) & SATA_SS_IPM_ACTIVE) == 0 && + timeout++ < 100) { + DELAY(100); + } +} + +static void +mvs_ch_intr(void *data) +{ + struct mvs_intr_arg *arg = (struct mvs_intr_arg *)data; + device_t dev = (device_t)arg->arg; + struct mvs_channel *ch = device_get_softc(dev); + uint32_t iec, serr = 0, fisic = 0; + enum mvs_err_type et; + int i, ccs, port = -1, selfdis = 0; + int edma = (ch->numtslots != 0 || ch->numdslots != 0); + +//device_printf(dev, "irq cause %02x EDMA %d IEC %08x\n", +// arg->cause, edma, ATA_INL(ch->r_mem, EDMA_IEC)); + /* New item in response queue. */ + if ((arg->cause & 2) && edma) + mvs_crbq_intr(dev); + /* Some error or special event. */ + if (arg->cause & 1) { + iec = ATA_INL(ch->r_mem, EDMA_IEC); +//device_printf(dev, "irq cause %02x EDMA %d IEC %08x\n", +// arg->cause, edma, iec); + if (iec & EDMA_IE_SERRINT) { + serr = ATA_INL(ch->r_mem, SATA_SE); + ATA_OUTL(ch->r_mem, SATA_SE, serr); +//device_printf(dev, "SERR %08x\n", serr); + } + /* EDMA self-disabled due to error. */ + if (iec & EDMA_IE_ESELFDIS) + selfdis = 1; + /* Transport interrupt. */ + if (iec & EDMA_IE_ETRANSINT) { + /* For Gen-I this bit means self-disable. */ + if (ch->quirks & MVS_Q_GENI) + selfdis = 1; + /* For Gen-II this bit means SDB-N. */ + else if (ch->quirks & MVS_Q_GENII) + fisic = SATA_FISC_FISWAIT4HOSTRDYEN_B1; + else /* For Gen-IIe - read FIS interrupt cause. */ + fisic = ATA_INL(ch->r_mem, SATA_FISIC); +//device_printf(dev, "FISIC %08x\n", fisic); + } + if (selfdis) + ch->curr_mode = MVS_EDMA_UNKNOWN; + ATA_OUTL(ch->r_mem, EDMA_IEC, ~iec); + /* Interface errors or Device error. */ + if (iec & (0xfc1e9000 | EDMA_IE_EDEVERR)) { + port = -1; + if (ch->numpslots != 0) { + ccs = 0; + } else { + if (ch->quirks & MVS_Q_GENIIE) + ccs = EDMA_S_EIOID(ATA_INL(ch->r_mem, EDMA_S)); + else + ccs = EDMA_S_EDEVQUETAG(ATA_INL(ch->r_mem, EDMA_S)); + /* Check if error is one-PMP-port-specific, */ + if (ch->fbs_enabled) { + /* Which ports were active. */ + for (i = 0; i < 16; i++) { + if (ch->numrslotspd[i] == 0) + continue; + if (port == -1) + port = i; + else if (port != i) { + port = -2; + break; + } + } + /* If several ports were active and EDMA still enabled - + * other ports are probably unaffected and may continue. + */ + if (port == -2 && !selfdis) { + uint16_t p = ATA_INL(ch->r_mem, SATA_SATAITC) >> 16; + port = ffs(p) - 1; + if (port != (fls(p) - 1)) + port = -2; + } + } + } +//device_printf(dev, "err slot %d port %d\n", ccs, port); + mvs_requeue_frozen(dev); + for (i = 0; i < MVS_MAX_SLOTS; i++) { + /* XXX: reqests in loading state. */ + if (((ch->rslots >> i) & 1) == 0) + continue; + if (port >= 0 && + ch->slot[i].ccb->ccb_h.target_id != port) + continue; + if (iec & EDMA_IE_EDEVERR) { /* Device error. */ + if (port != -2) { + if (ch->numtslots == 0) { + /* Untagged operation. */ + if (i == ccs) + et = MVS_ERR_TFE; + else + et = MVS_ERR_INNOCENT; + } else { + /* Tagged operation. */ + et = MVS_ERR_NCQ; + } + } else { + et = MVS_ERR_TFE; + ch->fatalerr = 1; + } + } else if (iec & 0xfc1e9000) { + if (ch->numtslots == 0 && i != ccs && port != -2) + et = MVS_ERR_INNOCENT; + else + et = MVS_ERR_SATA; + } else + et = MVS_ERR_INVALID; + mvs_end_transaction(&ch->slot[i], et); + } + } + /* Process SDB-N. */ + if (fisic & SATA_FISC_FISWAIT4HOSTRDYEN_B1) + mvs_notify_events(dev); + if (fisic) + ATA_OUTL(ch->r_mem, SATA_FISIC, ~fisic); + /* Process hot-plug. */ + if ((iec & (EDMA_IE_EDEVDIS | EDMA_IE_EDEVCON)) || + (serr & SATA_SE_PHY_CHANGED)) + mvs_phy_check_events(dev, serr); + } + /* Legacy mode device interrupt. */ + if ((arg->cause & 2) && !edma) + mvs_legacy_intr(dev); +} + +static uint8_t +mvs_getstatus(device_t dev, int clear) +{ + struct mvs_channel *ch = device_get_softc(dev); + uint8_t status = ATA_INB(ch->r_mem, clear ? ATA_STATUS : ATA_ALTSTAT); + + if (ch->fake_busy) { + if (status & (ATA_S_BUSY | ATA_S_DRQ | ATA_S_ERROR)) + ch->fake_busy = 0; + else + status |= ATA_S_BUSY; + } + return (status); +} + +static void +mvs_legacy_intr(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + struct mvs_slot *slot = &ch->slot[0]; /* PIO is always in slot 0. */ + union ccb *ccb = slot->ccb; + enum mvs_err_type et = MVS_ERR_NONE; + int port; + u_int length; + uint8_t status, ireason; + + /* Clear interrupt and get status. */ + status = mvs_getstatus(dev, 1); +// device_printf(dev, "Legacy intr status %02x\n", +// status); + if (slot->state < MVS_SLOT_RUNNING) + return; + port = ccb->ccb_h.target_id & 0x0f; + /* Wait a bit for late !BUSY status update. */ + if (status & ATA_S_BUSY) { + DELAY(100); + if ((status = mvs_getstatus(dev, 1)) & ATA_S_BUSY) { + DELAY(1000); + if ((status = mvs_getstatus(dev, 1)) & ATA_S_BUSY) + return; + } + } + /* If we got an error, we are done. */ + if (status & ATA_S_ERROR) { + et = MVS_ERR_TFE; + goto end_finished; + } + if (ccb->ccb_h.func_code == XPT_ATA_IO) { /* ATA PIO */ + ccb->ataio.res.status = status; + /* Are we moving data? */ + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { + /* If data read command - get them. */ + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { + if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { + device_printf(dev, "timeout waiting for read DRQ\n"); + et = MVS_ERR_TIMEOUT; + goto end_finished; + } + ATA_INSW_STRM(ch->r_mem, ATA_DATA, + (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), + ch->transfersize / 2); + } + /* Update how far we've gotten. */ + ch->donecount += ch->transfersize; + /* Do we need more? */ + if (ccb->ataio.dxfer_len > ch->donecount) { + /* Set this transfer size according to HW capabilities */ + ch->transfersize = min(ccb->ataio.dxfer_len - ch->donecount, + ch->curr[ccb->ccb_h.target_id].bytecount); + /* If data write command - put them */ + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { + if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { + device_printf(dev, "timeout waiting for write DRQ\n"); + et = MVS_ERR_TIMEOUT; + goto end_finished; + } + ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, + (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), + ch->transfersize / 2); + return; + } + /* If data read command, return & wait for interrupt */ + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) + return; + } + } + } else if (ch->basic_dma) { /* ATAPI DMA */ + if (status & ATA_S_DWF) + et = MVS_ERR_TFE; + else if (ATA_INL(ch->r_mem, DMA_S) & DMA_S_ERR) + et = MVS_ERR_TFE; + /* Stop basic DMA. */ + ATA_OUTL(ch->r_mem, DMA_C, 0); + goto end_finished; + } else { /* ATAPI PIO */ + length = ATA_INB(ch->r_mem,ATA_CYL_LSB) | (ATA_INB(ch->r_mem,ATA_CYL_MSB) << 8); + ireason = ATA_INB(ch->r_mem,ATA_IREASON); +//device_printf(dev, "status %02x, ireason %02x, length %d\n", status, ireason, length); + switch ((ireason & (ATA_I_CMD | ATA_I_IN)) | + (status & ATA_S_DRQ)) { + + case ATAPI_P_CMDOUT: +device_printf(dev, "ATAPI CMDOUT\n"); + /* Return wait for interrupt */ + return; + + case ATAPI_P_WRITE: +//device_printf(dev, "ATAPI WRITE\n"); + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { + device_printf(dev, "trying to write on read buffer\n"); + et = MVS_ERR_TFE; + goto end_finished; + break; + } + ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, + (uint16_t *)(ccb->csio.data_ptr + ch->donecount), + length / 2); + ch->donecount += length; + /* Set next transfer size according to HW capabilities */ + ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount, + ch->curr[ccb->ccb_h.target_id].bytecount); + /* Return wait for interrupt */ + return; + + case ATAPI_P_READ: +//device_printf(dev, "ATAPI READ\n"); + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { + device_printf(dev, "trying to read on write buffer\n"); + et = MVS_ERR_TFE; + goto end_finished; + } + ATA_INSW_STRM(ch->r_mem, ATA_DATA, + (uint16_t *)(ccb->csio.data_ptr + ch->donecount), + length / 2); + ch->donecount += length; + /* Set next transfer size according to HW capabilities */ + ch->transfersize = min(ccb->csio.dxfer_len - ch->donecount, + ch->curr[ccb->ccb_h.target_id].bytecount); + /* Return wait for interrupt */ + return; + + case ATAPI_P_DONEDRQ: +device_printf(dev, "ATAPI DONEDRQ\n"); + device_printf(dev, + "WARNING - DONEDRQ non conformant device\n"); + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { + ATA_INSW_STRM(ch->r_mem, ATA_DATA, + (uint16_t *)(ccb->csio.data_ptr + ch->donecount), + length / 2); + ch->donecount += length; + } + else if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { + ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, + (uint16_t *)(ccb->csio.data_ptr + ch->donecount), + length / 2); + ch->donecount += length; + } + else + et = MVS_ERR_TFE; + /* FALLTHROUGH */ + + case ATAPI_P_ABORT: + case ATAPI_P_DONE: +//device_printf(dev, "ATAPI ABORT/DONE\n"); + if (status & (ATA_S_ERROR | ATA_S_DWF)) + et = MVS_ERR_TFE; + goto end_finished; + + default: + device_printf(dev, "unknown transfer phase (status %02x, ireason %02x)\n", + status, ireason); + et = MVS_ERR_TFE; + } + } + +end_finished: + mvs_end_transaction(slot, et); +} + +static void +mvs_crbq_intr(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + struct mvs_crpb *crpb; + union ccb *ccb; + int in_idx, cin_idx, slot; + uint16_t flags; + + in_idx = (ATA_INL(ch->r_mem, EDMA_RESQIP) & EDMA_RESQP_ERPQP_MASK) >> + EDMA_RESQP_ERPQP_SHIFT; + bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, + BUS_DMASYNC_POSTREAD); + cin_idx = ch->in_idx; + ch->in_idx = in_idx; + while (in_idx != cin_idx) { + crpb = (struct mvs_crpb *) + (ch->dma.workrp + MVS_CRPB_OFFSET + (MVS_CRPB_SIZE * cin_idx)); + slot = le16toh(crpb->id) & MVS_CRPB_TAG_MASK; + flags = le16toh(crpb->rspflg); +//device_printf(dev, "CRPB %d %d %04x\n", cin_idx, slot, flags); + /* + * Handle only successfull completions here. + * Errors will be handled by main intr handler. + */ + if (ch->numtslots != 0 || (flags & EDMA_IE_EDEVERR) == 0) { +if ((flags >> 8) & ATA_S_ERROR) +device_printf(dev, "ERROR STATUS CRPB %d %d %04x\n", cin_idx, slot, flags); + if (ch->slot[slot].state >= MVS_SLOT_RUNNING) { + ccb = ch->slot[slot].ccb; + ccb->ataio.res.status = (flags & MVS_CRPB_ATASTS_MASK) >> + MVS_CRPB_ATASTS_SHIFT; + mvs_end_transaction(&ch->slot[slot], MVS_ERR_NONE); + } else +device_printf(dev, "EMPTY CRPB %d (->%d) %d %04x\n", cin_idx, in_idx, slot, flags); + } else +device_printf(dev, "ERROR FLAGS CRPB %d %d %04x\n", cin_idx, slot, flags); + + cin_idx = (cin_idx + 1) & (MVS_MAX_SLOTS - 1); + } + bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, + BUS_DMASYNC_PREREAD); + if (cin_idx == ch->in_idx) { + ATA_OUTL(ch->r_mem, EDMA_RESQOP, + ch->dma.workrp_bus | (cin_idx << EDMA_RESQP_ERPQP_SHIFT)); + } +} + +/* Must be called with channel locked. */ +static int +mvs_check_collision(device_t dev, union ccb *ccb) +{ + struct mvs_channel *ch = device_get_softc(dev); + + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + /* NCQ DMA */ + if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { + /* Can't mix NCQ and non-NCQ DMA commands. */ + if (ch->numdslots != 0) + return (1); + /* Can't mix NCQ and PIO commands. */ + if (ch->numpslots != 0) + return (1); + /* If we have no FBS */ + if (!ch->fbs_enabled) { + /* Tagged command while tagged to other target is active. */ + if (ch->numtslots != 0 && + ch->taggedtarget != ccb->ccb_h.target_id) + return (1); + } + /* Non-NCQ DMA */ + } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { + /* Can't mix non-NCQ DMA and NCQ commands. */ + if (ch->numtslots != 0) + return (1); + /* Can't mix non-NCQ DMA and PIO commands. */ + if (ch->numpslots != 0) + return (1); + /* PIO */ + } else { + /* Can't mix PIO with anything. */ + if (ch->numrslots != 0) + return (1); + } + if (ccb->ataio.cmd.flags & (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) { + /* Atomic command while anything active. */ + if (ch->numrslots != 0) + return (1); + } + } else { /* ATAPI */ + /* ATAPI goes without EDMA, so can't mix it with anything. */ + if (ch->numrslots != 0) + return (1); + } + /* We have some atomic command running. */ + if (ch->aslots != 0) + return (1); + return (0); +} + +static void +mvs_tfd_read(device_t dev, union ccb *ccb) +{ + struct mvs_channel *ch = device_get_softc(dev); + struct ata_res *res = &ccb->ataio.res; + + res->status = ATA_INB(ch->r_mem, ATA_ALTSTAT); + res->error = ATA_INB(ch->r_mem, ATA_ERROR); + res->device = ATA_INB(ch->r_mem, ATA_DRIVE); + ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_HOB); + res->sector_count_exp = ATA_INB(ch->r_mem, ATA_COUNT); + res->lba_low_exp = ATA_INB(ch->r_mem, ATA_SECTOR); + res->lba_mid_exp = ATA_INB(ch->r_mem, ATA_CYL_LSB); + res->lba_high_exp = ATA_INB(ch->r_mem, ATA_CYL_MSB); + ATA_OUTB(ch->r_mem, ATA_CONTROL, 0); + res->sector_count = ATA_INB(ch->r_mem, ATA_COUNT); + res->lba_low = ATA_INB(ch->r_mem, ATA_SECTOR); + res->lba_mid = ATA_INB(ch->r_mem, ATA_CYL_LSB); + res->lba_high = ATA_INB(ch->r_mem, ATA_CYL_MSB); +} + +static void +mvs_tfd_write(device_t dev, union ccb *ccb) +{ + struct mvs_channel *ch = device_get_softc(dev); + struct ata_cmd *cmd = &ccb->ataio.cmd; + + ATA_OUTB(ch->r_mem, ATA_DRIVE, cmd->device); + ATA_OUTB(ch->r_mem, ATA_CONTROL, cmd->control); + ATA_OUTB(ch->r_mem, ATA_FEATURE, cmd->features_exp); + ATA_OUTB(ch->r_mem, ATA_FEATURE, cmd->features); + ATA_OUTB(ch->r_mem, ATA_COUNT, cmd->sector_count_exp); + ATA_OUTB(ch->r_mem, ATA_COUNT, cmd->sector_count); + ATA_OUTB(ch->r_mem, ATA_SECTOR, cmd->lba_low_exp); + ATA_OUTB(ch->r_mem, ATA_SECTOR, cmd->lba_low); + ATA_OUTB(ch->r_mem, ATA_CYL_LSB, cmd->lba_mid_exp); + ATA_OUTB(ch->r_mem, ATA_CYL_LSB, cmd->lba_mid); + ATA_OUTB(ch->r_mem, ATA_CYL_MSB, cmd->lba_high_exp); + ATA_OUTB(ch->r_mem, ATA_CYL_MSB, cmd->lba_high); + ATA_OUTB(ch->r_mem, ATA_COMMAND, cmd->command); +} + + +/* Must be called with channel locked. */ +static void +mvs_begin_transaction(device_t dev, union ccb *ccb) +{ + struct mvs_channel *ch = device_get_softc(dev); + struct mvs_slot *slot; + int slotn, tag; + + if (ch->pm_level > 0) + mvs_ch_pm_wake(dev); + /* Softreset is a special case. */ + if (ccb->ccb_h.func_code == XPT_ATA_IO && + (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL)) { + mvs_softreset(dev, ccb); + return; + } + /* Choose empty slot. */ + slotn = ffs(~ch->oslots) - 1; + if ((ccb->ccb_h.func_code == XPT_ATA_IO) && + (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) { + if (ch->quirks & MVS_Q_GENIIE) + tag = ffs(~ch->otagspd[ccb->ccb_h.target_id]) - 1; + else + tag = slotn; + } else + tag = 0; + /* Occupy chosen slot. */ + slot = &ch->slot[slotn]; + slot->ccb = ccb; + slot->tag = tag; + /* Stop PM timer. */ + if (ch->numrslots == 0 && ch->pm_level > 3) + callout_stop(&ch->pm_timer); + /* Update channel stats. */ + ch->oslots |= (1 << slot->slot); + ch->numrslots++; + ch->numrslotspd[ccb->ccb_h.target_id]++; + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { + ch->otagspd[ccb->ccb_h.target_id] |= (1 << slot->tag); + ch->numtslots++; + ch->numtslotspd[ccb->ccb_h.target_id]++; + ch->taggedtarget = ccb->ccb_h.target_id; + mvs_set_edma_mode(dev, MVS_EDMA_NCQ); + } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { + ch->numdslots++; + mvs_set_edma_mode(dev, MVS_EDMA_ON); + } else { + ch->numpslots++; + mvs_set_edma_mode(dev, MVS_EDMA_OFF); + } + if (ccb->ataio.cmd.flags & + (CAM_ATAIO_CONTROL | CAM_ATAIO_NEEDRESULT)) { + ch->aslots |= (1 << slot->slot); + } + } else { + uint8_t *cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ? + ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes; + ch->numpslots++; + /* Use ATAPI DMA only for commands without under-/overruns. */ + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE && + ch->curr[ccb->ccb_h.target_id].mode >= ATA_DMA && + (ch->quirks & MVS_Q_SOC) == 0 && + (cdb[0] == 0x08 || + cdb[0] == 0x0a || + cdb[0] == 0x28 || + cdb[0] == 0x2a || + cdb[0] == 0x88 || + cdb[0] == 0x8a || + cdb[0] == 0xa8 || + cdb[0] == 0xaa || + cdb[0] == 0xbe)) { + ch->basic_dma = 1; + } + mvs_set_edma_mode(dev, MVS_EDMA_OFF); + } + if (ch->numpslots == 0 || ch->basic_dma) { + void *buf; + bus_size_t size; + + slot->state = MVS_SLOT_LOADING; + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + buf = ccb->ataio.data_ptr; + size = ccb->ataio.dxfer_len; + } else { + buf = ccb->csio.data_ptr; + size = ccb->csio.dxfer_len; + } + bus_dmamap_load(ch->dma.data_tag, slot->dma.data_map, + buf, size, mvs_dmasetprd, slot, 0); + } else + mvs_legacy_execute_transaction(slot); +} + +/* Locked by busdma engine. */ +static void +mvs_dmasetprd(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct mvs_slot *slot = arg; + struct mvs_channel *ch = device_get_softc(slot->dev); + struct mvs_eprd *eprd; + int i; + + if (error) { + device_printf(slot->dev, "DMA load error\n"); + mvs_end_transaction(slot, MVS_ERR_INVALID); + return; + } + KASSERT(nsegs <= MVS_SG_ENTRIES, ("too many DMA segment entries\n")); + /* If there is only one segment - no need to use S/G table on Gen-IIe. */ + if (nsegs == 1 && ch->basic_dma == 0 && (ch->quirks & MVS_Q_GENIIE)) { + slot->dma.addr = segs[0].ds_addr; + slot->dma.len = segs[0].ds_len; + } else { + slot->dma.addr = 0; + /* Get a piece of the workspace for this EPRD */ + eprd = (struct mvs_eprd *) + (ch->dma.workrq + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot)); + /* Fill S/G table */ + for (i = 0; i < nsegs; i++) { + eprd[i].prdbal = htole32(segs[i].ds_addr); + eprd[i].bytecount = htole32(segs[i].ds_len & MVS_EPRD_MASK); + eprd[i].prdbah = htole32((segs[i].ds_addr >> 16) >> 16); + } + eprd[i - 1].bytecount |= htole32(MVS_EPRD_EOF); + } + bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, + ((slot->ccb->ccb_h.flags & CAM_DIR_IN) ? + BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE)); + if (ch->basic_dma) + mvs_legacy_execute_transaction(slot); + else + mvs_execute_transaction(slot); +} + +static void +mvs_legacy_execute_transaction(struct mvs_slot *slot) +{ + device_t dev = slot->dev; + struct mvs_channel *ch = device_get_softc(dev); + bus_addr_t eprd; + union ccb *ccb = slot->ccb; + int port = ccb->ccb_h.target_id & 0x0f; + int timeout; + + slot->state = MVS_SLOT_RUNNING; + ch->rslots |= (1 << slot->slot); + ATA_OUTB(ch->r_mem, SATA_SATAICTL, port << SATA_SATAICTL_PMPTX_SHIFT); + if (ccb->ccb_h.func_code == XPT_ATA_IO) { +// device_printf(dev, "%d Legacy command %02x size %d\n", +// port, ccb->ataio.cmd.command, ccb->ataio.dxfer_len); + mvs_tfd_write(dev, ccb); + /* Device reset doesn't interrupt. */ + if (ccb->ataio.cmd.command == ATA_DEVICE_RESET) { + int timeout = 1000000; + do { + DELAY(10); + ccb->ataio.res.status = ATA_INB(ch->r_mem, ATA_STATUS); + } while (ccb->ataio.res.status & ATA_S_BUSY && timeout--); + mvs_legacy_intr(dev); + return; + } + ch->donecount = 0; + ch->transfersize = min(ccb->ataio.dxfer_len, + ch->curr[port].bytecount); + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) + ch->fake_busy = 1; + /* If data write command - output the data */ + if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { + if (mvs_wait(dev, ATA_S_DRQ, ATA_S_BUSY, 1000) < 0) { + device_printf(dev, "timeout waiting for write DRQ\n"); + mvs_end_transaction(slot, MVS_ERR_TIMEOUT); + return; + } + ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, + (uint16_t *)(ccb->ataio.data_ptr + ch->donecount), + ch->transfersize / 2); + } + } else { +// device_printf(dev, "%d ATAPI command %02x size %d dma %d\n", +// port, ccb->csio.cdb_io.cdb_bytes[0], ccb->csio.dxfer_len, +// ch->basic_dma); + ch->donecount = 0; + ch->transfersize = min(ccb->csio.dxfer_len, + ch->curr[port].bytecount); + /* Write ATA PACKET command. */ + if (ch->basic_dma) { + ATA_OUTB(ch->r_mem, ATA_FEATURE, ATA_F_DMA); + ATA_OUTB(ch->r_mem, ATA_CYL_LSB, 0); + ATA_OUTB(ch->r_mem, ATA_CYL_MSB, 0); + } else { + ATA_OUTB(ch->r_mem, ATA_FEATURE, 0); + ATA_OUTB(ch->r_mem, ATA_CYL_LSB, ch->transfersize); + ATA_OUTB(ch->r_mem, ATA_CYL_MSB, ch->transfersize >> 8); + } + ATA_OUTB(ch->r_mem, ATA_COMMAND, ATA_PACKET_CMD); + ch->fake_busy = 1; + /* Wait for ready to write ATAPI command block */ + if (mvs_wait(dev, 0, ATA_S_BUSY, 1000) < 0) { + device_printf(dev, "timeout waiting for ATAPI !BUSY\n"); + mvs_end_transaction(slot, MVS_ERR_TIMEOUT); + return; + } + timeout = 5000; + while (timeout--) { + int reason = ATA_INB(ch->r_mem, ATA_IREASON); + int status = ATA_INB(ch->r_mem, ATA_STATUS); + + if (((reason & (ATA_I_CMD | ATA_I_IN)) | + (status & (ATA_S_DRQ | ATA_S_BUSY))) == ATAPI_P_CMDOUT) + break; + DELAY(20); + } + if (timeout <= 0) { + device_printf(dev, "timeout waiting for ATAPI command ready\n"); + mvs_end_transaction(slot, MVS_ERR_TIMEOUT); + return; + } + /* Write ATAPI command. */ + ATA_OUTSW_STRM(ch->r_mem, ATA_DATA, + (uint16_t *)((ccb->ccb_h.flags & CAM_CDB_POINTER) ? + ccb->csio.cdb_io.cdb_ptr : ccb->csio.cdb_io.cdb_bytes), + ch->curr[port].atapi / 2); + DELAY(10); + if (ch->basic_dma) { + /* Start basic DMA. */ + eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET + + (MVS_EPRD_SIZE * slot->slot); + ATA_OUTL(ch->r_mem, DMA_DTLBA, eprd); + ATA_OUTL(ch->r_mem, DMA_DTHBA, (eprd >> 16) >> 16); + ATA_OUTL(ch->r_mem, DMA_C, DMA_C_START | + (((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) ? + DMA_C_READ : 0)); + } else if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) + ch->fake_busy = 1; + } + /* Start command execution timeout */ + callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000, + (timeout_t*)mvs_timeout, slot); +} + +/* Must be called with channel locked. */ +static void +mvs_execute_transaction(struct mvs_slot *slot) +{ + device_t dev = slot->dev; + struct mvs_channel *ch = device_get_softc(dev); + bus_addr_t eprd; + struct mvs_crqb *crqb; + struct mvs_crqb_gen2e *crqb2e; + union ccb *ccb = slot->ccb; + int port = ccb->ccb_h.target_id & 0x0f; + int i; + +// device_printf(dev, "%d EDMA command %02x size %d slot %d tag %d\n", +// port, ccb->ataio.cmd.command, ccb->ataio.dxfer_len, slot->slot, slot->tag); + /* Get address of the prepared EPRD */ + eprd = ch->dma.workrq_bus + MVS_EPRD_OFFSET + (MVS_EPRD_SIZE * slot->slot); + /* Prepare CRQB. Gen IIe uses different CRQB format. */ + if (ch->quirks & MVS_Q_GENIIE) { + crqb2e = (struct mvs_crqb_gen2e *) + (ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); + crqb2e->ctrlflg = htole32( + ((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB2E_READ : 0) | + (slot->tag << MVS_CRQB2E_DTAG_SHIFT) | + (port << MVS_CRQB2E_PMP_SHIFT) | + (slot->slot << MVS_CRQB2E_HTAG_SHIFT)); + /* If there is only one segment - no need to use S/G table. */ + if (slot->dma.addr != 0) { + eprd = slot->dma.addr; + crqb2e->ctrlflg |= htole32(MVS_CRQB2E_CPRD); + crqb2e->drbc = slot->dma.len; + } + crqb2e->cprdbl = htole32(eprd); + crqb2e->cprdbh = htole32((eprd >> 16) >> 16); + crqb2e->cmd[0] = 0; + crqb2e->cmd[1] = 0; + crqb2e->cmd[2] = ccb->ataio.cmd.command; + crqb2e->cmd[3] = ccb->ataio.cmd.features; + crqb2e->cmd[4] = ccb->ataio.cmd.lba_low; + crqb2e->cmd[5] = ccb->ataio.cmd.lba_mid; + crqb2e->cmd[6] = ccb->ataio.cmd.lba_high; + crqb2e->cmd[7] = ccb->ataio.cmd.device; + crqb2e->cmd[8] = ccb->ataio.cmd.lba_low_exp; + crqb2e->cmd[9] = ccb->ataio.cmd.lba_mid_exp; + crqb2e->cmd[10] = ccb->ataio.cmd.lba_high_exp; + crqb2e->cmd[11] = ccb->ataio.cmd.features_exp; + if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { + crqb2e->cmd[12] = slot->tag << 3; + crqb2e->cmd[13] = 0; + } else { + crqb2e->cmd[12] = ccb->ataio.cmd.sector_count; + crqb2e->cmd[13] = ccb->ataio.cmd.sector_count_exp; + } + crqb2e->cmd[14] = 0; + crqb2e->cmd[15] = 0; + } else { + crqb = (struct mvs_crqb *) + (ch->dma.workrq + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); + crqb->cprdbl = htole32(eprd); + crqb->cprdbh = htole32((eprd >> 16) >> 16); + crqb->ctrlflg = htole16( + ((ccb->ccb_h.flags & CAM_DIR_IN) ? MVS_CRQB_READ : 0) | + (slot->slot << MVS_CRQB_TAG_SHIFT) | + (port << MVS_CRQB_PMP_SHIFT)); + i = 0; + /* + * Controller can handle only 11 of 12 ATA registers, + * so we have to choose which one to skip. + */ + if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { + crqb->cmd[i++] = ccb->ataio.cmd.features_exp; + crqb->cmd[i++] = 0x11; + } + crqb->cmd[i++] = ccb->ataio.cmd.features; + crqb->cmd[i++] = 0x11; + if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { + crqb->cmd[i++] = slot->tag << 3; + crqb->cmd[i++] = 0x12; + } else { + crqb->cmd[i++] = ccb->ataio.cmd.sector_count_exp; + crqb->cmd[i++] = 0x12; + crqb->cmd[i++] = ccb->ataio.cmd.sector_count; + crqb->cmd[i++] = 0x12; + } + crqb->cmd[i++] = ccb->ataio.cmd.lba_low_exp; + crqb->cmd[i++] = 0x13; + crqb->cmd[i++] = ccb->ataio.cmd.lba_low; + crqb->cmd[i++] = 0x13; + crqb->cmd[i++] = ccb->ataio.cmd.lba_mid_exp; + crqb->cmd[i++] = 0x14; + crqb->cmd[i++] = ccb->ataio.cmd.lba_mid; + crqb->cmd[i++] = 0x14; + crqb->cmd[i++] = ccb->ataio.cmd.lba_high_exp; + crqb->cmd[i++] = 0x15; + crqb->cmd[i++] = ccb->ataio.cmd.lba_high; + crqb->cmd[i++] = 0x15; + crqb->cmd[i++] = ccb->ataio.cmd.device; + crqb->cmd[i++] = 0x16; + crqb->cmd[i++] = ccb->ataio.cmd.command; + crqb->cmd[i++] = 0x97; + } + bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, + BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(ch->dma.workrp_tag, ch->dma.workrp_map, + BUS_DMASYNC_PREREAD); + slot->state = MVS_SLOT_RUNNING; + ch->rslots |= (1 << slot->slot); + /* Issue command to the controller. */ + ch->out_idx = (ch->out_idx + 1) & (MVS_MAX_SLOTS - 1); + ATA_OUTL(ch->r_mem, EDMA_REQQIP, + ch->dma.workrq_bus + MVS_CRQB_OFFSET + (MVS_CRQB_SIZE * ch->out_idx)); + /* Start command execution timeout */ + callout_reset(&slot->timeout, (int)ccb->ccb_h.timeout * hz / 1000, + (timeout_t*)mvs_timeout, slot); + return; +} + +/* Must be called with channel locked. */ +static void +mvs_process_timeout(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + int i; + + mtx_assert(&ch->mtx, MA_OWNED); + /* Handle the rest of commands. */ + for (i = 0; i < MVS_MAX_SLOTS; i++) { + /* Do we have a running request on slot? */ + if (ch->slot[i].state < MVS_SLOT_RUNNING) + continue; + mvs_end_transaction(&ch->slot[i], MVS_ERR_TIMEOUT); + } +} + +/* Must be called with channel locked. */ +static void +mvs_rearm_timeout(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + int i; + + mtx_assert(&ch->mtx, MA_OWNED); + for (i = 0; i < MVS_MAX_SLOTS; i++) { + struct mvs_slot *slot = &ch->slot[i]; + + /* Do we have a running request on slot? */ + if (slot->state < MVS_SLOT_RUNNING) + continue; + if ((ch->toslots & (1 << i)) == 0) + continue; + callout_reset(&slot->timeout, + (int)slot->ccb->ccb_h.timeout * hz / 2000, + (timeout_t*)mvs_timeout, slot); + } +} + +/* Locked by callout mechanism. */ +static void +mvs_timeout(struct mvs_slot *slot) +{ + device_t dev = slot->dev; + struct mvs_channel *ch = device_get_softc(dev); + + /* Check for stale timeout. */ + if (slot->state < MVS_SLOT_RUNNING) + return; + device_printf(dev, "Timeout on slot %d\n", slot->slot); + device_printf(dev, "iec %08x sstat %08x serr %08x edma_s %08x " + "dma_c %08x dma_s %08x rs %08x status %02x\n", + ATA_INL(ch->r_mem, EDMA_IEC), + ATA_INL(ch->r_mem, SATA_SS), ATA_INL(ch->r_mem, SATA_SE), + ATA_INL(ch->r_mem, EDMA_S), ATA_INL(ch->r_mem, DMA_C), + ATA_INL(ch->r_mem, DMA_S), ch->rslots, + ATA_INB(ch->r_mem, ATA_ALTSTAT)); + /* Handle frozen command. */ + mvs_requeue_frozen(dev); + /* We wait for other commands timeout and pray. */ + if (ch->toslots == 0) + xpt_freeze_simq(ch->sim, 1); + ch->toslots |= (1 << slot->slot); + if ((ch->rslots & ~ch->toslots) == 0) + mvs_process_timeout(dev); + else + device_printf(dev, " ... waiting for slots %08x\n", + ch->rslots & ~ch->toslots); +} + +/* Must be called with channel locked. */ +static void +mvs_end_transaction(struct mvs_slot *slot, enum mvs_err_type et) +{ + device_t dev = slot->dev; + struct mvs_channel *ch = device_get_softc(dev); + union ccb *ccb = slot->ccb; + +//device_printf(dev, "cmd done status %d\n", et); + bus_dmamap_sync(ch->dma.workrq_tag, ch->dma.workrq_map, + BUS_DMASYNC_POSTWRITE); + /* Read result registers to the result struct + * May be incorrect if several commands finished same time, + * so read only when sure or have to. + */ + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + struct ata_res *res = &ccb->ataio.res; + + if ((et == MVS_ERR_TFE) || + (ccb->ataio.cmd.flags & CAM_ATAIO_NEEDRESULT)) { + mvs_tfd_read(dev, ccb); + } else + bzero(res, sizeof(*res)); + } + if (ch->numpslots == 0 || ch->basic_dma) { + if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { + bus_dmamap_sync(ch->dma.data_tag, slot->dma.data_map, + (ccb->ccb_h.flags & CAM_DIR_IN) ? + BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ch->dma.data_tag, slot->dma.data_map); + } + } + if (et != MVS_ERR_NONE) + ch->eslots |= (1 << slot->slot); + /* In case of error, freeze device for proper recovery. */ + if ((et != MVS_ERR_NONE) && (!ch->readlog) && + !(ccb->ccb_h.status & CAM_DEV_QFRZN)) { + xpt_freeze_devq(ccb->ccb_h.path, 1); + ccb->ccb_h.status |= CAM_DEV_QFRZN; + } + /* Set proper result status. */ + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + switch (et) { + case MVS_ERR_NONE: + ccb->ccb_h.status |= CAM_REQ_CMP; + if (ccb->ccb_h.func_code == XPT_SCSI_IO) + ccb->csio.scsi_status = SCSI_STATUS_OK; + break; + case MVS_ERR_INVALID: + ch->fatalerr = 1; + ccb->ccb_h.status |= CAM_REQ_INVALID; + break; + case MVS_ERR_INNOCENT: + ccb->ccb_h.status |= CAM_REQUEUE_REQ; + break; + case MVS_ERR_TFE: + case MVS_ERR_NCQ: + if (ccb->ccb_h.func_code == XPT_SCSI_IO) { + ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; + ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + } else { + ccb->ccb_h.status |= CAM_ATA_STATUS_ERROR; + } + break; + case MVS_ERR_SATA: + ch->fatalerr = 1; + if (!ch->readlog) { + xpt_freeze_simq(ch->sim, 1); + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_RELEASE_SIMQ; + } + ccb->ccb_h.status |= CAM_UNCOR_PARITY; + break; + case MVS_ERR_TIMEOUT: + if (!ch->readlog) { + xpt_freeze_simq(ch->sim, 1); + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + ccb->ccb_h.status |= CAM_RELEASE_SIMQ; + } + ccb->ccb_h.status |= CAM_CMD_TIMEOUT; + break; + default: + ch->fatalerr = 1; + ccb->ccb_h.status |= CAM_REQ_CMP_ERR; + } + /* Free slot. */ + ch->oslots &= ~(1 << slot->slot); + ch->rslots &= ~(1 << slot->slot); + ch->aslots &= ~(1 << slot->slot); + if (et != MVS_ERR_TIMEOUT) { + if (ch->toslots == (1 << slot->slot)) + xpt_release_simq(ch->sim, TRUE); + ch->toslots &= ~(1 << slot->slot); + } + slot->state = MVS_SLOT_EMPTY; + slot->ccb = NULL; + /* Update channel stats. */ + ch->numrslots--; + ch->numrslotspd[ccb->ccb_h.target_id]--; + if (ccb->ccb_h.func_code == XPT_ATA_IO) { + if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) { + ch->otagspd[ccb->ccb_h.target_id] &= ~(1 << slot->tag); + ch->numtslots--; + ch->numtslotspd[ccb->ccb_h.target_id]--; + } else if (ccb->ataio.cmd.flags & CAM_ATAIO_DMA) { + ch->numdslots--; + } else { + ch->numpslots--; + } + } else { + ch->numpslots--; + ch->basic_dma = 0; + } + /* If it was our READ LOG command - process it. */ + if (ch->readlog) { + mvs_process_read_log(dev, ccb); + /* If it was NCQ command error, put result on hold. */ + } else if (et == MVS_ERR_NCQ) { + ch->hold[slot->slot] = ccb; + ch->holdtag[slot->slot] = slot->tag; + ch->numhslots++; + } else + xpt_done(ccb); + /* Unfreeze frozen command. */ + if (ch->frozen && !mvs_check_collision(dev, ch->frozen)) { + union ccb *fccb = ch->frozen; + ch->frozen = NULL; + mvs_begin_transaction(dev, fccb); + xpt_release_simq(ch->sim, TRUE); + } + /* If we have no other active commands, ... */ + if (ch->rslots == 0) { + /* if there was fatal error - reset port. */ + if (ch->toslots != 0 || ch->fatalerr) { + mvs_reset(dev); + } else { + /* if we have slots in error, we can reinit port. */ + if (ch->eslots != 0) { + mvs_set_edma_mode(dev, MVS_EDMA_OFF); + ch->eslots = 0; + } + /* if there commands on hold, we can do READ LOG. */ + if (!ch->readlog && ch->numhslots) + mvs_issue_read_log(dev); + } + /* If all the rest of commands are in timeout - give them chance. */ + } else if ((ch->rslots & ~ch->toslots) == 0 && + et != MVS_ERR_TIMEOUT) + mvs_rearm_timeout(dev); + /* Start PM timer. */ + if (ch->numrslots == 0 && ch->pm_level > 3 && + (ch->curr[ch->pm_present ? 15 : 0].caps & CTS_SATA_CAPS_D_PMREQ)) { + callout_schedule(&ch->pm_timer, + (ch->pm_level == 4) ? hz / 1000 : hz / 8); + } +} + +static void +mvs_issue_read_log(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + union ccb *ccb; + struct ccb_ataio *ataio; + int i; + + ch->readlog = 1; + /* Find some holden command. */ + for (i = 0; i < MVS_MAX_SLOTS; i++) { + if (ch->hold[i]) + break; + } + ccb = xpt_alloc_ccb_nowait(); + if (ccb == NULL) { + device_printf(dev, "Unable allocate READ LOG command"); + return; /* XXX */ + } + ccb->ccb_h = ch->hold[i]->ccb_h; /* Reuse old header. */ + ccb->ccb_h.func_code = XPT_ATA_IO; + ccb->ccb_h.flags = CAM_DIR_IN; + ccb->ccb_h.timeout = 1000; /* 1s should be enough. */ + ataio = &ccb->ataio; + ataio->data_ptr = malloc(512, M_MVS, M_NOWAIT); + if (ataio->data_ptr == NULL) { + device_printf(dev, "Unable allocate memory for READ LOG command"); + return; /* XXX */ + } + ataio->dxfer_len = 512; + bzero(&ataio->cmd, sizeof(ataio->cmd)); + ataio->cmd.flags = CAM_ATAIO_48BIT; + ataio->cmd.command = 0x2F; /* READ LOG EXT */ + ataio->cmd.sector_count = 1; + ataio->cmd.sector_count_exp = 0; + ataio->cmd.lba_low = 0x10; + ataio->cmd.lba_mid = 0; + ataio->cmd.lba_mid_exp = 0; + /* Freeze SIM while doing READ LOG EXT. */ + xpt_freeze_simq(ch->sim, 1); + mvs_begin_transaction(dev, ccb); +} + +static void +mvs_process_read_log(device_t dev, union ccb *ccb) +{ + struct mvs_channel *ch = device_get_softc(dev); + uint8_t *data; + struct ata_res *res; + int i; + + ch->readlog = 0; + + data = ccb->ataio.data_ptr; + if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP && + (data[0] & 0x80) == 0) { + for (i = 0; i < MVS_MAX_SLOTS; i++) { + if (!ch->hold[i]) + continue; + if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id) + continue; + if ((data[0] & 0x1F) == ch->holdtag[i]) { + res = &ch->hold[i]->ataio.res; + res->status = data[2]; + res->error = data[3]; + res->lba_low = data[4]; + res->lba_mid = data[5]; + res->lba_high = data[6]; + res->device = data[7]; + res->lba_low_exp = data[8]; + res->lba_mid_exp = data[9]; + res->lba_high_exp = data[10]; + res->sector_count = data[12]; + res->sector_count_exp = data[13]; + } else { + ch->hold[i]->ccb_h.status &= ~CAM_STATUS_MASK; + ch->hold[i]->ccb_h.status |= CAM_REQUEUE_REQ; + } + xpt_done(ch->hold[i]); + ch->hold[i] = NULL; + ch->numhslots--; + } + } else { + if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) + device_printf(dev, "Error while READ LOG EXT\n"); + else if ((data[0] & 0x80) == 0) { + device_printf(dev, "Non-queued command error in READ LOG EXT\n"); + } + for (i = 0; i < MVS_MAX_SLOTS; i++) { + if (!ch->hold[i]) + continue; + if (ch->hold[i]->ccb_h.target_id != ccb->ccb_h.target_id) + continue; + xpt_done(ch->hold[i]); + ch->hold[i] = NULL; + ch->numhslots--; + } + } + free(ccb->ataio.data_ptr, M_MVS); + xpt_free_ccb(ccb); + xpt_release_simq(ch->sim, TRUE); +} + +static int +mvs_wait(device_t dev, u_int s, u_int c, int t) +{ + int timeout = 0; + uint8_t st; + + while (((st = mvs_getstatus(dev, 0)) & (s | c)) != s) { + DELAY(1000); + if (timeout++ > t) { + device_printf(dev, "Wait status %02x\n", st); + return (-1); + } + } + return (timeout); +} + +static void +mvs_requeue_frozen(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + union ccb *fccb = ch->frozen; + + if (fccb) { + ch->frozen = NULL; + fccb->ccb_h.status = CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ; + if (!(fccb->ccb_h.status & CAM_DEV_QFRZN)) { + xpt_freeze_devq(fccb->ccb_h.path, 1); + fccb->ccb_h.status |= CAM_DEV_QFRZN; + } + xpt_done(fccb); + } +} + +static void +mvs_reset(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + int i; + + xpt_freeze_simq(ch->sim, 1); + if (bootverbose) + device_printf(dev, "MVS reset...\n"); + /* Requeue freezed command. */ + mvs_requeue_frozen(dev); + /* Kill the engine and requeue all running commands. */ + mvs_set_edma_mode(dev, MVS_EDMA_OFF); + ATA_OUTL(ch->r_mem, DMA_C, 0); + for (i = 0; i < MVS_MAX_SLOTS; i++) { + /* Do we have a running request on slot? */ + if (ch->slot[i].state < MVS_SLOT_RUNNING) + continue; + /* XXX; Commands in loading state. */ + mvs_end_transaction(&ch->slot[i], MVS_ERR_INNOCENT); + } + for (i = 0; i < MVS_MAX_SLOTS; i++) { + if (!ch->hold[i]) + continue; + xpt_done(ch->hold[i]); + ch->hold[i] = NULL; + ch->numhslots--; + } + if (ch->toslots != 0) + xpt_release_simq(ch->sim, TRUE); + ch->eslots = 0; + ch->toslots = 0; + ch->fatalerr = 0; + /* Tell the XPT about the event */ + xpt_async(AC_BUS_RESET, ch->path, NULL); + ATA_OUTL(ch->r_mem, EDMA_IEM, 0); + ATA_OUTL(ch->r_mem, EDMA_CMD, EDMA_CMD_EATARST); + DELAY(25); + ATA_OUTL(ch->r_mem, EDMA_CMD, 0); + /* Reset and reconnect PHY, */ + if (!mvs_sata_phy_reset(dev)) { + if (bootverbose) + device_printf(dev, + "MVS reset done: phy reset found no device\n"); + ch->devices = 0; + ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); + ATA_OUTL(ch->r_mem, EDMA_IEC, 0); + ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); + xpt_release_simq(ch->sim, TRUE); + return; + } + /* Wait for clearing busy status. */ + if ((i = mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, 15000)) < 0) + device_printf(dev, "device is not ready\n"); + else if (bootverbose) + device_printf(dev, "ready wait time=%dms\n", i); + ch->devices = 1; + ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); + ATA_OUTL(ch->r_mem, EDMA_IEC, 0); + ATA_OUTL(ch->r_mem, EDMA_IEM, ~EDMA_IE_TRANSIENT); + if (bootverbose) + device_printf(dev, "MVS reset done: device found\n"); + xpt_release_simq(ch->sim, TRUE); +} + +static void +mvs_softreset(device_t dev, union ccb *ccb) +{ + struct mvs_channel *ch = device_get_softc(dev); + int port = ccb->ccb_h.target_id & 0x0f; + int i; + + mvs_set_edma_mode(dev, MVS_EDMA_OFF); + ATA_OUTB(ch->r_mem, SATA_SATAICTL, port << SATA_SATAICTL_PMPTX_SHIFT); + ATA_OUTB(ch->r_mem, ATA_CONTROL, ATA_A_RESET); + DELAY(10000); + ATA_OUTB(ch->r_mem, ATA_CONTROL, 0); + ccb->ccb_h.status &= ~CAM_STATUS_MASK; + /* Wait for clearing busy status. */ + if ((i = mvs_wait(dev, 0, ATA_S_BUSY | ATA_S_DRQ, ccb->ccb_h.timeout)) < 0) { + ccb->ccb_h.status |= CAM_CMD_TIMEOUT; + } else { + ccb->ccb_h.status |= CAM_REQ_CMP; + } + mvs_tfd_read(dev, ccb); + xpt_done(ccb); +} + +static int +mvs_sata_connect(struct mvs_channel *ch) +{ + u_int32_t status; + int timeout; + + /* Wait up to 100ms for "connect well" */ + for (timeout = 0; timeout < 100 ; timeout++) { + status = ATA_INL(ch->r_mem, SATA_SS); + if (((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_ONLINE) && + ((status & SATA_SS_SPD_MASK) != SATA_SS_SPD_NO_SPEED) && + ((status & SATA_SS_IPM_MASK) == SATA_SS_IPM_ACTIVE)) + break; + if ((status & SATA_SS_DET_MASK) == SATA_SS_DET_PHY_OFFLINE) { + if (bootverbose) { + device_printf(ch->dev, "SATA offline status=%08x\n", + status); + } + return (0); + } + DELAY(1000); + } + if (timeout >= 100) { + if (bootverbose) { + device_printf(ch->dev, "SATA connect timeout status=%08x\n", + status); + } + return (0); + } + if (bootverbose) { + device_printf(ch->dev, "SATA connect time=%dms status=%08x\n", + timeout, status); + } + /* Clear SATA error register */ + ATA_OUTL(ch->r_mem, SATA_SE, 0xffffffff); + return (1); +} + +static int +mvs_sata_phy_reset(device_t dev) +{ + struct mvs_channel *ch = device_get_softc(dev); + int sata_rev; + uint32_t val; + + sata_rev = ch->user[ch->pm_present ? 15 : 0].revision; + if (sata_rev == 1) + val = SATA_SC_SPD_SPEED_GEN1; + else if (sata_rev == 2) + val = SATA_SC_SPD_SPEED_GEN2; + else if (sata_rev == 3) + val = SATA_SC_SPD_SPEED_GEN3; + else + val = 0; + ATA_OUTL(ch->r_mem, SATA_SC, + SATA_SC_DET_RESET | val | + SATA_SC_IPM_DIS_PARTIAL | SATA_SC_IPM_DIS_SLUMBER); + DELAY(5000); + ATA_OUTL(ch->r_mem, SATA_SC, + SATA_SC_DET_IDLE | val | ((ch->pm_level > 0) ? 0 : + (SATA_SC_IPM_DIS_PARTIAL | SATA_SC_IPM_DIS_SLUMBER))); + DELAY(5000); + if (!mvs_sata_connect(ch)) { + if (ch->pm_level > 0) + ATA_OUTL(ch->r_mem, SATA_SC, SATA_SC_DET_DISABLE); + return (0); + } + return (1); +} + +static int +mvs_check_ids(device_t dev, union ccb *ccb) +{ + struct mvs_channel *ch = device_get_softc(dev); + + if (ccb->ccb_h.target_id > ((ch->quirks & MVS_Q_GENI) ? 0 : 15)) { + ccb->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return (-1); + } + if (ccb->ccb_h.target_lun != 0) { + ccb->ccb_h.status = CAM_LUN_INVALID; + xpt_done(ccb); + return (-1); + } + return (0); +} + +static void +mvsaction(struct cam_sim *sim, union ccb *ccb) +{ + device_t dev; + struct mvs_channel *ch; + + CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mvsaction func_code=%x\n", + ccb->ccb_h.func_code)); + + ch = (struct mvs_channel *)cam_sim_softc(sim); + dev = ch->dev; + switch (ccb->ccb_h.func_code) { + /* Common cases first */ + case XPT_ATA_IO: /* Execute the requested I/O operation */ + case XPT_SCSI_IO: + if (mvs_check_ids(dev, ccb)) + return; + if (ch->devices == 0 || + (ch->pm_present == 0 && + ccb->ccb_h.target_id > 0 && ccb->ccb_h.target_id < 15)) { + ccb->ccb_h.status = CAM_SEL_TIMEOUT; + break; + } + /* Check for command collision. */ + if (mvs_check_collision(dev, ccb)) { + /* Freeze command. */ + ch->frozen = ccb; + /* We have only one frozen slot, so freeze simq also. */ + xpt_freeze_simq(ch->sim, 1); + return; + } + mvs_begin_transaction(dev, ccb); + return; + case XPT_EN_LUN: /* Enable LUN as a target */ + case XPT_TARGET_IO: /* Execute target I/O request */ + case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ + case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ + case XPT_ABORT: /* Abort the specified CCB */ + /* XXX Implement */ + ccb->ccb_h.status = CAM_REQ_INVALID; + break; + case XPT_SET_TRAN_SETTINGS: + { + struct ccb_trans_settings *cts = &ccb->cts; + struct mvs_device *d; + + if (mvs_check_ids(dev, ccb)) + return; + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) + d = &ch->curr[ccb->ccb_h.target_id]; + else + d = &ch->user[ccb->ccb_h.target_id]; + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION) + d->revision = cts->xport_specific.sata.revision; + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE) + d->mode = cts->xport_specific.sata.mode; + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT) { + d->bytecount = min((ch->quirks & MVS_Q_GENIIE) ? 8192 : 2048, + cts->xport_specific.sata.bytecount); + } + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_TAGS) + d->tags = min(MVS_MAX_SLOTS, cts->xport_specific.sata.tags); + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_PM) + ch->pm_present = cts->xport_specific.sata.pm_present; + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI) + d->atapi = cts->xport_specific.sata.atapi; + if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS) + d->caps = cts->xport_specific.sata.caps; + ccb->ccb_h.status = CAM_REQ_CMP; + break; + } + case XPT_GET_TRAN_SETTINGS: + /* Get default/user set transfer settings for the target */ + { + struct ccb_trans_settings *cts = &ccb->cts; + struct mvs_device *d; + uint32_t status; + + if (mvs_check_ids(dev, ccb)) + return; + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) + d = &ch->curr[ccb->ccb_h.target_id]; + else + d = &ch->user[ccb->ccb_h.target_id]; + cts->protocol = PROTO_ATA; + cts->protocol_version = PROTO_VERSION_UNSPECIFIED; + cts->transport = XPORT_SATA; + cts->transport_version = XPORT_VERSION_UNSPECIFIED; + cts->proto_specific.valid = 0; + cts->xport_specific.sata.valid = 0; + if (cts->type == CTS_TYPE_CURRENT_SETTINGS && + (ccb->ccb_h.target_id == 15 || + (ccb->ccb_h.target_id == 0 && !ch->pm_present))) { + status = ATA_INL(ch->r_mem, SATA_SS) & SATA_SS_SPD_MASK; + if (status & 0x0f0) { + cts->xport_specific.sata.revision = + (status & 0x0f0) >> 4; + cts->xport_specific.sata.valid |= + CTS_SATA_VALID_REVISION; + } + cts->xport_specific.sata.caps = d->caps & CTS_SATA_CAPS_D; +// if (ch->pm_level) +// cts->xport_specific.sata.caps |= CTS_SATA_CAPS_H_PMREQ; + cts->xport_specific.sata.caps &= + ch->user[ccb->ccb_h.target_id].caps; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; + } else { + cts->xport_specific.sata.revision = d->revision; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION; + cts->xport_specific.sata.caps = d->caps; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS; + } + cts->xport_specific.sata.mode = d->mode; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE; + cts->xport_specific.sata.bytecount = d->bytecount; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT; + cts->xport_specific.sata.pm_present = ch->pm_present; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_PM; + cts->xport_specific.sata.tags = d->tags; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_TAGS; + cts->xport_specific.sata.atapi = d->atapi; + cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI; + ccb->ccb_h.status = CAM_REQ_CMP; + break; + } + case XPT_RESET_BUS: /* Reset the specified SCSI bus */ + case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ + mvs_reset(dev); + ccb->ccb_h.status = CAM_REQ_CMP; + break; + case XPT_TERM_IO: /* Terminate the I/O process */ + /* XXX Implement */ + ccb->ccb_h.status = CAM_REQ_INVALID; + break; + case XPT_PATH_INQ: /* Path routing inquiry */ + { + struct ccb_pathinq *cpi = &ccb->cpi; + + cpi->version_num = 1; /* XXX??? */ + cpi->hba_inquiry = PI_SDTR_ABLE; + if (!(ch->quirks & MVS_Q_GENI)) { + cpi->hba_inquiry |= PI_SATAPM; + /* Gen-II is extremely slow with NCQ on PMP. */ + if ((ch->quirks & MVS_Q_GENIIE) || ch->pm_present == 0) + cpi->hba_inquiry |= PI_TAG_ABLE; + } + cpi->target_sprt = 0; + cpi->hba_misc = PIM_SEQSCAN; + cpi->hba_eng_cnt = 0; + if (!(ch->quirks & MVS_Q_GENI)) + cpi->max_target = 15; + else + cpi->max_target = 0; + cpi->max_lun = 0; + cpi->initiator_id = 0; + cpi->bus_id = cam_sim_bus(sim); + cpi->base_transfer_speed = 150000; + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "Marvell", HBA_IDLEN); + strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); + cpi->unit_number = cam_sim_unit(sim); + cpi->transport = XPORT_SATA; + cpi->transport_version = XPORT_VERSION_UNSPECIFIED; + cpi->protocol = PROTO_ATA; + cpi->protocol_version = PROTO_VERSION_UNSPECIFIED; + cpi->maxio = MAXPHYS; + cpi->ccb_h.status = CAM_REQ_CMP; + break; + } + default: + ccb->ccb_h.status = CAM_REQ_INVALID; + break; + } + xpt_done(ccb); +} + +static void +mvspoll(struct cam_sim *sim) +{ + struct mvs_channel *ch = (struct mvs_channel *)cam_sim_softc(sim); + struct mvs_intr_arg arg; + + arg.arg = ch->dev; + arg.cause = 2; /* XXX */ + mvs_ch_intr(arg.arg); +} + diff --git a/sys/dev/mvs/mvs.h b/sys/dev/mvs/mvs.h new file mode 100644 index 0000000..9ec4e3d --- /dev/null +++ b/sys/dev/mvs/mvs.h @@ -0,0 +1,650 @@ +/*- + * Copyright (c) 2010 Alexander Motin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "mvs_if.h" + +/* Chip registers */ +#define CHIP_PCIEIC 0x1900 /* PCIe Interrupt Cause */ +#define CHIP_PCIEIM 0x1910 /* PCIe Interrupt Mask */ +#define CHIP_PCIIC 0x1d58 /* PCI Interrupt Cause */ +#define CHIP_PCIIM 0x1d5c /* PCI Interrupt Mask */ +#define CHIP_MIC 0x1d60 /* Main Interrupt Cause */ +#define CHIP_MIM 0x1d64 /* Main Interrupt Mask */ +#define CHIP_SOC_MIC 0x20 /* SoC Main Interrupt Cause */ +#define CHIP_SOC_MIM 0x24 /* SoC Main Interrupt Mask */ +#define IC_ERR_IRQ (1 << 0) /* shift by (2 * port #) */ +#define IC_DONE_IRQ (1 << 1) /* shift by (2 * port #) */ +#define IC_HC0 0x000001ff /* bits 0-8 = HC0 */ +#define IC_HC_SHIFT 9 /* HC1 shift */ +#define IC_HC1 (IC_HC0 << IC_HC_SHIFT) /* 9-17 = HC1 */ +#define IC_ERR_HC0 0x00000055 /* HC0 ERR_IRQ */ +#define IC_DONE_HC0 0x000000aa /* HC0 DONE_IRQ */ +#define IC_ERR_HC1 (IC_ERR_HC0 << IC_HC_SHIFT) /* HC1 ERR_IRQ */ +#define IC_DONE_HC1 (IC_DONE_HC0 << IC_HC_SHIFT) /* HC1 DONE_IRQ */ +#define IC_HC0_COAL_DONE (1 << 8) /* HC0 IRQ coalescing */ +#define IC_HC1_COAL_DONE (1 << 17) /* HC1 IRQ coalescing */ +#define IC_PCI_ERR (1 << 18) +#define IC_TRAN_COAL_LO_DONE (1 << 19) /* transaction coalescing */ +#define IC_TRAN_COAL_HI_DONE (1 << 20) /* transaction coalescing */ +#define IC_ALL_PORTS_COAL_DONE (1 << 21) /* GEN_II(E) IRQ coalescing */ +#define IC_GPIO_INT (1 << 22) +#define IC_SELF_INT (1 << 23) +#define IC_TWSI_INT (1 << 24) +#define IC_MAIN_RSVD (0xfe000000) /* bits 31-25 */ +#define IC_MAIN_RSVD_5 (0xfff10000) /* bits 31-19 */ +#define IC_MAIN_RSVD_SOC (0xfffffec0) /* bits 31-9, 7-6 */ + +#define CHIP_SOC_LED 0x2C /* SoC LED Configuration */ + +/* Chip CCC registers */ +#define CHIP_ICC 0x18008 +#define CHIP_ICC_ALL_PORTS (1 << 4) /* all ports irq event */ +#define CHIP_ICT 0x180cc +#define CHIP_ITT 0x180d0 +#define CHIP_TRAN_COAL_CAUSE_LO 0x18088 +#define CHIP_TRAN_COAL_CAUSE_HI 0x1808c + +/* Host Controller registers */ +#define HC_SIZE 0x10000 +#define HC_OFFSET 0x20000 +#define HC_BASE(hc) ((hc) * HC_SIZE + HC_OFFSET) + +#define HC_CFG 0x0 /* Configuration */ +#define HC_CFG_TIMEOUT_MASK (0xff << 0) +#define HC_CFG_NODMABS (1 << 8) +#define HC_CFG_NOEDMABS (1 << 9) +#define HC_CFG_NOPRDBS (1 << 10) +#define HC_CFG_TIMEOUTEN (1 << 16) /* Timer Enable */ +#define HC_CFG_COALDIS(p) (1 << ((p) + 24))/* Coalescing Disable*/ +#define HC_RQOP 0x4 /* Request Queue Out-Pointer */ +#define HC_RQIP 0x8 /* Response Queue In-Pointer */ +#define HC_ICT 0xc /* Interrupt Coalescing Threshold */ +#define HC_ICT_SAICOALT_MASK 0x000000ff +#define HC_ITT 0x10 /* Interrupt Time Threshold */ +#define HC_ITT_SAITMTH_MASK 0x00ffffff +#define HC_IC 0x14 /* Interrupt Cause */ +#define HC_IC_DONE(p) (1 << (p)) /* SaCrpb/DMA Done */ +#define HC_IC_COAL (1 << 4) /* Intr Coalescing */ +#define HC_IC_DEV(p) (1 << ((p) + 8)) /* Device Intr */ + +/* Port registers */ +#define PORT_SIZE 0x2000 +#define PORT_OFFSET 0x2000 +#define PORT_BASE(hc) ((hc) * PORT_SIZE + PORT_OFFSET) + +#define EDMA_CFG 0x0 /* Configuration */ +#define EDMA_CFG_RESERVED (0x1f << 0) /* Queue len ? */ +#define EDMA_CFG_ESATANATVCMDQUE (1 << 5) +#define EDMA_CFG_ERDBSZ (1 << 8) +#define EDMA_CFG_EQUE (1 << 9) +#define EDMA_CFG_ERDBSZEXT (1 << 11) +#define EDMA_CFG_RESERVED2 (1 << 12) +#define EDMA_CFG_EWRBUFFERLEN (1 << 13) +#define EDMA_CFG_EDEVERR (1 << 14) +#define EDMA_CFG_EEDMAFBS (1 << 16) +#define EDMA_CFG_ECUTTHROUGHEN (1 << 17) +#define EDMA_CFG_EEARLYCOMPLETIONEN (1 << 18) +#define EDMA_CFG_EEDMAQUELEN (1 << 19) +#define EDMA_CFG_EHOSTQUEUECACHEEN (1 << 22) +#define EDMA_CFG_EMASKRXPM (1 << 23) +#define EDMA_CFG_RESUMEDIS (1 << 24) +#define EDMA_CFG_EDMAFBS (1 << 26) +#define EDMA_T 0x4 /* Timer */ +#define EDMA_IEC 0x8 /* Interrupt Error Cause */ +#define EDMA_IEM 0xc /* Interrupt Error Mask */ +#define EDMA_IE_EDEVERR (1 << 2) /* EDMA Device Error */ +#define EDMA_IE_EDEVDIS (1 << 3) /* EDMA Dev Disconn */ +#define EDMA_IE_EDEVCON (1 << 4) /* EDMA Dev Conn */ +#define EDMA_IE_SERRINT (1 << 5) +#define EDMA_IE_ESELFDIS (1 << 7) /* EDMA Self Disable */ +#define EDMA_IE_ETRANSINT (1 << 8) /* Transport Layer */ +#define EDMA_IE_EIORDYERR (1 << 12) /* EDMA IORdy Error */ +#define EDMA_IE_LINKXERR_SATACRC (1 << 0) /* SATA CRC error */ +#define EDMA_IE_LINKXERR_INTERNALFIFO (1 << 1) /* internal FIFO err */ +#define EDMA_IE_LINKXERR_LINKLAYERRESET (1 << 2) + /* Link Layer is reset by the reception of SYNC primitive from device */ +#define EDMA_IE_LINKXERR_OTHERERRORS (1 << 3) + /* + * Link state errors, coding errors, or running disparity errors occur + * during FIS reception. + */ +#define EDMA_IE_LINKTXERR_FISTXABORTED (1 << 4) /* FIS Tx is aborted */ +#define EDMA_IE_LINKCTLRXERR(x) ((x) << 13) /* Link Ctrl Recv Err */ +#define EDMA_IE_LINKDATARXERR(x) ((x) << 17) /* Link Data Recv Err */ +#define EDMA_IE_LINKCTLTXERR(x) ((x) << 21) /* Link Ctrl Tx Error */ +#define EDMA_IE_LINKDATATXERR(x) ((x) << 26) /* Link Data Tx Error */ +#define EDMA_IE_TRANSPROTERR (1 << 31) /* Transport Proto E */ +#define EDMA_IE_TRANSIENT (EDMA_IE_LINKCTLRXERR(0x0b) | \ + EDMA_IE_LINKCTLTXERR(0x1f)) + /* Non-fatal Errors */ +#define EDMA_REQQBAH 0x10 /* Request Queue Base Address High */ +#define EDMA_REQQIP 0x14 /* Request Queue In-Pointer */ +#define EDMA_REQQOP 0x18 /* Request Queue Out-Pointer */ +#define EDMA_REQQP_ERQQP_SHIFT 5 +#define EDMA_REQQP_ERQQP_MASK 0x000003e0 +#define EDMA_REQQP_ERQQBAP_MASK 0x00000c00 +#define EDMA_REQQP_ERQQBA_MASK 0xfffff000 +#define EDMA_RESQBAH 0x1c /* Response Queue Base Address High */ +#define EDMA_RESQIP 0x20 /* Response Queue In-Pointer */ +#define EDMA_RESQOP 0x24 /* Response Queue Out-Pointer */ +#define EDMA_RESQP_ERPQP_SHIFT 3 +#define EDMA_RESQP_ERPQP_MASK 0x000000f8 +#define EDMA_RESQP_ERPQBAP_MASK 0x00000300 +#define EDMA_RESQP_ERPQBA_MASK 0xfffffc00 +#define EDMA_CMD 0x28 /* Command */ +#define EDMA_CMD_EENEDMA (1 << 0) /* Enable EDMA */ +#define EDMA_CMD_EDSEDMA (1 << 1) /* Disable EDMA */ +#define EDMA_CMD_EATARST (1 << 2) /* ATA Device Reset */ +#define EDMA_CMD_EEDMAFRZ (1 << 4) /* EDMA Freeze */ +#define EDMA_TC 0x2c /* Test Control */ +#define EDMA_S 0x30 /* Status */ +#define EDMA_S_EDEVQUETAG(s) ((s) & 0x0000001f) +#define EDMA_S_EDEVDIR_WRITE (0 << 5) +#define EDMA_S_EDEVDIR_READ (1 << 5) +#define EDMA_S_ECACHEEMPTY (1 << 6) +#define EDMA_S_EDMAIDLE (1 << 7) +#define EDMA_S_ESTATE(s) (((s) & 0x0000ff00) >> 8) +#define EDMA_S_EIOID(s) (((s) & 0x003f0000) >> 16) +#define EDMA_IORT 0x34 /* IORdy Timeout */ +#define EDMA_CDT 0x40 /* Command Delay Threshold */ +#define EDMA_HC 0x60 /* Halt Condition */ +#define EDMA_UNKN_RESD 0x6C /* Unknown register */ +#define EDMA_CQDCQOS(x) (0x90 + ((x) << 2) + /* NCQ Done/TCQ Outstanding Status */ + +/* ATA register defines */ +#define ATA_DATA 0x100 /* (RW) data */ +#define ATA_FEATURE 0x104 /* (W) feature */ +#define ATA_F_DMA 0x01 /* enable DMA */ +#define ATA_F_OVL 0x02 /* enable overlap */ +#define ATA_ERROR 0x104 /* (R) error */ +#define ATA_E_ILI 0x01 /* illegal length */ +#define ATA_E_NM 0x02 /* no media */ +#define ATA_E_ABORT 0x04 /* command aborted */ +#define ATA_E_MCR 0x08 /* media change request */ +#define ATA_E_IDNF 0x10 /* ID not found */ +#define ATA_E_MC 0x20 /* media changed */ +#define ATA_E_UNC 0x40 /* uncorrectable data */ +#define ATA_E_ICRC 0x80 /* UDMA crc error */ +#define ATA_E_ATAPI_SENSE_MASK 0xf0 /* ATAPI sense key mask */ +#define ATA_COUNT 0x108 /* (W) sector count */ +#define ATA_IREASON 0x108 /* (R) interrupt reason */ +#define ATA_I_CMD 0x01 /* cmd (1) | data (0) */ +#define ATA_I_IN 0x02 /* read (1) | write (0) */ +#define ATA_I_RELEASE 0x04 /* released bus (1) */ +#define ATA_I_TAGMASK 0xf8 /* tag mask */ +#define ATA_SECTOR 0x10c /* (RW) sector # */ +#define ATA_CYL_LSB 0x110 /* (RW) cylinder# LSB */ +#define ATA_CYL_MSB 0x114 /* (RW) cylinder# MSB */ +#define ATA_DRIVE 0x118 /* (W) Sector/Drive/Head */ +#define ATA_D_LBA 0x40 /* use LBA addressing */ +#define ATA_D_IBM 0xa0 /* 512 byte sectors, ECC */ +#define ATA_COMMAND 0x11c /* (W) command */ +#define ATA_STATUS 0x11c /* (R) status */ +#define ATA_S_ERROR 0x01 /* error */ +#define ATA_S_INDEX 0x02 /* index */ +#define ATA_S_CORR 0x04 /* data corrected */ +#define ATA_S_DRQ 0x08 /* data request */ +#define ATA_S_DSC 0x10 /* drive seek completed */ +#define ATA_S_SERVICE 0x10 /* drive needs service */ +#define ATA_S_DWF 0x20 /* drive write fault */ +#define ATA_S_DMA 0x20 /* DMA ready */ +#define ATA_S_READY 0x40 /* drive ready */ +#define ATA_S_BUSY 0x80 /* busy */ +#define ATA_CONTROL 0x120 /* (W) control */ +#define ATA_A_IDS 0x02 /* disable interrupts */ +#define ATA_A_RESET 0x04 /* RESET controller */ +#define ATA_A_4BIT 0x08 /* 4 head bits */ +#define ATA_A_HOB 0x80 /* High Order Byte enable */ +#define ATA_ALTSTAT 0x120 /* (R) alternate status */ +#define ATAPI_P_READ (ATA_S_DRQ | ATA_I_IN) +#define ATAPI_P_WRITE (ATA_S_DRQ) +#define ATAPI_P_CMDOUT (ATA_S_DRQ | ATA_I_CMD) +#define ATAPI_P_DONEDRQ (ATA_S_DRQ | ATA_I_CMD | ATA_I_IN) +#define ATAPI_P_DONE (ATA_I_CMD | ATA_I_IN) +#define ATAPI_P_ABORT 0 + +/* Basic DMA Registers */ +#define DMA_C 0x224 /* Basic DMA Command */ +#define DMA_C_START (1 << 0) +#define DMA_C_READ (1 << 3) +#define DMA_C_DREGIONVALID (1 << 8) +#define DMA_C_DREGIONLAST (1 << 9) +#define DMA_C_CONTFROMPREV (1 << 10) +#define DMA_C_DRBC(n) (((n) & 0xffff) << 16) +#define DMA_S 0x228 /* Basic DMA Status */ +#define DMA_S_ACT (1 << 0) /* Active */ +#define DMA_S_ERR (1 << 1) /* Error */ +#define DMA_S_PAUSED (1 << 2) /* Paused */ +#define DMA_S_LAST (1 << 3) /* Last */ +#define DMA_DTLBA 0x22c /* Descriptor Table Low Base Address */ +#define DMA_DTLBA_MASK 0xfffffff0 +#define DMA_DTHBA 0x230 /* Descriptor Table High Base Address */ +#define DMA_DRLA 0x234 /* Data Region Low Address */ +#define DMA_DRHA 0x238 /* Data Region High Address */ + +/* Serial-ATA Registers */ +#define SATA_SS 0x300 /* SStatus */ +#define SATA_SS_DET_MASK 0x0000000f +#define SATA_SS_DET_NO_DEVICE 0x00000000 +#define SATA_SS_DET_DEV_PRESENT 0x00000001 +#define SATA_SS_DET_PHY_ONLINE 0x00000003 +#define SATA_SS_DET_PHY_OFFLINE 0x00000004 + +#define SATA_SS_SPD_MASK 0x000000f0 +#define SATA_SS_SPD_NO_SPEED 0x00000000 +#define SATA_SS_SPD_GEN1 0x00000010 +#define SATA_SS_SPD_GEN2 0x00000020 +#define SATA_SS_SPD_GEN3 0x00000040 + +#define SATA_SS_IPM_MASK 0x00000f00 +#define SATA_SS_IPM_NO_DEVICE 0x00000000 +#define SATA_SS_IPM_ACTIVE 0x00000100 +#define SATA_SS_IPM_PARTIAL 0x00000200 +#define SATA_SS_IPM_SLUMBER 0x00000600 +#define SATA_SE 0x304 /* SError */ +#define SATA_SEIM 0x340 /* SError Interrupt Mask */ +#define SATA_SE_DATA_CORRECTED 0x00000001 +#define SATA_SE_COMM_CORRECTED 0x00000002 +#define SATA_SE_DATA_ERR 0x00000100 +#define SATA_SE_COMM_ERR 0x00000200 +#define SATA_SE_PROT_ERR 0x00000400 +#define SATA_SE_HOST_ERR 0x00000800 +#define SATA_SE_PHY_CHANGED 0x00010000 +#define SATA_SE_PHY_IERROR 0x00020000 +#define SATA_SE_COMM_WAKE 0x00040000 +#define SATA_SE_DECODE_ERR 0x00080000 +#define SATA_SE_PARITY_ERR 0x00100000 +#define SATA_SE_CRC_ERR 0x00200000 +#define SATA_SE_HANDSHAKE_ERR 0x00400000 +#define SATA_SE_LINKSEQ_ERR 0x00800000 +#define SATA_SE_TRANSPORT_ERR 0x01000000 +#define SATA_SE_UNKNOWN_FIS 0x02000000 +#define SATA_SC 0x308 /* SControl */ +#define SATA_SC_DET_MASK 0x0000000f +#define SATA_SC_DET_IDLE 0x00000000 +#define SATA_SC_DET_RESET 0x00000001 +#define SATA_SC_DET_DISABLE 0x00000004 + +#define SATA_SC_SPD_MASK 0x000000f0 +#define SATA_SC_SPD_NO_SPEED 0x00000000 +#define SATA_SC_SPD_SPEED_GEN1 0x00000010 +#define SATA_SC_SPD_SPEED_GEN2 0x00000020 +#define SATA_SC_SPD_SPEED_GEN3 0x00000040 + +#define SATA_SC_IPM_MASK 0x00000f00 +#define SATA_SC_IPM_NONE 0x00000000 +#define SATA_SC_IPM_DIS_PARTIAL 0x00000100 +#define SATA_SC_IPM_DIS_SLUMBER 0x00000200 + +#define SATA_SC_SPM_MASK 0x0000f000 +#define SATA_SC_SPM_NONE 0x00000000 +#define SATA_SC_SPM_PARTIAL 0x00001000 +#define SATA_SC_SPM_SLUMBER 0x00002000 +#define SATA_SC_SPM_ACTIVE 0x00004000 +#define SATA_LTM 0x30c /* LTMode */ +#define SATA_PHYM3 0x310 /* PHY Mode 3 */ +#define SATA_PHYM4 0x314 /* PHY Mode 4 */ +#define SATA_PHYM1 0x32c /* PHY Mode 1 */ +#define SATA_PHYM2 0x330 /* PHY Mode 2 */ +#define SATA_BISTC 0x334 /* BIST Control */ +#define SATA_BISTDW1 0x338 /* BIST DW1 */ +#define SATA_BISTDW2 0x33c /* BIST DW2 */ +#define SATA_SATAICFG 0x050 /* Serial-ATA Interface Configuration */ +#define SATA_SATAICFG_REFCLKCNF_20MHZ (0 << 0) +#define SATA_SATAICFG_REFCLKCNF_25MHZ (1 << 0) +#define SATA_SATAICFG_REFCLKCNF_30MHZ (2 << 0) +#define SATA_SATAICFG_REFCLKCNF_40MHZ (3 << 0) +#define SATA_SATAICFG_REFCLKCNF_MASK (3 << 0) +#define SATA_SATAICFG_REFCLKDIV_1 (0 << 2) +#define SATA_SATAICFG_REFCLKDIV_2 (1 << 2) /* Used 20 or 25MHz */ +#define SATA_SATAICFG_REFCLKDIV_4 (2 << 2) /* Used 40MHz */ +#define SATA_SATAICFG_REFCLKDIV_3 (3 << 2) /* Used 30MHz */ +#define SATA_SATAICFG_REFCLKDIV_MASK (3 << 2) +#define SATA_SATAICFG_REFCLKFEEDDIV_50 (0 << 4) /* or 100, when Gen2En is 1 */ +#define SATA_SATAICFG_REFCLKFEEDDIV_60 (1 << 4) /* or 120. Used 25MHz */ +#define SATA_SATAICFG_REFCLKFEEDDIV_75 (2 << 4) /* or 150. Used 20MHz */ +#define SATA_SATAICFG_REFCLKFEEDDIV_90 (3 << 4) /* or 180 */ +#define SATA_SATAICFG_REFCLKFEEDDIV_MASK (3 << 4) +#define SATA_SATAICFG_PHYSSCEN (1 << 6) +#define SATA_SATAICFG_GEN2EN (1 << 7) +#define SATA_SATAICFG_COMMEN (1 << 8) +#define SATA_SATAICFG_PHYSHUTDOWN (1 << 9) +#define SATA_SATAICFG_TARGETMODE (1 << 10) /* 1 = Initiator */ +#define SATA_SATAICFG_COMCHANNEL (1 << 11) +#define SATA_SATAICFG_IGNOREBSY (1 << 24) +#define SATA_SATAICFG_LINKRSTEN (1 << 25) +#define SATA_SATAICFG_CMDRETXDS (1 << 26) +#define SATA_SATAICTL 0x344 /* Serial-ATA Interface Control */ +#define SATA_SATAICTL_PMPTX_MASK 0x0000000f +#define SATA_SATAICTL_PMPTX_SHIFT 0 +#define SATA_SATAICTL_VUM (1 << 8) +#define SATA_SATAICTL_VUS (1 << 9) +#define SATA_SATAICTL_EDMAACT (1 << 16) +#define SATA_SATAICTL_CLEARSTAT (1 << 24) +#define SATA_SATAICTL_SRST (1 << 25) +#define SATA_SATAITC 0x348 /* Serial-ATA Interface Test Control */ +#define SATA_SATAIS 0x34c /* Serial-ATA Interface Status */ +#define SATA_VU 0x35c /* Vendor Unique */ +#define SATA_FISC 0x360 /* FIS Configuration */ +#define SATA_FISC_FISWAIT4RDYEN_B0 (1 << 0) /* Device to Host FIS */ +#define SATA_FISC_FISWAIT4RDYEN_B1 (1 << 1) /* SDB FIS rcv with bit 0 */ +#define SATA_FISC_FISWAIT4RDYEN_B2 (1 << 2) /* DMA Activate FIS */ +#define SATA_FISC_FISWAIT4RDYEN_B3 (1 << 3) /* DMA Setup FIS */ +#define SATA_FISC_FISWAIT4RDYEN_B4 (1 << 4) /* Data FIS first DW */ +#define SATA_FISC_FISWAIT4RDYEN_B5 (1 << 5) /* Data FIS entire FIS */ +#define SATA_FISC_FISWAIT4HOSTRDYEN_B0 (1 << 8) + /* Device to Host FIS with or */ +#define SATA_FISC_FISWAIT4HOSTRDYEN_B1 (1 << 9) /* SDB FIS rcv with bit */ +#define SATA_FISC_FISWAIT4HOSTRDYEN_B2 (1 << 10) /* SDB FIS rcv with */ +#define SATA_FISC_FISWAIT4HOSTRDYEN_B3 (1 << 11) /* BIST Acivate FIS */ +#define SATA_FISC_FISWAIT4HOSTRDYEN_B4 (1 << 12) /* PIO Setup FIS */ +#define SATA_FISC_FISWAIT4HOSTRDYEN_B5 (1 << 13) /* Data FIS with Link error */ +#define SATA_FISC_FISWAIT4HOSTRDYEN_B6 (1 << 14) /* Unrecognized FIS type */ +#define SATA_FISC_FISWAIT4HOSTRDYEN_B7 (1 << 15) /* Any FIS */ +#define SATA_FISC_FISDMAACTIVATESYNCRESP (1 << 16) +#define SATA_FISC_FISUNRECTYPECONT (1 << 17) +#define SATA_FISIC 0x364 /* FIS Interrupt Cause */ +#define SATA_FISIM 0x368 /* FIS Interrupt Mask */ +#define SATA_FISDW0 0x370 /* FIS DW0 */ +#define SATA_FISDW1 0x374 /* FIS DW1 */ +#define SATA_FISDW2 0x378 /* FIS DW2 */ +#define SATA_FISDW3 0x37c /* FIS DW3 */ +#define SATA_FISDW4 0x380 /* FIS DW4 */ +#define SATA_FISDW5 0x384 /* FIS DW5 */ +#define SATA_FISDW6 0x388 /* FIS DW6 */ + +#define MVS_MAX_PORTS 8 +#define MVS_MAX_SLOTS 32 + +/* Pessimistic prognosis on number of required S/G entries */ +#define MVS_SG_ENTRIES (btoc(MAXPHYS) + 1) + +/* EDMA Command Request Block (CRQB) Data */ +struct mvs_crqb { + uint32_t cprdbl; /* cPRD Desriptor Table Base Low Address */ + uint32_t cprdbh; /* cPRD Desriptor Table Base High Address */ + uint16_t ctrlflg; /* Control Flags */ +#define MVS_CRQB_READ 0x0001 +#define MVS_CRQB_TAG_MASK 0x003e +#define MVS_CRQB_TAG_SHIFT 1 +#define MVS_CRQB_PMP_MASK 0xf000 +#define MVS_CRQB_PMP_SHIFT 12 + uint8_t cmd[22]; +} __packed; + +struct mvs_crqb_gen2e { + uint32_t cprdbl; /* cPRD Desriptor Table Base Low Address */ + uint32_t cprdbh; /* cPRD Desriptor Table Base High Address */ + uint32_t ctrlflg; /* Control Flags */ +#define MVS_CRQB2E_READ 0x00000001 +#define MVS_CRQB2E_DTAG_MASK 0x0000003e +#define MVS_CRQB2E_DTAG_SHIFT 1 +#define MVS_CRQB2E_PMP_MASK 0x0000f000 +#define MVS_CRQB2E_PMP_SHIFT 12 +#define MVS_CRQB2E_CPRD 0x00010000 +#define MVS_CRQB2E_HTAG_MASK 0x003e0000 +#define MVS_CRQB2E_HTAG_SHIFT 17 + uint32_t drbc; /* Data Region Byte Count */ + uint8_t cmd[16]; +} __packed; + +/* EDMA Phisical Region Descriptors (ePRD) Table Data Structure */ +struct mvs_eprd { + uint32_t prdbal; /* Address bits[31:1] */ + uint32_t bytecount; /* Byte Count */ +#define MVS_EPRD_MASK 0x0000ffff /* max 64KB */ +#define MVS_EPRD_MAX (MVS_EPRD_MASK + 1) +#define MVS_EPRD_EOF 0x80000000 + uint32_t prdbah; /* Address bits[63:32] */ + uint32_t resv; +} __packed; + +/* Command request blocks. 32 commands. First 1Kbyte aligned. */ +#define MVS_CRQB_OFFSET 0 +#define MVS_CRQB_SIZE 32 /* sizeof(struct mvs_crqb) */ +#define MVS_CRQB_MASK 0x000003e0 +#define MVS_CRQB_SHIFT 5 +#define MVS_CRQB_TO_ADDR(slot) ((slot) << MVS_CRQB_SHIFT) +#define MVS_ADDR_TO_CRQB(addr) (((addr) & MVS_CRQB_MASK) >> MVS_CRQB_SHIFT) +/* ePRD blocks. Up to 32 commands, Each 16byte aligned. */ +#define MVS_EPRD_OFFSET (MVS_CRQB_OFFSET + MVS_CRQB_SIZE * MVS_MAX_SLOTS) +#define MVS_EPRD_SIZE (MVS_SG_ENTRIES * 16) /* sizeof(struct mvs_eprd) */ +/* Request work area. */ +#define MVS_WORKRQ_SIZE (MVS_EPRD_OFFSET + MVS_EPRD_SIZE * MVS_MAX_SLOTS) + +/* EDMA Command Response Block (CRPB) Data */ +struct mvs_crpb { + uint16_t id; /* CRPB ID */ +#define MVS_CRPB_TAG_MASK 0x001F +#define MVS_CRPB_TAG_SHIFT 0 + uint16_t rspflg; /* CPRB Response Flags */ +#define MVS_CRPB_EDMASTS_MASK 0x007F +#define MVS_CRPB_EDMASTS_SHIFT 0 +#define MVS_CRPB_ATASTS_MASK 0xFF00 +#define MVS_CRPB_ATASTS_SHIFT 8 + uint32_t ts; /* CPRB Time Stamp */ +} __packed; + +/* Command response blocks. 32 commands. First 256byte aligned. */ +#define MVS_CRPB_OFFSET 0 +#define MVS_CRPB_SIZE sizeof(struct mvs_crpb) +#define MVS_CRPB_MASK 0x000000f8 +#define MVS_CRPB_SHIFT 3 +#define MVS_CRPB_TO_ADDR(slot) ((slot) << MVS_CRPB_SHIFT) +#define MVS_ADDR_TO_CRPB(addr) (((addr) & MVS_CRPB_MASK) >> MVS_CRPB_SHIFT) +/* Request work area. */ +#define MVS_WORKRP_SIZE (MVS_CRPB_OFFSET + MVS_CRPB_SIZE * MVS_MAX_SLOTS) + +/* misc defines */ +#define ATA_IRQ_RID 0 +#define ATA_INTR_FLAGS (INTR_MPSAFE|INTR_TYPE_BIO|INTR_ENTROPY) + +struct ata_dmaslot { + bus_dmamap_t data_map; /* Data DMA map */ + bus_addr_t addr; /* Data address */ + uint16_t len; /* Data size */ +}; + +/* structure holding DMA related information */ +struct mvs_dma { + bus_dma_tag_t workrq_tag; /* Request workspace DMA tag */ + bus_dmamap_t workrq_map; /* Request workspace DMA map */ + uint8_t *workrq; /* Request workspace */ + bus_addr_t workrq_bus; /* Request bus address */ + bus_dma_tag_t workrp_tag; /* Reply workspace DMA tag */ + bus_dmamap_t workrp_map; /* Reply workspace DMA map */ + uint8_t *workrp; /* Reply workspace */ + bus_addr_t workrp_bus; /* Reply bus address */ + bus_dma_tag_t data_tag; /* Data DMA tag */ +}; + +enum mvs_slot_states { + MVS_SLOT_EMPTY, + MVS_SLOT_LOADING, + MVS_SLOT_RUNNING, + MVS_SLOT_EXECUTING +}; + +struct mvs_slot { + device_t dev; /* Device handle */ + int slot; /* Number of this slot */ + int tag; /* Used command tag */ + enum mvs_slot_states state; /* Slot state */ + union ccb *ccb; /* CCB occupying slot */ + struct ata_dmaslot dma; /* DMA data of this slot */ + struct callout timeout; /* Execution timeout */ +}; + +struct mvs_device { + int revision; + int mode; + u_int bytecount; + u_int atapi; + u_int tags; + u_int caps; +}; + +enum mvs_edma_mode { + MVS_EDMA_UNKNOWN, + MVS_EDMA_OFF, + MVS_EDMA_ON, + MVS_EDMA_QUEUED, + MVS_EDMA_NCQ, +}; + +/* structure describing an ATA channel */ +struct mvs_channel { + device_t dev; /* Device handle */ + int unit; /* Physical channel */ + struct resource *r_mem; /* Memory of this channel */ + struct resource *r_irq; /* Interrupt of this channel */ + void *ih; /* Interrupt handle */ + struct mvs_dma dma; /* DMA data */ + struct cam_sim *sim; + struct cam_path *path; + int quirks; +#define MVS_Q_GENI 1 +#define MVS_Q_GENII 2 +#define MVS_Q_GENIIE 4 +#define MVS_Q_SOC 8 +#define MVS_Q_CT 16 + int pm_level; /* power management level */ + + struct mvs_slot slot[MVS_MAX_SLOTS]; + union ccb *hold[MVS_MAX_SLOTS]; + int holdtag[MVS_MAX_SLOTS]; /* Tags used for holden commands. */ + struct mtx mtx; /* state lock */ + int devices; /* What is present */ + int pm_present; /* PM presence reported */ + enum mvs_edma_mode curr_mode; /* Current EDMA mode */ + int fbs_enabled; /* FIS-based switching enabled */ + uint32_t oslots; /* Occupied slots */ + uint32_t otagspd[16]; /* Occupied device tags */ + uint32_t rslots; /* Running slots */ + uint32_t aslots; /* Slots with atomic commands */ + uint32_t eslots; /* Slots in error */ + uint32_t toslots; /* Slots in timeout */ + int numrslots; /* Number of running slots */ + int numrslotspd[16];/* Number of running slots per dev */ + int numpslots; /* Number of PIO slots */ + int numdslots; /* Number of DMA slots */ + int numtslots; /* Number of NCQ slots */ + int numtslotspd[16];/* Number of NCQ slots per dev */ + int numhslots; /* Number of holden slots */ + int readlog; /* Our READ LOG active */ + int fatalerr; /* Fatal error happend */ + int lastslot; /* Last used slot */ + int taggedtarget; /* Last tagged target */ + int out_idx; /* Next written CRQB */ + int in_idx; /* Next read CRPB */ + u_int transfersize; /* PIO transfer size */ + u_int donecount; /* PIO bytes sent/received */ + u_int basic_dma; /* Basic DMA used for ATAPI */ + u_int fake_busy; /* Fake busy bit after command submission */ + union ccb *frozen; /* Frozen command */ + struct callout pm_timer; /* Power management events */ + + struct mvs_device user[16]; /* User-specified settings */ + struct mvs_device curr[16]; /* Current settings */ +}; + +/* structure describing a MVS controller */ +struct mvs_controller { + device_t dev; + int r_rid; + struct resource *r_mem; + struct rman sc_iomem; + struct mvs_controller_irq { + struct resource *r_irq; + void *handle; + int r_irq_rid; + } irq; + int quirks; + int channels; + int ccc; /* CCC timeout */ + int cccc; /* CCC commands */ + struct mtx mtx; /* MIM access lock */ + int gmim; /* Globally wanted MIM bits */ + int pmim; /* Port wanted MIM bits */ + int mim; /* Current MIM bits */ + int msi; /* MSI enabled */ + int msia; /* MSI active */ + struct { + void (*function)(void *); + void *argument; + } interrupt[MVS_MAX_PORTS]; +}; + +enum mvs_err_type { + MVS_ERR_NONE, /* No error */ + MVS_ERR_INVALID, /* Error detected by us before submitting. */ + MVS_ERR_INNOCENT, /* Innocent victim. */ + MVS_ERR_TFE, /* Task File Error. */ + MVS_ERR_SATA, /* SATA error. */ + MVS_ERR_TIMEOUT, /* Command execution timeout. */ + MVS_ERR_NCQ, /* NCQ command error. CCB should be put on hold + * until READ LOG executed to reveal error. */ +}; + +struct mvs_intr_arg { + void *arg; + u_int cause; +}; + +extern devclass_t mvs_devclass; + +/* macros to hide busspace uglyness */ +#define ATA_INB(res, offset) \ + bus_read_1((res), (offset)) +#define ATA_INW(res, offset) \ + bus_read_2((res), (offset)) +#define ATA_INL(res, offset) \ + bus_read_4((res), (offset)) +#define ATA_INSW(res, offset, addr, count) \ + bus_read_multi_2((res), (offset), (addr), (count)) +#define ATA_INSW_STRM(res, offset, addr, count) \ + bus_read_multi_stream_2((res), (offset), (addr), (count)) +#define ATA_INSL(res, offset, addr, count) \ + bus_read_multi_4((res), (offset), (addr), (count)) +#define ATA_INSL_STRM(res, offset, addr, count) \ + bus_read_multi_stream_4((res), (offset), (addr), (count)) +#define ATA_OUTB(res, offset, value) \ + bus_write_1((res), (offset), (value)) +#define ATA_OUTW(res, offset, value) \ + bus_write_2((res), (offset), (value)) +#define ATA_OUTL(res, offset, value) \ + bus_write_4((res), (offset), (value)); +#define ATA_OUTSW(res, offset, addr, count) \ + bus_write_multi_2((res), (offset), (addr), (count)) +#define ATA_OUTSW_STRM(res, offset, addr, count) \ + bus_write_multi_stream_2((res), (offset), (addr), (count)) +#define ATA_OUTSL(res, offset, addr, count) \ + bus_write_multi_4((res), (offset), (addr), (count)) +#define ATA_OUTSL_STRM(res, offset, addr, count) \ + bus_write_multi_stream_4((res), (offset), (addr), (count)) diff --git a/sys/dev/mvs/mvs_if.m b/sys/dev/mvs/mvs_if.m new file mode 100644 index 0000000..e744219 --- /dev/null +++ b/sys/dev/mvs/mvs_if.m @@ -0,0 +1,34 @@ +# Copyright (c) 2010 Alexander Motin +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer, +# without modification, immediately at the beginning of the file. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# $FreeBSD$ + +INTERFACE mvs; + +METHOD void edma { + device_t dev; + device_t child; + int mode; +}; + diff --git a/sys/dev/mvs/mvs_pci.c b/sys/dev/mvs/mvs_pci.c new file mode 100644 index 0000000..4fae627 --- /dev/null +++ b/sys/dev/mvs/mvs_pci.c @@ -0,0 +1,507 @@ +/*- + * Copyright (c) 2010 Alexander Motin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mvs.h" + +/* local prototypes */ +static int mvs_setup_interrupt(device_t dev); +static void mvs_intr(void *data); +static int mvs_suspend(device_t dev); +static int mvs_resume(device_t dev); +static int mvs_ctlr_setup(device_t dev); + +static struct { + uint32_t id; + uint8_t rev; + const char *name; + int ports; + int quirks; +} mvs_ids[] = { + {0x504011ab, 0x00, "Marvell 88SX5040", 4, MVS_Q_GENI}, + {0x504111ab, 0x00, "Marvell 88SX5041", 4, MVS_Q_GENI}, + {0x508011ab, 0x00, "Marvell 88SX5080", 8, MVS_Q_GENI}, + {0x508111ab, 0x00, "Marvell 88SX5081", 8, MVS_Q_GENI}, + {0x604011ab, 0x00, "Marvell 88SX6040", 4, MVS_Q_GENII}, + {0x604111ab, 0x00, "Marvell 88SX6041", 4, MVS_Q_GENII}, + {0x604211ab, 0x00, "Marvell 88SX6042", 4, MVS_Q_GENIIE}, + {0x608011ab, 0x00, "Marvell 88SX6080", 8, MVS_Q_GENII}, + {0x608111ab, 0x00, "Marvell 88SX6081", 8, MVS_Q_GENII}, + {0x704211ab, 0x00, "Marvell 88SX7042", 4, MVS_Q_GENIIE|MVS_Q_CT}, + {0x02419005, 0x00, "Adaptec 1420SA", 4, MVS_Q_GENII}, + {0x02439005, 0x00, "Adaptec 1430SA", 4, MVS_Q_GENIIE|MVS_Q_CT}, + {0x00000000, 0x00, NULL, 0, 0} +}; + +static int +mvs_probe(device_t dev) +{ + char buf[64]; + int i; + uint32_t devid = pci_get_devid(dev); + uint8_t revid = pci_get_revid(dev); + + for (i = 0; mvs_ids[i].id != 0; i++) { + if (mvs_ids[i].id == devid && + mvs_ids[i].rev <= revid) { + snprintf(buf, sizeof(buf), "%s SATA controller", + mvs_ids[i].name); + device_set_desc_copy(dev, buf); + return (BUS_PROBE_VENDOR); + } + } + return (ENXIO); +} + +static int +mvs_attach(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + device_t child; + int error, unit, i; + uint32_t devid = pci_get_devid(dev); + uint8_t revid = pci_get_revid(dev); + + ctlr->dev = dev; + i = 0; + while (mvs_ids[i].id != 0 && + (mvs_ids[i].id != devid || + mvs_ids[i].rev > revid)) + i++; + ctlr->channels = mvs_ids[i].ports; + ctlr->quirks = mvs_ids[i].quirks; + resource_int_value(device_get_name(dev), + device_get_unit(dev), "ccc", &ctlr->ccc); + ctlr->cccc = 8; + resource_int_value(device_get_name(dev), + device_get_unit(dev), "cccc", &ctlr->cccc); + if (ctlr->ccc == 0 || ctlr->cccc == 0) { + ctlr->ccc = 0; + ctlr->cccc = 0; + } + if (ctlr->ccc > 100000) + ctlr->ccc = 100000; + device_printf(dev, + "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n", + ((ctlr->quirks & MVS_Q_GENI) ? "I" : + ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")), + ctlr->channels, + ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"), + ((ctlr->quirks & MVS_Q_GENI) ? + "not supported" : "supported"), + ((ctlr->quirks & MVS_Q_GENIIE) ? + " with FBS" : "")); + mtx_init(&ctlr->mtx, "MVS controller lock", NULL, MTX_DEF); + /* We should have a memory BAR(0). */ + ctlr->r_rid = PCIR_BAR(0); + if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &ctlr->r_rid, RF_ACTIVE))) + return ENXIO; + /* Setup our own memory management for channels. */ + ctlr->sc_iomem.rm_type = RMAN_ARRAY; + ctlr->sc_iomem.rm_descr = "I/O memory addresses"; + if ((error = rman_init(&ctlr->sc_iomem)) != 0) { + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + return (error); + } + if ((error = rman_manage_region(&ctlr->sc_iomem, + rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) { + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + rman_fini(&ctlr->sc_iomem); + return (error); + } + pci_enable_busmaster(dev); + mvs_ctlr_setup(dev); + /* Setup interrupts. */ + if (mvs_setup_interrupt(dev)) { + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + rman_fini(&ctlr->sc_iomem); + return ENXIO; + } + /* Attach all channels on this controller */ + for (unit = 0; unit < ctlr->channels; unit++) { + child = device_add_child(dev, "mvsch", -1); + if (child == NULL) + device_printf(dev, "failed to add channel device\n"); + else + device_set_ivars(child, (void *)(intptr_t)unit); + } + bus_generic_attach(dev); + return 0; +} + +static int +mvs_detach(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + device_t *children; + int nchildren, i; + + /* Detach & delete all children */ + if (!device_get_children(dev, &children, &nchildren)) { + for (i = 0; i < nchildren; i++) + device_delete_child(dev, children[i]); + free(children, M_TEMP); + } + /* Free interrupt. */ + if (ctlr->irq.r_irq) { + bus_teardown_intr(dev, ctlr->irq.r_irq, + ctlr->irq.handle); + bus_release_resource(dev, SYS_RES_IRQ, + ctlr->irq.r_irq_rid, ctlr->irq.r_irq); + } + pci_release_msi(dev); + /* Free memory. */ + rman_fini(&ctlr->sc_iomem); + if (ctlr->r_mem) + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + mtx_destroy(&ctlr->mtx); + return (0); +} + +static int +mvs_ctlr_setup(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int i, ccc = ctlr->ccc, cccc = ctlr->cccc, ccim = 0; + + /* Mask chip interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0x00000000); + /* Mask PCI interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x00000000); + /* Clear PCI interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_PCIIC, 0x00000000); + if (ccc && bootverbose) { + device_printf(dev, + "CCC with %dus/%dcmd enabled\n", + ctlr->ccc, ctlr->cccc); + } + ccc *= 150; + /* Configure chip-global CCC */ + if (ctlr->channels > 4 && (ctlr->quirks & MVS_Q_GENI) == 0) { + ATA_OUTL(ctlr->r_mem, CHIP_ICT, cccc); + ATA_OUTL(ctlr->r_mem, CHIP_ITT, ccc); + ATA_OUTL(ctlr->r_mem, CHIP_ICC, ~CHIP_ICC_ALL_PORTS); + if (ccc) + ccim |= IC_ALL_PORTS_COAL_DONE; + ccc = 0; + cccc = 0; + } + for (i = 0; i < ctlr->channels / 4; i++) { + /* Configure per-HC CCC */ + ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_ICT, cccc); + ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_ITT, ccc); + if (ccc) + ccim |= (IC_HC0_COAL_DONE << (i * IC_HC_SHIFT)); + /* Clear HC interrupts */ + ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_IC, 0x00000000); + } + /* Enable chip interrupts */ + ctlr->gmim = (ccim ? ccim : (IC_DONE_HC0 | IC_DONE_HC1)) | + IC_ERR_HC0 | IC_ERR_HC1; + ctlr->mim = ctlr->gmim | ctlr->pmim; + ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim); + /* Enable PCI interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x007fffff); + return (0); +} + +static void +mvs_edma(device_t dev, device_t child, int mode) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int unit = ((struct mvs_channel *)device_get_softc(child))->unit; + int bit = IC_DONE_IRQ << (unit * 2 + unit / 4) ; + + if (ctlr->ccc == 0) + return; + /* CCC is not working for non-EDMA mode. Unmask device interrupts. */ + mtx_lock(&ctlr->mtx); + if (mode == MVS_EDMA_OFF) + ctlr->pmim |= bit; + else + ctlr->pmim &= ~bit; + ctlr->mim = ctlr->gmim | ctlr->pmim; + if (!ctlr->msia) + ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim); + mtx_unlock(&ctlr->mtx); +} + +static int +mvs_suspend(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + + bus_generic_suspend(dev); + /* Mask chip interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0x00000000); + /* Mask PCI interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x00000000); + return 0; +} + +static int +mvs_resume(device_t dev) +{ + + mvs_ctlr_setup(dev); + return (bus_generic_resume(dev)); +} + +static int +mvs_setup_interrupt(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int msi = 0; + + /* Process hints. */ + resource_int_value(device_get_name(dev), + device_get_unit(dev), "msi", &msi); + if (msi < 0) + msi = 0; + else if (msi > 0) + msi = min(1, pci_msi_count(dev)); + /* Allocate MSI if needed/present. */ + if (msi && pci_alloc_msi(dev, &msi) != 0) + msi = 0; + ctlr->msi = msi; + /* Allocate all IRQs. */ + ctlr->irq.r_irq_rid = msi ? 1 : 0; + if (!(ctlr->irq.r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &ctlr->irq.r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "unable to map interrupt\n"); + return (ENXIO); + } + if ((bus_setup_intr(dev, ctlr->irq.r_irq, ATA_INTR_FLAGS, NULL, + mvs_intr, ctlr, &ctlr->irq.handle))) { + device_printf(dev, "unable to setup interrupt\n"); + bus_release_resource(dev, SYS_RES_IRQ, + ctlr->irq.r_irq_rid, ctlr->irq.r_irq); + ctlr->irq.r_irq = 0; + return (ENXIO); + } + return (0); +} + +/* + * Common case interrupt handler. + */ +static void +mvs_intr(void *data) +{ + struct mvs_controller *ctlr = data; + struct mvs_intr_arg arg; + void (*function)(void *); + int p; + u_int32_t ic, aic; + + ic = ATA_INL(ctlr->r_mem, CHIP_MIC); +//device_printf(ctlr->dev, "irq MIC:%08x\n", ic); + if (ctlr->msi) { + /* We have to to mask MSI during processing. */ + mtx_lock(&ctlr->mtx); + ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0); + ctlr->msia = 1; /* Deny MIM update during processing. */ + mtx_unlock(&ctlr->mtx); + } else if (ic == 0) + return; + /* Acknowledge all-ports CCC interrupt. */ + if (ic & IC_ALL_PORTS_COAL_DONE) + ATA_OUTL(ctlr->r_mem, CHIP_ICC, ~CHIP_ICC_ALL_PORTS); + for (p = 0; p < ctlr->channels; p++) { + if ((p & 3) == 0) { + if (p != 0) + ic >>= 1; + if ((ic & IC_HC0) == 0) { + p += 3; + ic >>= 8; + continue; + } + /* Acknowledge interrupts of this HC. */ + aic = 0; + if (ic & (IC_DONE_IRQ << 0)) + aic |= HC_IC_DONE(0) | HC_IC_DEV(0); + if (ic & (IC_DONE_IRQ << 2)) + aic |= HC_IC_DONE(1) | HC_IC_DEV(1); + if (ic & (IC_DONE_IRQ << 4)) + aic |= HC_IC_DONE(2) | HC_IC_DEV(2); + if (ic & (IC_DONE_IRQ << 6)) + aic |= HC_IC_DONE(3) | HC_IC_DEV(3); + if (ic & IC_HC0_COAL_DONE) + aic |= HC_IC_COAL; + ATA_OUTL(ctlr->r_mem, HC_BASE(p == 4) + HC_IC, ~aic); + } + /* Call per-port interrupt handler. */ + arg.cause = ic & (IC_ERR_IRQ|IC_DONE_IRQ); + if ((arg.cause != 0) && + (function = ctlr->interrupt[p].function)) { + arg.arg = ctlr->interrupt[p].argument; + function(&arg); + } + ic >>= 2; + } + if (ctlr->msi) { + /* Unmasking MSI triggers next interrupt, if needed. */ + mtx_lock(&ctlr->mtx); + ctlr->msia = 0; /* Allow MIM update. */ + ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim); + mtx_unlock(&ctlr->mtx); + } +} + +static struct resource * +mvs_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int unit = ((struct mvs_channel *)device_get_softc(child))->unit; + struct resource *res = NULL; + int offset = HC_BASE(unit >> 2) + PORT_BASE(unit & 0x03); + long st; + + switch (type) { + case SYS_RES_MEMORY: + st = rman_get_start(ctlr->r_mem); + res = rman_reserve_resource(&ctlr->sc_iomem, st + offset, + st + offset + PORT_SIZE - 1, PORT_SIZE, RF_ACTIVE, child); + if (res) { + bus_space_handle_t bsh; + bus_space_tag_t bst; + bsh = rman_get_bushandle(ctlr->r_mem); + bst = rman_get_bustag(ctlr->r_mem); + bus_space_subregion(bst, bsh, offset, PORT_SIZE, &bsh); + rman_set_bushandle(res, bsh); + rman_set_bustag(res, bst); + } + break; + case SYS_RES_IRQ: + if (*rid == ATA_IRQ_RID) + res = ctlr->irq.r_irq; + break; + } + return (res); +} + +static int +mvs_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + + switch (type) { + case SYS_RES_MEMORY: + rman_release_resource(r); + return (0); + case SYS_RES_IRQ: + if (rid != ATA_IRQ_RID) + return ENOENT; + return (0); + } + return (EINVAL); +} + +static int +mvs_setup_intr(device_t dev, device_t child, struct resource *irq, + int flags, driver_filter_t *filter, driver_intr_t *function, + void *argument, void **cookiep) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int unit = (intptr_t)device_get_ivars(child); + + if (filter != NULL) { + printf("mvs.c: we cannot use a filter here\n"); + return (EINVAL); + } + ctlr->interrupt[unit].function = function; + ctlr->interrupt[unit].argument = argument; + return (0); +} + +static int +mvs_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int unit = (intptr_t)device_get_ivars(child); + + ctlr->interrupt[unit].function = NULL; + ctlr->interrupt[unit].argument = NULL; + return (0); +} + +static int +mvs_print_child(device_t dev, device_t child) +{ + int retval; + + retval = bus_print_child_header(dev, child); + retval += printf(" at channel %d", + (int)(intptr_t)device_get_ivars(child)); + retval += bus_print_child_footer(dev, child); + + return (retval); +} + +static device_method_t mvs_methods[] = { + DEVMETHOD(device_probe, mvs_probe), + DEVMETHOD(device_attach, mvs_attach), + DEVMETHOD(device_detach, mvs_detach), + DEVMETHOD(device_suspend, mvs_suspend), + DEVMETHOD(device_resume, mvs_resume), + DEVMETHOD(bus_print_child, mvs_print_child), + DEVMETHOD(bus_alloc_resource, mvs_alloc_resource), + DEVMETHOD(bus_release_resource, mvs_release_resource), + DEVMETHOD(bus_setup_intr, mvs_setup_intr), + DEVMETHOD(bus_teardown_intr,mvs_teardown_intr), + DEVMETHOD(mvs_edma, mvs_edma), + { 0, 0 } +}; +static driver_t mvs_driver = { + "mvs", + mvs_methods, + sizeof(struct mvs_controller) +}; +DRIVER_MODULE(mvs, pci, mvs_driver, mvs_devclass, 0, 0); +MODULE_VERSION(mvs, 1); +MODULE_DEPEND(mvs, cam, 1, 1, 1); + diff --git a/sys/dev/mvs/mvs_soc.c b/sys/dev/mvs/mvs_soc.c new file mode 100644 index 0000000..298a873 --- /dev/null +++ b/sys/dev/mvs/mvs_soc.c @@ -0,0 +1,437 @@ +/*- + * Copyright (c) 2010 Alexander Motin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mvs.h" + +/* local prototypes */ +static int mvs_setup_interrupt(device_t dev); +static void mvs_intr(void *data); +static int mvs_suspend(device_t dev); +static int mvs_resume(device_t dev); +static int mvs_ctlr_setup(device_t dev); + +static struct { + uint32_t id; + uint8_t rev; + const char *name; + int ports; + int quirks; +} mvs_ids[] = { + {MV_DEV_88F5182, 0x00, "Marvell 88F5182", 2, MVS_Q_GENIIE|MVS_Q_SOC}, + {MV_DEV_88F6281, 0x00, "Marvell 88F6281", 2, MVS_Q_GENIIE|MVS_Q_SOC}, + {MV_DEV_MV78100, 0x00, "Marvell MV78100", 2, MVS_Q_GENIIE|MVS_Q_SOC}, + {MV_DEV_MV78100_Z0, 0x00,"Marvell MV78100", 2, MVS_Q_GENIIE|MVS_Q_SOC}, + {0, 0x00, NULL, 0, 0} +}; + +static int +mvs_probe(device_t dev) +{ + char buf[64]; + int i; + uint32_t devid, revid; + + soc_id(&devid, &revid); + for (i = 0; mvs_ids[i].id != 0; i++) { + if (mvs_ids[i].id == devid && + mvs_ids[i].rev <= revid) { + snprintf(buf, sizeof(buf), "%s SATA controller", + mvs_ids[i].name); + device_set_desc_copy(dev, buf); + return (BUS_PROBE_VENDOR); + } + } + return (ENXIO); +} + +static int +mvs_attach(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + device_t child; + int error, unit, i; + uint32_t devid, revid; + + soc_id(&devid, &revid); + ctlr->dev = dev; + i = 0; + while (mvs_ids[i].id != 0 && + (mvs_ids[i].id != devid || + mvs_ids[i].rev > revid)) + i++; + ctlr->channels = mvs_ids[i].ports; + ctlr->quirks = mvs_ids[i].quirks; + resource_int_value(device_get_name(dev), + device_get_unit(dev), "ccc", &ctlr->ccc); + ctlr->cccc = 8; + resource_int_value(device_get_name(dev), + device_get_unit(dev), "cccc", &ctlr->cccc); + if (ctlr->ccc == 0 || ctlr->cccc == 0) { + ctlr->ccc = 0; + ctlr->cccc = 0; + } + if (ctlr->ccc > 100000) + ctlr->ccc = 100000; + device_printf(dev, + "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n", + ((ctlr->quirks & MVS_Q_GENI) ? "I" : + ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")), + ctlr->channels, + ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"), + ((ctlr->quirks & MVS_Q_GENI) ? + "not supported" : "supported"), + ((ctlr->quirks & MVS_Q_GENIIE) ? + " with FBS" : "")); + mtx_init(&ctlr->mtx, "MVS controller lock", NULL, MTX_DEF); + /* We should have a memory BAR(0). */ + ctlr->r_rid = 0; + if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &ctlr->r_rid, RF_ACTIVE))) + return ENXIO; + /* Setup our own memory management for channels. */ + ctlr->sc_iomem.rm_type = RMAN_ARRAY; + ctlr->sc_iomem.rm_descr = "I/O memory addresses"; + if ((error = rman_init(&ctlr->sc_iomem)) != 0) { + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + return (error); + } + if ((error = rman_manage_region(&ctlr->sc_iomem, + rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) { + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + rman_fini(&ctlr->sc_iomem); + return (error); + } + mvs_ctlr_setup(dev); + /* Setup interrupts. */ + if (mvs_setup_interrupt(dev)) { + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + rman_fini(&ctlr->sc_iomem); + return ENXIO; + } + /* Attach all channels on this controller */ + for (unit = 0; unit < ctlr->channels; unit++) { + child = device_add_child(dev, "mvsch", -1); + if (child == NULL) + device_printf(dev, "failed to add channel device\n"); + else + device_set_ivars(child, (void *)(intptr_t)unit); + } + bus_generic_attach(dev); + return 0; +} + +static int +mvs_detach(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + device_t *children; + int nchildren, i; + + /* Detach & delete all children */ + if (!device_get_children(dev, &children, &nchildren)) { + for (i = 0; i < nchildren; i++) + device_delete_child(dev, children[i]); + free(children, M_TEMP); + } + /* Free interrupt. */ + if (ctlr->irq.r_irq) { + bus_teardown_intr(dev, ctlr->irq.r_irq, + ctlr->irq.handle); + bus_release_resource(dev, SYS_RES_IRQ, + ctlr->irq.r_irq_rid, ctlr->irq.r_irq); + } + /* Free memory. */ + rman_fini(&ctlr->sc_iomem); + if (ctlr->r_mem) + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + mtx_destroy(&ctlr->mtx); + return (0); +} + +static int +mvs_ctlr_setup(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int ccc = ctlr->ccc, cccc = ctlr->cccc, ccim = 0; + + /* Mask chip interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, 0x00000000); + /* Clear HC interrupts */ + ATA_OUTL(ctlr->r_mem, HC_IC, 0x00000000); + /* Clear chip interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIC, 0); + /* Configure per-HC CCC */ + if (ccc && bootverbose) { + device_printf(dev, + "CCC with %dus/%dcmd enabled\n", + ctlr->ccc, ctlr->cccc); + } + ccc *= 150; + ATA_OUTL(ctlr->r_mem, HC_ICT, cccc); + ATA_OUTL(ctlr->r_mem, HC_ITT, ccc); + if (ccc) + ccim |= IC_HC0_COAL_DONE; + /* Enable chip interrupts */ + ctlr->gmim = (ccc ? IC_HC0_COAL_DONE : IC_DONE_HC0) | IC_ERR_HC0; + ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, ctlr->gmim | ctlr->pmim); + return (0); +} + +static void +mvs_edma(device_t dev, device_t child, int mode) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int unit = ((struct mvs_channel *)device_get_softc(child))->unit; + int bit = IC_DONE_IRQ << (unit * 2); + + if (ctlr->ccc == 0) + return; + /* CCC is not working for non-EDMA mode. Unmask device interrupts. */ + mtx_lock(&ctlr->mtx); + if (mode == MVS_EDMA_OFF) + ctlr->pmim |= bit; + else + ctlr->pmim &= ~bit; + ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, ctlr->gmim | ctlr->pmim); + mtx_unlock(&ctlr->mtx); +} + +static int +mvs_suspend(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + + bus_generic_suspend(dev); + /* Mask chip interrupts */ + ATA_OUTL(ctlr->r_mem, CHIP_SOC_MIM, 0x00000000); + return 0; +} + +static int +mvs_resume(device_t dev) +{ + + mvs_ctlr_setup(dev); + return (bus_generic_resume(dev)); +} + +static int +mvs_setup_interrupt(device_t dev) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + + /* Allocate all IRQs. */ + ctlr->irq.r_irq_rid = 0; + if (!(ctlr->irq.r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &ctlr->irq.r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "unable to map interrupt\n"); + return (ENXIO); + } + if ((bus_setup_intr(dev, ctlr->irq.r_irq, ATA_INTR_FLAGS, NULL, + mvs_intr, ctlr, &ctlr->irq.handle))) { + device_printf(dev, "unable to setup interrupt\n"); + bus_release_resource(dev, SYS_RES_IRQ, + ctlr->irq.r_irq_rid, ctlr->irq.r_irq); + ctlr->irq.r_irq = 0; + return (ENXIO); + } + return (0); +} + +/* + * Common case interrupt handler. + */ +static void +mvs_intr(void *data) +{ + struct mvs_controller *ctlr = data; + struct mvs_intr_arg arg; + void (*function)(void *); + int p; + u_int32_t ic, aic; + + ic = ATA_INL(ctlr->r_mem, CHIP_SOC_MIC); +//device_printf(ctlr->dev, "irq MIC:%08x\n", ic); + if ((ic & IC_HC0) == 0) + return; + /* Acknowledge interrupts of this HC. */ + aic = 0; + if (ic & (IC_DONE_IRQ << 0)) + aic |= HC_IC_DONE(0) | HC_IC_DEV(0); + if (ic & (IC_DONE_IRQ << 2)) + aic |= HC_IC_DONE(1) | HC_IC_DEV(1); + if (ic & (IC_DONE_IRQ << 4)) + aic |= HC_IC_DONE(2) | HC_IC_DEV(2); + if (ic & (IC_DONE_IRQ << 6)) + aic |= HC_IC_DONE(3) | HC_IC_DEV(3); + if (ic & IC_HC0_COAL_DONE) + aic |= HC_IC_COAL; + ATA_OUTL(ctlr->r_mem, HC_IC, ~aic); + /* Call per-port interrupt handler. */ + for (p = 0; p < ctlr->channels; p++) { + arg.cause = ic & (IC_ERR_IRQ|IC_DONE_IRQ); + if ((arg.cause != 0) && + (function = ctlr->interrupt[p].function)) { + arg.arg = ctlr->interrupt[p].argument; + function(&arg); + } + ic >>= 2; + } +} + +static struct resource * +mvs_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int unit = ((struct mvs_channel *)device_get_softc(child))->unit; + struct resource *res = NULL; + int offset = PORT_BASE(unit & 0x03); + long st; + + switch (type) { + case SYS_RES_MEMORY: + st = rman_get_start(ctlr->r_mem); + res = rman_reserve_resource(&ctlr->sc_iomem, st + offset, + st + offset + PORT_SIZE - 1, PORT_SIZE, RF_ACTIVE, child); + if (res) { + bus_space_handle_t bsh; + bus_space_tag_t bst; + bsh = rman_get_bushandle(ctlr->r_mem); + bst = rman_get_bustag(ctlr->r_mem); + bus_space_subregion(bst, bsh, offset, PORT_SIZE, &bsh); + rman_set_bushandle(res, bsh); + rman_set_bustag(res, bst); + } + break; + case SYS_RES_IRQ: + if (*rid == ATA_IRQ_RID) + res = ctlr->irq.r_irq; + break; + } + return (res); +} + +static int +mvs_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + + switch (type) { + case SYS_RES_MEMORY: + rman_release_resource(r); + return (0); + case SYS_RES_IRQ: + if (rid != ATA_IRQ_RID) + return ENOENT; + return (0); + } + return (EINVAL); +} + +static int +mvs_setup_intr(device_t dev, device_t child, struct resource *irq, + int flags, driver_filter_t *filter, driver_intr_t *function, + void *argument, void **cookiep) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int unit = (intptr_t)device_get_ivars(child); + + if (filter != NULL) { + printf("mvs.c: we cannot use a filter here\n"); + return (EINVAL); + } + ctlr->interrupt[unit].function = function; + ctlr->interrupt[unit].argument = argument; + return (0); +} + +static int +mvs_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) +{ + struct mvs_controller *ctlr = device_get_softc(dev); + int unit = (intptr_t)device_get_ivars(child); + + ctlr->interrupt[unit].function = NULL; + ctlr->interrupt[unit].argument = NULL; + return (0); +} + +static int +mvs_print_child(device_t dev, device_t child) +{ + int retval; + + retval = bus_print_child_header(dev, child); + retval += printf(" at channel %d", + (int)(intptr_t)device_get_ivars(child)); + retval += bus_print_child_footer(dev, child); + + return (retval); +} + +static device_method_t mvs_methods[] = { + DEVMETHOD(device_probe, mvs_probe), + DEVMETHOD(device_attach, mvs_attach), + DEVMETHOD(device_detach, mvs_detach), + DEVMETHOD(device_suspend, mvs_suspend), + DEVMETHOD(device_resume, mvs_resume), + DEVMETHOD(bus_print_child, mvs_print_child), + DEVMETHOD(bus_alloc_resource, mvs_alloc_resource), + DEVMETHOD(bus_release_resource, mvs_release_resource), + DEVMETHOD(bus_setup_intr, mvs_setup_intr), + DEVMETHOD(bus_teardown_intr,mvs_teardown_intr), + DEVMETHOD(mvs_edma, mvs_edma), + { 0, 0 } +}; +static driver_t mvs_driver = { + "sata", + mvs_methods, + sizeof(struct mvs_controller) +}; +DRIVER_MODULE(sata, mbus, mvs_driver, mvs_devclass, 0, 0); +MODULE_VERSION(sata, 1); + diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 83c7757..601b73b 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -188,6 +188,7 @@ SUBDIR= ${_3dfx} \ msdosfs_iconv \ ${_mse} \ msk \ + mvs \ mwl \ mxge \ my \ diff --git a/sys/modules/mvs/Makefile b/sys/modules/mvs/Makefile new file mode 100644 index 0000000..f33a092 --- /dev/null +++ b/sys/modules/mvs/Makefile @@ -0,0 +1,10 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../dev/mvs + +KMOD= mvs +SRCS= mvs.c mvs_pci.c mvs.h mvs_if.h device_if.h bus_if.h pci_if.h opt_cam.h + +MFILES= kern/bus_if.m kern/device_if.m dev/pci/pci_if.m dev/mvs/mvs_if.m + +.include -- cgit v1.1 From 630328c1b513925136fa49a9af3f323f4a7d53c9 Mon Sep 17 00:00:00 2001 From: marius Date: Sun, 2 May 2010 19:38:17 +0000 Subject: Add support for SPARC64 V (and where it already makes sense for other HAL/Fujitsu) CPUs. For the most part this consists of fleshing out the MMU and cache handling, it doesn't add pmap optimizations possible with these CPU, yet, though. With these changes FreeBSD runs stable on Fujitsu Siemens PRIMEPOWER 250 and likely also other models based on SPARC64 V like 450, 650 and 850. Thanks go to Michael Moll for providing access to a PRIMEPOWER 250. --- sys/boot/sparc64/loader/main.c | 8 +++-- sys/conf/files.sparc64 | 1 + sys/sparc64/include/asi.h | 7 ++++- sys/sparc64/include/cache.h | 4 +++ sys/sparc64/include/mcntl.h | 62 ++++++++++++++++++++++++++++++++++++++ sys/sparc64/sparc64/cache.c | 20 +++++++++++-- sys/sparc64/sparc64/cheetah.c | 15 ++++++++-- sys/sparc64/sparc64/identcpu.c | 24 +++++++++++++-- sys/sparc64/sparc64/machdep.c | 6 +++- sys/sparc64/sparc64/mp_locore.S | 22 +++++++++----- sys/sparc64/sparc64/mp_machdep.c | 9 ++++-- sys/sparc64/sparc64/pmap.c | 9 +++--- sys/sparc64/sparc64/tick.c | 9 ++++-- sys/sparc64/sparc64/zeus.c | 65 ++++++++++++++++++++++++++++++++++++++++ 14 files changed, 232 insertions(+), 29 deletions(-) create mode 100644 sys/sparc64/include/mcntl.h create mode 100644 sys/sparc64/sparc64/zeus.c diff --git a/sys/boot/sparc64/loader/main.c b/sys/boot/sparc64/loader/main.c index 2afbfee..b3e7908 100644 --- a/sys/boot/sparc64/loader/main.c +++ b/sys/boot/sparc64/loader/main.c @@ -451,7 +451,8 @@ dtlb_va_to_pa_sun4u(vm_offset_t va) reg = dtlb_get_data_sun4u(i); wrpr(pstate, pstate, 0); reg >>= TD_PA_SHIFT; - if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) return (reg & TD_PA_CH_MASK); return (reg & TD_PA_SF_MASK); } @@ -474,7 +475,8 @@ itlb_va_to_pa_sun4u(vm_offset_t va) reg = itlb_get_data_sun4u(i); wrpr(pstate, pstate, 0); reg >>= TD_PA_SHIFT; - if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) return (reg & TD_PA_CH_MASK); return (reg & TD_PA_SF_MASK); } @@ -696,6 +698,7 @@ cpu_cpuid_prop_sun4u(void) switch (cpu_impl) { case CPU_IMPL_SPARC64: + case CPU_IMPL_SPARC64V: case CPU_IMPL_ULTRASPARCI: case CPU_IMPL_ULTRASPARCII: case CPU_IMPL_ULTRASPARCIIi: @@ -720,6 +723,7 @@ cpu_get_mid_sun4u(void) switch (cpu_impl) { case CPU_IMPL_SPARC64: + case CPU_IMPL_SPARC64V: case CPU_IMPL_ULTRASPARCI: case CPU_IMPL_ULTRASPARCII: case CPU_IMPL_ULTRASPARCIIi: diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64 index 63ee2c5..3a0620a 100644 --- a/sys/conf/files.sparc64 +++ b/sys/conf/files.sparc64 @@ -138,3 +138,4 @@ sparc64/sparc64/tsb.c standard sparc64/sparc64/uio_machdep.c standard sparc64/sparc64/upa.c optional creator sparc64/sparc64/vm_machdep.c standard +sparc64/sparc64/zeus.c standard diff --git a/sys/sparc64/include/asi.h b/sys/sparc64/include/asi.h index 90dc3f3..e5769c1 100644 --- a/sys/sparc64/include/asi.h +++ b/sys/sparc64/include/asi.h @@ -82,7 +82,10 @@ #define ASI_DCACHE_SNOOP_TAG 0x44 /* US-III Cu */ /* Named ASI_DCUCR on US-III, but is mostly identical except for added bits. */ -#define ASI_LSU_CTL_REG 0x45 +#define ASI_LSU_CTL_REG 0x45 /* US only */ + +#define ASI_MCNTL 0x45 /* SPARC64 only */ +#define AA_MCNTL 0x08 #define ASI_DCACHE_DATA 0x46 #define ASI_DCACHE_TAG 0x47 @@ -167,6 +170,8 @@ #define ASI_ICACHE_PRE_DECODE 0x6e /* US-I, II */ #define ASI_ICACHE_PRE_NEXT_FIELD 0x6f /* US-I, II */ +#define ASI_FLUSH_L1I 0x67 /* SPARC64 only */ + #define ASI_BLK_AUIP 0x70 #define ASI_BLK_AIUS 0x71 diff --git a/sys/sparc64/include/cache.h b/sys/sparc64/include/cache.h index 9c4804b..29bff69 100644 --- a/sys/sparc64/include/cache.h +++ b/sys/sparc64/include/cache.h @@ -113,6 +113,10 @@ extern cache_flush_t *cache_flush; extern dcache_page_inval_t *dcache_page_inval; extern icache_page_inval_t *icache_page_inval; +cache_flush_t zeus_cache_flush; +dcache_page_inval_t zeus_dcache_page_inval; +icache_page_inval_t zeus_icache_page_inval; + #endif /* KERNEL */ #endif /* !LOCORE */ diff --git a/sys/sparc64/include/mcntl.h b/sys/sparc64/include/mcntl.h new file mode 100644 index 0000000..e9483c0 --- /dev/null +++ b/sys/sparc64/include/mcntl.h @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2010 Marius Strobl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _MACHINE_MCNTL_H +#define _MACHINE_MCNTL_H + +/* + * Definitions for the SPARC64 V, VI, VII and VIIIfx Memory Control Register + */ +#define MCNTL_JPS1_TSBP (1UL << 8) + +#define MCNTL_RMD_SHIFT 12 +#define MCNTL_RMD_BITS 2 +#define MCNTL_RMD_MASK \ + (((1UL << MCNTL_RMD_BITS) - 1) << MCNTL_RMD_SHIFT) +#define MCNTL_RMD_FULL (0UL << MCNTL_RMD_SHIFT) +#define MCNTL_RMD_1024 (2UL << MCNTL_RMD_SHIFT) +#define MCNTL_RMD_512 (3UL << MCNTL_RMD_SHIFT) + +#define MCNTL_FW_FDTLB (1UL << 14) +#define MCNTL_FW_FITLB (1UL << 15) +#define MCNTL_NC_CACHE (1UL << 16) + +/* The following bits are valid for the SPARC64 VI, VII and VIIIfx only. */ +#define MCNTL_MPG_SDTLB (1UL << 6) +#define MCNTL_MPG_SITLB (1UL << 7) + +/* The following bits are valid for the SPARC64 VIIIfx only. */ +#define MCNTL_HPF_SHIFT 18 +#define MCNTL_HPF_BITS 2 +#define MCNTL_HPF_MASK \ + (((1UL << MCNTL_HPF_BITS) - 1) << MCNTL_HPF_SHIFT) +#define MCNTL_HPF_STRONG (0UL << MCNTL_HPF_SHIFT) +#define MCNTL_HPF_NOT (1UL << MCNTL_HPF_SHIFT) +#define MCNTL_HPF_WEAK (2UL << MCNTL_HPF_SHIFT) + +#endif /* _MACHINE_MCNTL_H */ diff --git a/sys/sparc64/sparc64/cache.c b/sys/sparc64/sparc64/cache.c index 8cb8dee..a3c6119 100644 --- a/sys/sparc64/sparc64/cache.c +++ b/sys/sparc64/sparc64/cache.c @@ -141,7 +141,12 @@ cache_init(struct pcpu *pcpu) if ((pcpu->pc_cache.dc_size & ~(1UL << (ffs(pcpu->pc_cache.dc_size) - 1))) != 0) panic("cache_init: D$ size not a power of 2"); - if (((pcpu->pc_cache.dc_size / pcpu->pc_cache.dc_assoc) / + /* + * For CPUs which don't support unaliasing in hardware ensure that + * the data cache doesn't have too many virtual colors. + */ + if (pcpu->pc_impl != CPU_IMPL_SPARC64V && + ((pcpu->pc_cache.dc_size / pcpu->pc_cache.dc_assoc) / PAGE_SIZE) != DCACHE_COLORS) panic("cache_init: too many D$ colors"); set = pcpu->pc_cache.ec_size / pcpu->pc_cache.ec_assoc; @@ -155,12 +160,21 @@ cache_init(struct pcpu *pcpu) icache_page_inval = cheetah_icache_page_inval; tlb_flush_nonlocked = cheetah_tlb_flush_nonlocked; tlb_flush_user = cheetah_tlb_flush_user; - } else { + } else if (pcpu->pc_impl == CPU_IMPL_SPARC64V) { + cache_enable = cheetah_cache_enable; + cache_flush = zeus_cache_flush; + dcache_page_inval = zeus_dcache_page_inval; + icache_page_inval = zeus_icache_page_inval; + tlb_flush_nonlocked = cheetah_tlb_flush_nonlocked; + tlb_flush_user = cheetah_tlb_flush_user; + } else if (pcpu->pc_impl >= CPU_IMPL_ULTRASPARCI && + pcpu->pc_impl < CPU_IMPL_ULTRASPARCIII) { cache_enable = spitfire_cache_enable; cache_flush = spitfire_cache_flush; dcache_page_inval = spitfire_dcache_page_inval; icache_page_inval = spitfire_icache_page_inval; tlb_flush_nonlocked = spitfire_tlb_flush_nonlocked; tlb_flush_user = spitfire_tlb_flush_user; - } + } else + panic("cache_init: unknown CPU"); } diff --git a/sys/sparc64/sparc64/cheetah.c b/sys/sparc64/sparc64/cheetah.c index 8366187..99d38c9 100644 --- a/sys/sparc64/sparc64/cheetah.c +++ b/sys/sparc64/sparc64/cheetah.c @@ -39,11 +39,13 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -52,7 +54,8 @@ __FBSDID("$FreeBSD$"); #define CHEETAH_ICACHE_TAG_LOWER 0x30 /* - * CPU-specific initialization + * CPU-specific initialization - this is used for both the Sun Cheetah and + * later as well as the Fujitsu Zeus and later CPUs. */ void cheetah_init(u_int cpu_impl) @@ -75,6 +78,14 @@ cheetah_init(u_int cpu_impl) stxa(AA_IMMU_TSB_NEXT_REG, ASI_IMMU, 0); membar(Sync); + if (cpu_impl == CPU_IMPL_SPARC64V) { + /* Ensure MCNTL_JPS1_TSBP is 0. */ + val = ldxa(AA_MCNTL, ASI_MCNTL); + val &= ~MCNTL_JPS1_TSBP; + stxa(AA_MCNTL, ASI_MCNTL, val); + return; + } + /* * Configure the first large dTLB to hold 4MB pages (e.g. for direct * mappings) for all three contexts and ensure the second one is set @@ -207,7 +218,7 @@ cheetah_dcache_page_inval(vm_paddr_t spa) * consistency is maintained by hardware. */ void -cheetah_icache_page_inval(vm_paddr_t pa) +cheetah_icache_page_inval(vm_paddr_t pa __unused) { } diff --git a/sys/sparc64/sparc64/identcpu.c b/sys/sparc64/sparc64/identcpu.c index 0b73151..455aa67 100644 --- a/sys/sparc64/sparc64/identcpu.c +++ b/sys/sparc64/sparc64/identcpu.c @@ -41,7 +41,7 @@ cpu_identify(u_long vers, u_int freq, u_int id) switch (VER_MANUF(vers)) { case 0x04: - manus = "HAL"; + manus = "HAL/Fujitsu"; break; case 0x13: case 0x17: @@ -57,6 +57,27 @@ cpu_identify(u_long vers, u_int freq, u_int id) case CPU_IMPL_SPARC64: impls = "SPARC64"; break; + case CPU_IMPL_SPARC64II: + impls = "SPARC64-II"; + break; + case CPU_IMPL_SPARC64III: + impls = "SPARC64-III"; + break; + case CPU_IMPL_SPARC64IV: + impls = "SPARC64-IV"; + break; + case CPU_IMPL_SPARC64V: + impls = "SPARC64-V"; + break; + case CPU_IMPL_SPARC64VI: + impls = "SPARC64-VI"; + break; + case CPU_IMPL_SPARC64VII: + impls = "SPARC64-VII"; + break; + case CPU_IMPL_SPARC64VIIIfx: + impls = "SPARC64-VIIIfx"; + break; case CPU_IMPL_ULTRASPARCI: impls = "UltraSparc-I"; break; @@ -67,7 +88,6 @@ cpu_identify(u_long vers, u_int freq, u_int id) impls = "UltraSparc-IIi"; break; case CPU_IMPL_ULTRASPARCIIe: - /* V9 Manual says `UltraSparc-e'. I assume this is wrong. */ impls = "UltraSparc-IIe"; break; case CPU_IMPL_ULTRASPARCIII: diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c index c904060..eda2e01 100644 --- a/sys/sparc64/sparc64/machdep.c +++ b/sys/sparc64/sparc64/machdep.c @@ -276,6 +276,7 @@ cpu_cpuid_prop(u_int cpu_impl) switch (cpu_impl) { case CPU_IMPL_SPARC64: + case CPU_IMPL_SPARC64V: case CPU_IMPL_ULTRASPARCI: case CPU_IMPL_ULTRASPARCII: case CPU_IMPL_ULTRASPARCIIi: @@ -300,6 +301,7 @@ cpu_get_mid(u_int cpu_impl) switch (cpu_impl) { case CPU_IMPL_SPARC64: + case CPU_IMPL_SPARC64V: case CPU_IMPL_ULTRASPARCI: case CPU_IMPL_ULTRASPARCII: case CPU_IMPL_ULTRASPARCIIi: @@ -343,7 +345,8 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) /* * Do CPU-specific initialization. */ - if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) cheetah_init(cpu_impl); /* @@ -491,6 +494,7 @@ sparc64_init(caddr_t mdp, u_long o1, u_long o2, u_long o3, ofw_vec_t *vec) if (cpu_use_vis) { switch (cpu_impl) { case CPU_IMPL_SPARC64: + case CPU_IMPL_SPARC64V: case CPU_IMPL_ULTRASPARCI: case CPU_IMPL_ULTRASPARCII: case CPU_IMPL_ULTRASPARCIIi: diff --git a/sys/sparc64/sparc64/mp_locore.S b/sys/sparc64/sparc64/mp_locore.S index bd4fd13..e78b4b9 100644 --- a/sys/sparc64/sparc64/mp_locore.S +++ b/sys/sparc64/sparc64/mp_locore.S @@ -200,19 +200,25 @@ ENTRY(mp_startup) srlx %l1, VER_IMPL_SHIFT, %l1 sll %l1, VER_IMPL_SIZE, %l1 srl %l1, VER_IMPL_SIZE, %l1 + cmp %l1, CPU_IMPL_SPARC64V + bl %icc, 4f + nop + cmp %l1, CPU_IMPL_ULTRASPARCI + bl %icc, 2f + nop cmp %l1, CPU_IMPL_ULTRASPARCIII bl %icc, 3f nop - mov CPU_STICKSYNC, %l2 +2: mov CPU_STICKSYNC, %l2 membar #StoreLoad stw %l2, [%l0 + CSA_STATE] -2: ldx [%l0 + CSA_STICK], %l2 - brz %l2, 2b +3: ldx [%l0 + CSA_STICK], %l2 + brz %l2, 3b nop wr %l2, 0, %asr24 -3: call cpu_get_mid +4: call cpu_get_mid mov %l1, %o0 /* @@ -225,9 +231,9 @@ ENTRY(mp_startup) /* * Wait till its our turn to bootstrap. */ -4: lduw [%l0 + CSA_MID], %l1 +5: lduw [%l0 + CSA_MID], %l1 cmp %l1, %o0 - bne %xcc, 4b + bne %xcc, 5b nop add %l0, CSA_TTES, %l1 @@ -236,7 +242,7 @@ ENTRY(mp_startup) /* * Map the per-CPU pages. */ -5: sllx %l2, TTE_SHIFT, %l3 +6: sllx %l2, TTE_SHIFT, %l3 add %l1, %l3, %l3 ldx [%l3 + TTE_VPN], %l4 @@ -251,7 +257,7 @@ ENTRY(mp_startup) add %l2, 1, %l2 cmp %l2, PCPU_PAGES - bne %xcc, 5b + bne %xcc, 6b nop /* diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c index ce66a4b..4281204 100644 --- a/sys/sparc64/sparc64/mp_machdep.c +++ b/sys/sparc64/sparc64/mp_machdep.c @@ -164,7 +164,8 @@ mp_init(u_int cpu_impl) if (cpu_impl == CPU_IMPL_ULTRASPARCIIIi || cpu_impl == CPU_IMPL_ULTRASPARCIIIip) isjbus = 1; - if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) cpu_ipi_selected = cheetah_ipi_selected; else cpu_ipi_selected = spitfire_ipi_selected; @@ -315,7 +316,8 @@ ap_start(phandle_t node, u_int mid, u_int cpu_impl) ; membar(StoreLoad); csa->csa_tick = rd(tick); - if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) { + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) { while (csa->csa_state != CPU_STICKSYNC) ; membar(StoreLoad); @@ -411,7 +413,8 @@ cpu_mp_bootstrap(struct pcpu *pc) csa = &cpu_start_args; /* Do CPU-specific initialization. */ - if (pc->pc_impl >= CPU_IMPL_ULTRASPARCIII) + if (pc->pc_impl == CPU_IMPL_SPARC64V || + pc->pc_impl >= CPU_IMPL_ULTRASPARCIII) cheetah_init(pc->pc_impl); /* * Enable the caches. Note that his may include applying workarounds. diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index 5d69c13..4a2853c 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -528,7 +528,8 @@ pmap_bootstrap(u_int cpu_impl) tp->tte_data = ((translations[i].om_tte & ~((TD_SOFT2_MASK << TD_SOFT2_SHIFT) | - (cpu_impl < CPU_IMPL_ULTRASPARCIII ? + (cpu_impl >= CPU_IMPL_ULTRASPARCI && + cpu_impl < CPU_IMPL_ULTRASPARCIII ? (TD_DIAG_SF_MASK << TD_DIAG_SF_SHIFT) : (TD_RSVD_CH_MASK << TD_RSVD_CH_SHIFT)) | (TD_SOFT_MASK << TD_SOFT_SHIFT))) | TD_EXEC) + @@ -704,16 +705,16 @@ retry: if (va >= VM_MIN_DIRECT_ADDRESS) { tp = NULL; m = PHYS_TO_VM_PAGE(TLB_DIRECT_TO_PHYS(va)); - (void)vm_page_pa_tryrelock(pm, TLB_DIRECT_TO_PHYS(va), &pa); + (void)vm_page_pa_tryrelock(pm, TLB_DIRECT_TO_PHYS(va), + &pa); vm_page_hold(m); } else { tp = tsb_kvtotte(va); if ((tp->tte_data & TD_V) == 0) tp = NULL; } - } else { + } else tp = tsb_tte_lookup(pm, va); - } if (tp != NULL && ((tp->tte_data & TD_SW) || (prot & VM_PROT_WRITE) == 0)) { if (vm_page_pa_tryrelock(pm, TTE_GET_PA(tp), &pa)) diff --git a/sys/sparc64/sparc64/tick.c b/sys/sparc64/sparc64/tick.c index 1a38013..041faa0 100644 --- a/sys/sparc64/sparc64/tick.c +++ b/sys/sparc64/sparc64/tick.c @@ -120,7 +120,8 @@ cpu_initclocks(void) */ } else { clock = PCPU_GET(clock); - intr_setup(PIL_TICK, PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ? + intr_setup(PIL_TICK, PCPU_GET(impl) >= CPU_IMPL_ULTRASPARCI && + PCPU_GET(impl) < CPU_IMPL_ULTRASPARCIII ? tick_hardclock_bbwar : tick_hardclock, -1, NULL, NULL); set_cputicker(tick_cputicks, clock, 0); } @@ -325,7 +326,8 @@ void tick_clear(u_int cpu_impl) { - if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) wrstick(0, 0); wrpr(tick, 0, 0); } @@ -334,7 +336,8 @@ void tick_stop(u_int cpu_impl) { - if (cpu_impl >= CPU_IMPL_ULTRASPARCIII) + if (cpu_impl == CPU_IMPL_SPARC64V || + cpu_impl >= CPU_IMPL_ULTRASPARCIII) wrstickcmpr(1L << 63, 0); wrtickcmpr(1L << 63, 0); } diff --git a/sys/sparc64/sparc64/zeus.c b/sys/sparc64/sparc64/zeus.c new file mode 100644 index 0000000..a3dc4e5 --- /dev/null +++ b/sys/sparc64/sparc64/zeus.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2010 Marius Strobl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include +#include + +/* + * Flush all lines from the level 1 caches. + */ +void +zeus_cache_flush(void) +{ + + stxa_sync(0, ASI_FLUSH_L1I, 0); +} + +/* + * Flush a physical page from the data cache. Data cache consistency is + * maintained by hardware. + */ +void +zeus_dcache_page_inval(vm_paddr_t spa __unused) +{ + +} + +/* + * Flush a physical page from the intsruction cache. Instruction cache + * consistency is maintained by hardware. + */ +void +zeus_icache_page_inval(vm_paddr_t pa __unused) +{ + +} -- cgit v1.1 From 97e3b0ccbfdd08e675ae07586a31bd75fc8edde0 Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 20:24:25 +0000 Subject: Simplify vm_fault(). The introduction of the new page lock renders a bit of cleverness by vm_fault() to avoid repeatedly releasing and reacquiring the page queues lock pointless. Reviewed by: kib, kmacy --- sys/vm/vm_fault.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 5ee4ab4..f925594 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -215,7 +215,7 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fault_type, { vm_prot_t prot; int is_first_object_locked, result; - boolean_t are_queues_locked, growstack, wired; + boolean_t growstack, wired; int map_generation; vm_object_t next_object; vm_page_t marray[VM_FAULT_READ]; @@ -478,7 +478,6 @@ readrest: else firstpindex = fs.first_pindex - 2 * VM_FAULT_READ; - are_queues_locked = FALSE; /* * note: partially valid pages cannot be * included in the lookahead - NFS piecemeal @@ -495,17 +494,11 @@ readrest: if (mt->busy || (mt->oflags & VPO_BUSY)) continue; - if (!are_queues_locked) { - are_queues_locked = TRUE; - vm_page_lock(mt); - vm_page_lock_queues(); - } else { - vm_page_unlock_queues(); - vm_page_lock(mt); - vm_page_lock_queues(); - } + vm_page_lock(mt); + vm_page_lock_queues(); if (mt->hold_count || mt->wire_count) { + vm_page_unlock_queues(); vm_page_unlock(mt); continue; } @@ -515,10 +508,9 @@ readrest: } else { vm_page_cache(mt); } + vm_page_unlock_queues(); vm_page_unlock(mt); } - if (are_queues_locked) - vm_page_unlock_queues(); ahead += behind; behind = 0; } -- cgit v1.1 From 195c62fe8294da22cc552029487344d2da10624b Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 20:46:17 +0000 Subject: Defer the acquisition of the page and page queues locks in vm_pageout_object_deactivate_pages(). --- sys/vm/vm_pageout.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 39a06f8..3ce8a69 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -540,6 +540,7 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired) for (object = first_object;; object = backing_object) { if (pmap_resident_count(pmap) <= desired) goto unlock_return; + VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); if (object->type == OBJT_PHYS || object->paging_in_progress) goto unlock_return; @@ -551,19 +552,18 @@ vm_pageout_object_deactivate_pages(pmap, first_object, desired) */ p = TAILQ_FIRST(&object->memq); while (p != NULL) { - vm_page_lock(p); - vm_page_lock_queues(); - if (pmap_resident_count(pmap) <= desired) { - vm_page_unlock_queues(); - vm_page_unlock(p); + if (pmap_resident_count(pmap) <= desired) goto unlock_return; - } next = TAILQ_NEXT(p, listq); + if ((p->oflags & VPO_BUSY) != 0 || p->busy != 0) { + p = next; + continue; + } + vm_page_lock(p); + vm_page_lock_queues(); cnt.v_pdpages++; if (p->wire_count != 0 || p->hold_count != 0 || - p->busy != 0 || - (p->oflags & VPO_BUSY) || !pmap_page_exists_quick(pmap, p)) { vm_page_unlock_queues(); vm_page_unlock(p); -- cgit v1.1 From 205f9143e605ffd0bbeb8faccad2186ea32a245d Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 21:04:59 +0000 Subject: Eliminate an assignment that was made redundant by r207410. --- sys/vm/vm_pageout.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 3ce8a69..9921a84 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -1370,8 +1370,6 @@ vm_pageout_page_stats() ("vm_pageout_page_stats: page %p isn't active", m)); next = TAILQ_NEXT(m, pageq); - object = m->object; - if ((m->flags & PG_MARKER) != 0) { m = next; continue; -- cgit v1.1 From 5bdbfdef5238d07cbc7c88c8cd59830932c96624 Mon Sep 17 00:00:00 2001 From: mjacob Date: Sun, 2 May 2010 22:48:27 +0000 Subject: Print IR_RESYNC updates informatively. Obtained from: pluknet MFC after: 1 week --- sys/dev/mpt/mpt_cam.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c index 56ea3e0..39b57de 100644 --- a/sys/dev/mpt/mpt_cam.c +++ b/sys/dev/mpt/mpt_cam.c @@ -2575,6 +2575,10 @@ mpt_cam_event(struct mpt_softc *mpt, request_t *req, CAMLOCK_2_MPTLOCK(mpt); break; } + case MPI_EVENT_IR_RESYNC_UPDATE: + mpt_prt(mpt, "IR resync update %d completed\n", + (data0 >> 16) & 0xff); + break; case MPI_EVENT_EVENT_CHANGE: case MPI_EVENT_INTEGRATED_RAID: case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: -- cgit v1.1 From fbe19e5e155fcfd93567ff0a4105982000d15d0e Mon Sep 17 00:00:00 2001 From: alc Date: Sun, 2 May 2010 23:33:10 +0000 Subject: Add page lock assertions where we access the page's hold_count. --- sys/vm/vm_page.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index e73586a..59f8226 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1657,6 +1657,7 @@ vm_page_try_to_cache(vm_page_t m) { mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED); if (m->dirty || m->hold_count || m->busy || m->wire_count || (m->oflags & VPO_BUSY) || (m->flags & PG_UNMANAGED)) { @@ -1680,6 +1681,7 @@ vm_page_try_to_free(vm_page_t m) { mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); if (m->object != NULL) VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED); if (m->dirty || m->hold_count || m->busy || m->wire_count || @@ -1707,6 +1709,7 @@ vm_page_cache(vm_page_t m) vm_page_t root; mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); object = m->object; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); if ((m->flags & PG_UNMANAGED) || (m->oflags & VPO_BUSY) || m->busy || -- cgit v1.1 From 46340f07933ebae5d0723021a44679b64cb1013b Mon Sep 17 00:00:00 2001 From: yongari Date: Mon, 3 May 2010 00:56:26 +0000 Subject: Fix wrong dma tag usage. Previously it used TX descriptor ring dma tag which should be TX mbuf dma tag. Reported by: xclin cs dot nctu dot edu dot tw > --- sys/dev/sge/if_sge.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index 37476a2..43b7022 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -1421,7 +1421,7 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head) } *m_head = m; } - error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_tx_tag, map, + error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, map, *m_head, txsegs, &nsegs, 0); if (error != 0) { m_freem(*m_head); @@ -1430,10 +1430,11 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head) } /* Check descriptor overrun. */ if (sc->sge_cdata.sge_tx_cnt + nsegs >= SGE_TX_RING_CNT) { - bus_dmamap_unload(sc->sge_cdata.sge_tx_tag, map); + bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, map); return (ENOBUFS); } - bus_dmamap_sync(sc->sge_cdata.sge_tx_tag, map, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, map, + BUS_DMASYNC_PREWRITE); cflags = 0; if ((*m_head)->m_pkthdr.csum_flags & CSUM_IP) -- cgit v1.1 From 387e15c45aad8ee988d094eebcf76078a1a4752c Mon Sep 17 00:00:00 2001 From: alc Date: Mon, 3 May 2010 05:41:50 +0000 Subject: This is the first step in transitioning responsibility for synchronizing access to the page's wire_count from the page queues lock to the page lock. Submitted by: kmacy --- sys/kern/uipc_cow.c | 4 ++++ sys/kern/uipc_syscalls.c | 4 ++++ sys/net/bpf_zerocopy.c | 2 ++ 3 files changed, 10 insertions(+) diff --git a/sys/kern/uipc_cow.c b/sys/kern/uipc_cow.c index 5c0dcd2..88a5625 100644 --- a/sys/kern/uipc_cow.c +++ b/sys/kern/uipc_cow.c @@ -80,6 +80,7 @@ socow_iodone(void *addr, void *args) pp = sf_buf_page(sf); sf_buf_free(sf); /* remove COW mapping */ + vm_page_lock(pp); vm_page_lock_queues(); vm_page_cowclear(pp); vm_page_unwire(pp, 0); @@ -91,6 +92,7 @@ socow_iodone(void *addr, void *args) if (pp->wire_count == 0 && pp->object == NULL) vm_page_free(pp); vm_page_unlock_queues(); + vm_page_unlock(pp); socow_stats.iodone++; } @@ -149,6 +151,7 @@ socow_setup(struct mbuf *m0, struct uio *uio) */ sf = sf_buf_alloc(pp, SFB_CATCH); if (!sf) { + vm_page_lock(pp); vm_page_lock_queues(); vm_page_cowclear(pp); vm_page_unwire(pp, 0); @@ -160,6 +163,7 @@ socow_setup(struct mbuf *m0, struct uio *uio) if (pp->wire_count == 0 && pp->object == NULL) vm_page_free(pp); vm_page_unlock_queues(); + vm_page_unlock(pp); socow_stats.fail_sf_buf++; return(0); } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 3271235..a137875 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1715,6 +1715,7 @@ sf_buf_mext(void *addr, void *args) m = sf_buf_page(args); sf_buf_free(args); + vm_page_lock(m); vm_page_lock_queues(); vm_page_unwire(m, 0); /* @@ -1725,6 +1726,7 @@ sf_buf_mext(void *addr, void *args) if (m->wire_count == 0 && m->object == NULL) vm_page_free(m); vm_page_unlock_queues(); + vm_page_unlock(m); if (addr == NULL) return; sfs = addr; @@ -2136,6 +2138,7 @@ retry_space: if ((sf = sf_buf_alloc(pg, (mnw ? SFB_NOWAIT : SFB_CATCH))) == NULL) { mbstat.sf_allocfail++; + vm_page_lock(pg); vm_page_lock_queues(); vm_page_unwire(pg, 0); /* @@ -2144,6 +2147,7 @@ retry_space: if (pg->wire_count == 0 && pg->object == NULL) vm_page_free(pg); vm_page_unlock_queues(); + vm_page_unlock(pg); error = (mnw ? EAGAIN : EINTR); break; } diff --git a/sys/net/bpf_zerocopy.c b/sys/net/bpf_zerocopy.c index 3cf4b8d..5ca6978 100644 --- a/sys/net/bpf_zerocopy.c +++ b/sys/net/bpf_zerocopy.c @@ -112,11 +112,13 @@ static void zbuf_page_free(vm_page_t pp) { + vm_page_lock(pp); vm_page_lock_queues(); vm_page_unwire(pp, 0); if (pp->wire_count == 0 && pp->object == NULL) vm_page_free(pp); vm_page_unlock_queues(); + vm_page_unlock(pp); } /* -- cgit v1.1 From dda80c9587fba3b3c842e555ef7d08ed0949a600 Mon Sep 17 00:00:00 2001 From: alc Date: Mon, 3 May 2010 07:00:50 +0000 Subject: Assert that the page queues lock is held in vm_page_remove() and vm_page_unwire() only if the page is managed, i.e., pageable. --- sys/vm/vm_page.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 59f8226..acec3b7 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -790,6 +790,8 @@ vm_page_remove(vm_page_t m) vm_object_t object; vm_page_t root; + if ((m->flags & PG_UNMANAGED) == 0) + mtx_assert(&vm_page_queue_mtx, MA_OWNED); if ((object = m->object) == NULL) return; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); @@ -797,7 +799,6 @@ vm_page_remove(vm_page_t m) m->oflags &= ~VPO_BUSY; vm_page_flash(m); } - mtx_assert(&vm_page_queue_mtx, MA_OWNED); /* * Now remove from the object's list of backed pages. @@ -1586,7 +1587,8 @@ void vm_page_unwire(vm_page_t m, int activate) { - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + if ((m->flags & PG_UNMANAGED) == 0) + mtx_assert(&vm_page_queue_mtx, MA_OWNED); if (m->flags & PG_FICTITIOUS) return; if (m->wire_count > 0) { -- cgit v1.1 From 34bfab021b5442c5389d345f46ff6ff111e69da8 Mon Sep 17 00:00:00 2001 From: alc Date: Mon, 3 May 2010 07:08:16 +0000 Subject: The pages allocated by kmem_alloc_attr() and kmem_malloc() are unmanaged. Consequently, neither the page lock nor the page queues lock is needed to unwire and free them. --- sys/vm/vm_contig.c | 4 ---- sys/vm/vm_kern.c | 4 ---- 2 files changed, 8 deletions(-) diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index e6a9b78..c1c8618 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -268,11 +268,7 @@ retry: i -= PAGE_SIZE; m = vm_page_lookup(object, OFF_TO_IDX(offset + i)); - vm_page_lock(m); - vm_page_lock_queues(); vm_page_free(m); - vm_page_unlock_queues(); - vm_page_unlock(m); } VM_OBJECT_UNLOCK(object); vm_map_delete(map, addr, addr + size); diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index ead6d0d..95a4e9d 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -380,12 +380,8 @@ retry: i -= PAGE_SIZE; m = vm_page_lookup(kmem_object, OFF_TO_IDX(offset + i)); - vm_page_lock(m); - vm_page_lock_queues(); vm_page_unwire(m, 0); vm_page_free(m); - vm_page_unlock_queues(); - vm_page_unlock(m); } VM_OBJECT_UNLOCK(kmem_object); vm_map_delete(map, addr, addr + size); -- cgit v1.1 From 305cdfaf86fcdb4aa91519ed8096ab361cb28970 Mon Sep 17 00:00:00 2001 From: mm Date: Mon, 3 May 2010 07:32:24 +0000 Subject: Implement the no_user_check option to pam_krb5. This option is available in the Linux implementation of pam_krb5 and allows to authorize a user not known to the local system. Ccache is not used as we don't have a secure uid/gid for the cache file. Usable for authentication of external kerberos users (e.g Active Directory) via PAM from applications like Cyrus saslauthd, PHP or perl. PR: bin/146186 Submitted by: myself Approved by: deplhij (mentor) MFC after: 2 weeks --- lib/libpam/modules/pam_krb5/pam_krb5.8 | 4 ++++ lib/libpam/modules/pam_krb5/pam_krb5.c | 9 ++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.8 b/lib/libpam/modules/pam_krb5/pam_krb5.8 index 3e0db91..a182e62e 100644 --- a/lib/libpam/modules/pam_krb5/pam_krb5.8 +++ b/lib/libpam/modules/pam_krb5/pam_krb5.8 @@ -108,6 +108,10 @@ and .Ql %p , to designate the current process ID; can be used in .Ar name . +.It Cm no_user_check +Do not verify if a user exists on the local system. This option implies the +.Cm no_ccache +option because there is no secure local uid/gid for the cache file. .El .Ss Kerberos 5 Account Management Module The Kerberos 5 account management component diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.c b/lib/libpam/modules/pam_krb5/pam_krb5.c index b56e0a3..9623a17 100644 --- a/lib/libpam/modules/pam_krb5/pam_krb5.c +++ b/lib/libpam/modules/pam_krb5/pam_krb5.c @@ -89,6 +89,7 @@ static void compat_free_data_contents(krb5_context, krb5_data *); #define PAM_OPT_DEBUG "debug" #define PAM_OPT_FORWARDABLE "forwardable" #define PAM_OPT_NO_CCACHE "no_ccache" +#define PAM_OPT_NO_USER_CHECK "no_user_check" #define PAM_OPT_REUSE_CCACHE "reuse_ccache" /* @@ -194,6 +195,10 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, PAM_LOG("Got password"); + if (openpam_get_option(pamh, PAM_OPT_NO_USER_CHECK)) + PAM_LOG("Skipping local user check"); + else { + /* Verify the local user exists (AFTER getting the password) */ if (strchr(user, '@')) { /* get a local account name for this principal */ @@ -221,6 +226,7 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, } PAM_LOG("Done getpwnam()"); + } /* Get a TGT */ memset(&creds, 0, sizeof(krb5_creds)); @@ -366,7 +372,8 @@ pam_sm_setcred(pam_handle_t *pamh, int flags, return (PAM_SERVICE_ERR); /* If a persistent cache isn't desired, stop now. */ - if (openpam_get_option(pamh, PAM_OPT_NO_CCACHE)) + if (openpam_get_option(pamh, PAM_OPT_NO_CCACHE) || + openpam_get_option(pamh, PAM_OPT_NO_USER_CHECK)) return (PAM_SUCCESS); PAM_LOG("Establishing credentials"); -- cgit v1.1 From 213eac1f2c265b68ddb7cb7bbcb289f8e054c161 Mon Sep 17 00:00:00 2001 From: sobomax Date: Mon, 3 May 2010 07:32:50 +0000 Subject: Add new tunable 'net.link.ifqmaxlen' to set default send interface queue length. The default value for this parameter is 50, which is quite low for many of today's uses and the only way to modify this parameter right now is to edit if_var.h file. Also add read-only sysctl with the same name, so that it's possible to retrieve the current value. MFC after: 1 month --- sys/arm/at91/if_ate.c | 4 ++-- sys/arm/xscale/ixp425/if_npe.c | 2 +- sys/dev/ae/if_ae.c | 2 +- sys/dev/an/if_an.c | 4 ++-- sys/dev/ath/if_ath.c | 4 ++-- sys/dev/bwi/if_bwi.c | 4 ++-- sys/dev/bwn/if_bwn.c | 4 ++-- sys/dev/ce/if_ce.c | 8 ++++---- sys/dev/cm/smc90cx6.c | 2 +- sys/dev/cp/if_cp.c | 4 ++-- sys/dev/cs/if_cs.c | 2 +- sys/dev/ctau/if_ct.c | 4 ++-- sys/dev/cx/if_cx.c | 4 ++-- sys/dev/cxgb/cxgb_main.c | 2 +- sys/dev/ed/if_ed.c | 4 ++-- sys/dev/ep/if_ep.c | 4 ++-- sys/dev/ex/if_ex.c | 2 +- sys/dev/fe/if_fe.c | 2 +- sys/dev/ie/if_ie.c | 2 +- sys/dev/iicbus/if_ic.c | 2 +- sys/dev/ipw/if_ipw.c | 4 ++-- sys/dev/iwi/if_iwi.c | 4 ++-- sys/dev/iwn/if_iwn.c | 4 ++-- sys/dev/le/lance.c | 4 ++-- sys/dev/malo/if_malo.c | 4 ++-- sys/dev/mwl/if_mwl.c | 4 ++-- sys/dev/my/if_my.c | 4 ++-- sys/dev/nxge/if_nxge.c | 2 +- sys/dev/pdq/pdq_ifsubr.c | 2 +- sys/dev/ppbus/if_plip.c | 2 +- sys/dev/ral/rt2560.c | 4 ++-- sys/dev/ral/rt2661.c | 4 ++-- sys/dev/sbni/if_sbni.c | 2 +- sys/dev/smc/if_smc.c | 2 +- sys/dev/sn/if_sn.c | 4 ++-- sys/dev/snc/dp83932.c | 2 +- sys/dev/usb/net/uhso.c | 4 ++-- sys/dev/usb/net/usb_ethernet.c | 4 ++-- sys/dev/usb/wlan/if_rum.c | 4 ++-- sys/dev/usb/wlan/if_run.c | 4 ++-- sys/dev/usb/wlan/if_uath.c | 4 ++-- sys/dev/usb/wlan/if_upgt.c | 2 +- sys/dev/usb/wlan/if_ural.c | 4 ++-- sys/dev/usb/wlan/if_urtw.c | 4 ++-- sys/dev/usb/wlan/if_zyd.c | 2 +- sys/dev/vx/if_vx.c | 2 +- sys/dev/wi/if_wi.c | 4 ++-- sys/dev/wl/if_wl.c | 2 +- sys/dev/wpi/if_wpi.c | 4 ++-- sys/dev/xe/if_xe.c | 2 +- sys/mips/adm5120/if_admsw.c | 4 ++-- sys/mips/atheros/if_arge.c | 4 ++-- sys/net/if.c | 4 ++++ sys/net/if_ef.c | 2 +- sys/net/if_gif.c | 2 +- sys/net/if_gre.c | 2 +- sys/net/if_stf.c | 2 +- sys/net80211/ieee80211.c | 4 ++-- sys/netgraph/ng_eiface.c | 2 +- sys/netgraph/ng_fec.c | 2 +- sys/netgraph/ng_iface.c | 4 ++-- sys/netgraph/ng_tty.c | 2 +- sys/pci/if_rl.c | 4 ++-- 63 files changed, 103 insertions(+), 99 deletions(-) diff --git a/sys/arm/at91/if_ate.c b/sys/arm/at91/if_ate.c index 2f6b741..b065482 100644 --- a/sys/arm/at91/if_ate.c +++ b/sys/arm/at91/if_ate.c @@ -272,8 +272,8 @@ ate_attach(device_t dev) ifp->if_ioctl = ateioctl; ifp->if_init = ateinit; ifp->if_baudrate = 10000000; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ifp->if_linkmib = &sc->mibdata; ifp->if_linkmiblen = sizeof(sc->mibdata); diff --git a/sys/arm/xscale/ixp425/if_npe.c b/sys/arm/xscale/ixp425/if_npe.c index 5b605ae..3d8d670 100644 --- a/sys/arm/xscale/ixp425/if_npe.c +++ b/sys/arm/xscale/ixp425/if_npe.c @@ -360,7 +360,7 @@ npe_attach(device_t dev) ifp->if_ioctl = npeioctl; ifp->if_init = npeinit; IFQ_SET_MAXLEN(&ifp->if_snd, sc->txdma.nbuf - 1); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ifp->if_linkmib = &sc->mibdata; ifp->if_linkmiblen = sizeof(sc->mibdata); diff --git a/sys/dev/ae/if_ae.c b/sys/dev/ae/if_ae.c index 68181f4..d2812a4 100644 --- a/sys/dev/ae/if_ae.c +++ b/sys/dev/ae/if_ae.c @@ -378,7 +378,7 @@ ae_attach(device_t dev) ifp->if_init = ae_init; ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING; ifp->if_hwassist = 0; - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); IFQ_SET_READY(&ifp->if_snd); if (pci_find_extcap(dev, PCIY_PMG, &pmc) == 0) { diff --git a/sys/dev/an/if_an.c b/sys/dev/an/if_an.c index 6d9ef96..645fe41 100644 --- a/sys/dev/an/if_an.c +++ b/sys/dev/an/if_an.c @@ -767,8 +767,8 @@ an_attach(struct an_softc *sc, int flags) ifp->if_start = an_start; ifp->if_init = an_init; ifp->if_baudrate = 10000000; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); bzero(sc->an_config.an_nodename, sizeof(sc->an_config.an_nodename)); diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 5847489..15765f2 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -562,8 +562,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ifp->if_start = ath_start; ifp->if_ioctl = ath_ioctl; ifp->if_init = ath_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/bwi/if_bwi.c b/sys/dev/bwi/if_bwi.c index 96c5cc6..724778d 100644 --- a/sys/dev/bwi/if_bwi.c +++ b/sys/dev/bwi/if_bwi.c @@ -461,8 +461,8 @@ bwi_attach(struct bwi_softc *sc) ifp->if_init = bwi_init; ifp->if_ioctl = bwi_ioctl; ifp->if_start = bwi_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); callout_init_mtx(&sc->sc_watchdog_timer, &sc->sc_mtx, 0); diff --git a/sys/dev/bwn/if_bwn.c b/sys/dev/bwn/if_bwn.c index 5ca5098..fd36403 100644 --- a/sys/dev/bwn/if_bwn.c +++ b/sys/dev/bwn/if_bwn.c @@ -1193,8 +1193,8 @@ bwn_attach_pre(struct bwn_softc *sc) ifp->if_init = bwn_init; ifp->if_ioctl = bwn_ioctl; ifp->if_start = bwn_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); return (0); diff --git a/sys/dev/ce/if_ce.c b/sys/dev/ce/if_ce.c index f04fd09..d151b42 100644 --- a/sys/dev/ce/if_ce.c +++ b/sys/dev/ce/if_ce.c @@ -701,9 +701,9 @@ static int ce_attach (device_t dev) #endif continue; } - d->queue.ifq_maxlen = IFQ_MAXLEN; - d->hi_queue.ifq_maxlen = IFQ_MAXLEN; - d->rqueue.ifq_maxlen = IFQ_MAXLEN; + d->queue.ifq_maxlen = ifqmaxlen; + d->hi_queue.ifq_maxlen = ifqmaxlen; + d->rqueue.ifq_maxlen = ifqmaxlen; #if __FreeBSD_version >= 500000 mtx_init (&d->queue.ifq_mtx, "ce_queue", NULL, MTX_DEF); mtx_init (&d->hi_queue.ifq_mtx, "ce_queue_hi", NULL, MTX_DEF); @@ -732,7 +732,7 @@ static int ce_attach (device_t dev) d->ifp->if_ioctl = ce_sioctl; d->ifp->if_start = ce_ifstart; d->ifp->if_init = ce_initialize; - d->rqueue.ifq_maxlen = IFQ_MAXLEN; + d->rqueue.ifq_maxlen = ifqmaxlen; #if __FreeBSD_version >= 500000 mtx_init (&d->rqueue.ifq_mtx, "ce_rqueue", NULL, MTX_DEF); #endif diff --git a/sys/dev/cm/smc90cx6.c b/sys/dev/cm/smc90cx6.c index 0e9015e..719e468 100644 --- a/sys/dev/cm/smc90cx6.c +++ b/sys/dev/cm/smc90cx6.c @@ -189,7 +189,7 @@ cm_attach(dev) ifp->if_ioctl = cm_ioctl; ifp->if_init = cm_init; /* XXX IFQ_SET_READY(&ifp->if_snd); */ - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; arc_ifattach(ifp, linkaddress); diff --git a/sys/dev/cp/if_cp.c b/sys/dev/cp/if_cp.c index f6eeed5..e640230 100644 --- a/sys/dev/cp/if_cp.c +++ b/sys/dev/cp/if_cp.c @@ -505,8 +505,8 @@ static int cp_attach (device_t dev) NG_NODE_UNREF (d->node); continue; } - d->queue.ifq_maxlen = IFQ_MAXLEN; - d->hi_queue.ifq_maxlen = IFQ_MAXLEN; + d->queue.ifq_maxlen = ifqmaxlen; + d->hi_queue.ifq_maxlen = ifqmaxlen; mtx_init (&d->queue.ifq_mtx, "cp_queue", NULL, MTX_DEF); mtx_init (&d->hi_queue.ifq_mtx, "cp_queue_hi", NULL, MTX_DEF); #else /*NETGRAPH*/ diff --git a/sys/dev/cs/if_cs.c b/sys/dev/cs/if_cs.c index b32a03d..476b9dd 100644 --- a/sys/dev/cs/if_cs.c +++ b/sys/dev/cs/if_cs.c @@ -500,7 +500,7 @@ cs_attach(device_t dev) ifp->if_start=cs_start; ifp->if_ioctl=cs_ioctl; ifp->if_init=cs_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); diff --git a/sys/dev/ctau/if_ct.c b/sys/dev/ctau/if_ct.c index 125dfa5..dbdca97 100644 --- a/sys/dev/ctau/if_ct.c +++ b/sys/dev/ctau/if_ct.c @@ -722,8 +722,8 @@ static int ct_attach (device_t dev) ct_bus_dma_mem_free (&d->dmamem); continue; } - d->queue.ifq_maxlen = IFQ_MAXLEN; - d->hi_queue.ifq_maxlen = IFQ_MAXLEN; + d->queue.ifq_maxlen = ifqmaxlen; + d->hi_queue.ifq_maxlen = ifqmaxlen; mtx_init (&d->queue.ifq_mtx, "ct_queue", NULL, MTX_DEF); mtx_init (&d->hi_queue.ifq_mtx, "ct_queue_hi", NULL, MTX_DEF); #else /*NETGRAPH*/ diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c index 4e9750e..c8f53a0 100644 --- a/sys/dev/cx/if_cx.c +++ b/sys/dev/cx/if_cx.c @@ -831,8 +831,8 @@ static int cx_attach (device_t dev) cx_bus_dma_mem_free (&d->dmamem); continue; } - d->lo_queue.ifq_maxlen = IFQ_MAXLEN; - d->hi_queue.ifq_maxlen = IFQ_MAXLEN; + d->lo_queue.ifq_maxlen = ifqmaxlen; + d->hi_queue.ifq_maxlen = ifqmaxlen; mtx_init (&d->lo_queue.ifq_mtx, "cx_queue_lo", NULL, MTX_DEF); mtx_init (&d->hi_queue.ifq_mtx, "cx_queue_hi", NULL, MTX_DEF); #else /*NETGRAPH*/ diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c index a47284f..a805b5d 100644 --- a/sys/dev/cxgb/cxgb_main.c +++ b/sys/dev/cxgb/cxgb_main.c @@ -1012,7 +1012,7 @@ cxgb_port_attach(device_t dev) ifp->if_ioctl = cxgb_ioctl; ifp->if_start = cxgb_start; - ifp->if_snd.ifq_drv_maxlen = cxgb_snd_queue_len; + ifp->if_snd.ifq_drv_maxlen = max(cxgb_snd_queue_len, ifqmaxlen); IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen); IFQ_SET_READY(&ifp->if_snd); diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c index e065a67..839e2a5 100644 --- a/sys/dev/ed/if_ed.c +++ b/sys/dev/ed/if_ed.c @@ -283,8 +283,8 @@ ed_attach(device_t dev) ifp->if_start = ed_start; ifp->if_ioctl = ed_ioctl; ifp->if_init = ed_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ifp->if_linkmib = &sc->mibdata; ifp->if_linkmiblen = sizeof sc->mibdata; diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c index 59dd1c4..2436255 100644 --- a/sys/dev/ep/if_ep.c +++ b/sys/dev/ep/if_ep.c @@ -306,8 +306,8 @@ ep_attach(struct ep_softc *sc) ifp->if_start = epstart; ifp->if_ioctl = epioctl; ifp->if_init = epinit; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); callout_init_mtx(&sc->watchdog_timer, &sc->sc_mtx, 0); diff --git a/sys/dev/ex/if_ex.c b/sys/dev/ex/if_ex.c index d9e0c98..efd54bc 100644 --- a/sys/dev/ex/if_ex.c +++ b/sys/dev/ex/if_ex.c @@ -237,7 +237,7 @@ ex_attach(device_t dev) ifp->if_start = ex_start; ifp->if_ioctl = ex_ioctl; ifp->if_init = ex_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifmedia_init(&sc->ifmedia, 0, ex_ifmedia_upd, ex_ifmedia_sts); mtx_init(&sc->lock, device_get_nameunit(dev), MTX_NETWORK_LOCK, diff --git a/sys/dev/fe/if_fe.c b/sys/dev/fe/if_fe.c index eff92b7..9fe1f2c 100644 --- a/sys/dev/fe/if_fe.c +++ b/sys/dev/fe/if_fe.c @@ -766,7 +766,7 @@ fe_attach (device_t dev) * Set fixed interface flags. */ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); #if FE_SINGLE_TRANSMISSION /* Override txb config to allocate minimum. */ diff --git a/sys/dev/ie/if_ie.c b/sys/dev/ie/if_ie.c index 34c658e..172bf9e 100644 --- a/sys/dev/ie/if_ie.c +++ b/sys/dev/ie/if_ie.c @@ -318,7 +318,7 @@ ie_attach(device_t dev) ifp->if_start = iestart; ifp->if_ioctl = ieioctl; ifp->if_init = ieinit; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ether_ifattach(ifp, sc->enaddr); diff --git a/sys/dev/iicbus/if_ic.c b/sys/dev/iicbus/if_ic.c index bb5186c..4a05b16 100644 --- a/sys/dev/iicbus/if_ic.c +++ b/sys/dev/iicbus/if_ic.c @@ -181,7 +181,7 @@ icattach(device_t dev) ifp->if_output = icoutput; ifp->if_hdrlen = 0; ifp->if_addrlen = 0; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; ic_alloc_buffers(sc, ICMTU); diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c index 3315d65..2329c33 100644 --- a/sys/dev/ipw/if_ipw.c +++ b/sys/dev/ipw/if_ipw.c @@ -289,8 +289,8 @@ ipw_attach(device_t dev) ifp->if_init = ipw_init; ifp->if_ioctl = ipw_ioctl; ifp->if_start = ipw_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c index 1105425..4b765ef 100644 --- a/sys/dev/iwi/if_iwi.c +++ b/sys/dev/iwi/if_iwi.c @@ -363,8 +363,8 @@ iwi_attach(device_t dev) ifp->if_init = iwi_init; ifp->if_ioctl = iwi_ioctl; ifp->if_start = iwi_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c index 09c1efd..5a17d1e 100644 --- a/sys/dev/iwn/if_iwn.c +++ b/sys/dev/iwn/if_iwn.c @@ -627,8 +627,8 @@ iwn_attach(device_t dev) ifp->if_init = iwn_init; ifp->if_ioctl = iwn_ioctl; ifp->if_start = iwn_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ieee80211_ifattach(ic, macaddr); diff --git a/sys/dev/le/lance.c b/sys/dev/le/lance.c index db20099..8700aa2 100644 --- a/sys/dev/le/lance.c +++ b/sys/dev/le/lance.c @@ -133,8 +133,8 @@ lance_config(struct lance_softc *sc, const char* name, int unit) ifp->if_flags &= ~IFF_MULTICAST; #endif ifp->if_baudrate = IF_Mbps(10); - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); /* Initialize ifmedia structures. */ diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c index 57e0d3d..ae6ef88 100644 --- a/sys/dev/malo/if_malo.c +++ b/sys/dev/malo/if_malo.c @@ -275,8 +275,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc) ifp->if_start = malo_start; ifp->if_ioctl = malo_ioctl; ifp->if_init = malo_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index e4e469b..662f201 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -404,8 +404,8 @@ mwl_attach(uint16_t devid, struct mwl_softc *sc) ifp->if_start = mwl_start; ifp->if_ioctl = mwl_ioctl; ifp->if_init = mwl_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/my/if_my.c b/sys/dev/my/if_my.c index 99f6071..951473a 100644 --- a/sys/dev/my/if_my.c +++ b/sys/dev/my/if_my.c @@ -902,8 +902,8 @@ my_attach(device_t dev) ifp->if_start = my_start; ifp->if_init = my_init; ifp->if_baudrate = 10000000; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); if (sc->my_info->my_did == MTD803ID) diff --git a/sys/dev/nxge/if_nxge.c b/sys/dev/nxge/if_nxge.c index c86d7b6..0e67413 100644 --- a/sys/dev/nxge/if_nxge.c +++ b/sys/dev/nxge/if_nxge.c @@ -1190,7 +1190,7 @@ xge_interface_setup(device_t dev) ifnetp->if_start = xge_send; /* TODO: Check and assign optimal value */ - ifnetp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifnetp->if_snd.ifq_maxlen = ifqmaxlen; ifnetp->if_capabilities = IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM; diff --git a/sys/dev/pdq/pdq_ifsubr.c b/sys/dev/pdq/pdq_ifsubr.c index ec14150..4df0082 100644 --- a/sys/dev/pdq/pdq_ifsubr.c +++ b/sys/dev/pdq/pdq_ifsubr.c @@ -471,7 +471,7 @@ pdq_ifattach(pdq_softc_t *sc, const pdq_uint8_t *llc, pdq_type_t type) if_initname(ifp, device_get_name(sc->dev), device_get_unit(sc->dev)); ifp->if_softc = sc; ifp->if_init = pdq_ifinit; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; ifp->if_ioctl = pdq_ifioctl; diff --git a/sys/dev/ppbus/if_plip.c b/sys/dev/ppbus/if_plip.c index 3e4c1ca..fc81aec 100644 --- a/sys/dev/ppbus/if_plip.c +++ b/sys/dev/ppbus/if_plip.c @@ -262,7 +262,7 @@ lp_attach(device_t dev) ifp->if_output = lpoutput; ifp->if_hdrlen = 0; ifp->if_addrlen = 0; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c index 9549107..8589768 100644 --- a/sys/dev/ral/rt2560.c +++ b/sys/dev/ral/rt2560.c @@ -267,8 +267,8 @@ rt2560_attach(device_t dev, int id) ifp->if_init = rt2560_init; ifp->if_ioctl = rt2560_ioctl; ifp->if_start = rt2560_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c index 9bc8838..9b77c23 100644 --- a/sys/dev/ral/rt2661.c +++ b/sys/dev/ral/rt2661.c @@ -269,8 +269,8 @@ rt2661_attach(device_t dev, int id) ifp->if_init = rt2661_init; ifp->if_ioctl = rt2661_ioctl; ifp->if_start = rt2661_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/sbni/if_sbni.c b/sys/dev/sbni/if_sbni.c index 8c8687c..7ca46d3 100644 --- a/sys/dev/sbni/if_sbni.c +++ b/sys/dev/sbni/if_sbni.c @@ -235,7 +235,7 @@ sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags) ifp->if_init = sbni_init; ifp->if_start = sbni_start; ifp->if_ioctl = sbni_ioctl; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); /* report real baud rate */ csr0 = sbni_inb(sc, CSR0); diff --git a/sys/dev/smc/if_smc.c b/sys/dev/smc/if_smc.c index f7f5407..6d9ba59 100644 --- a/sys/dev/smc/if_smc.c +++ b/sys/dev/smc/if_smc.c @@ -347,7 +347,7 @@ smc_attach(device_t dev) ifp->if_init = smc_init; ifp->if_ioctl = smc_ioctl; ifp->if_start = smc_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities = ifp->if_capenable = 0; diff --git a/sys/dev/sn/if_sn.c b/sys/dev/sn/if_sn.c index 217d811..0f86f92 100644 --- a/sys/dev/sn/if_sn.c +++ b/sys/dev/sn/if_sn.c @@ -207,8 +207,8 @@ sn_attach(device_t dev) ifp->if_ioctl = snioctl; ifp->if_init = sninit; ifp->if_baudrate = 10000000; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ether_ifattach(ifp, eaddr); diff --git a/sys/dev/snc/dp83932.c b/sys/dev/snc/dp83932.c index c659c82..0b62053 100644 --- a/sys/dev/snc/dp83932.c +++ b/sys/dev/snc/dp83932.c @@ -177,7 +177,7 @@ sncconfig(sc, media, nmedia, defmedia, myea) ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = sncinit; ifp->if_mtu = ETHERMTU; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); /* Initialize media goo. */ ifmedia_init(&sc->sc_media, 0, snc_mediachange, diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c index a810ec4..21a23c9 100644 --- a/sys/dev/usb/net/uhso.c +++ b/sys/dev/usb/net/uhso.c @@ -1471,8 +1471,8 @@ static int uhso_attach_ifnet(struct uhso_softc *sc, struct usb_interface *iface, ifp->if_output = uhso_if_output; ifp->if_flags = 0; ifp->if_softc = sc; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); if_attach(ifp); diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c index 6cf4460..bd75cef 100644 --- a/sys/dev/usb/net/usb_ethernet.c +++ b/sys/dev/usb/net/usb_ethernet.c @@ -214,8 +214,8 @@ ue_attach_post_task(struct usb_proc_msg *_task) ifp->if_ioctl = uether_ioctl; ifp->if_start = ue_start; ifp->if_init = ue_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ue->ue_ifp = ifp; diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index 4a5fbae..155b767 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -478,8 +478,8 @@ rum_attach(device_t self) ifp->if_init = rum_init; ifp->if_ioctl = rum_ioctl; ifp->if_start = rum_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 3ab607f..c798c32 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -609,8 +609,8 @@ run_attach(device_t self) ifp->if_init = run_init; ifp->if_ioctl = run_ioctl; ifp->if_start = run_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c index 7838d5a..40b7c83 100644 --- a/sys/dev/usb/wlan/if_uath.c +++ b/sys/dev/usb/wlan/if_uath.c @@ -438,8 +438,8 @@ uath_attach(device_t dev) ifp->if_ioctl = uath_ioctl; ifp->if_start = uath_start; /* XXX UATH_TX_DATA_LIST_COUNT */ - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic = ifp->if_l2com; diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c index 20f06c6..091b9df 100644 --- a/sys/dev/usb/wlan/if_upgt.c +++ b/sys/dev/usb/wlan/if_upgt.c @@ -331,7 +331,7 @@ upgt_attach(device_t dev) ifp->if_init = upgt_init; ifp->if_ioctl = upgt_ioctl; ifp->if_start = upgt_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); IFQ_SET_READY(&ifp->if_snd); ic = ifp->if_l2com; diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c index 4a4378b..6839bcf 100644 --- a/sys/dev/usb/wlan/if_ural.c +++ b/sys/dev/usb/wlan/if_ural.c @@ -467,8 +467,8 @@ ural_attach(device_t self) ifp->if_init = ural_init; ifp->if_ioctl = ural_ioctl; ifp->if_start = ural_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/usb/wlan/if_urtw.c b/sys/dev/usb/wlan/if_urtw.c index 6604268..9ff16f3 100644 --- a/sys/dev/usb/wlan/if_urtw.c +++ b/sys/dev/usb/wlan/if_urtw.c @@ -867,8 +867,8 @@ urtw_attach(device_t dev) ifp->if_ioctl = urtw_ioctl; ifp->if_start = urtw_start; /* XXX URTW_TX_DATA_LIST_COUNT */ - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic = ifp->if_l2com; diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c index a0b8179..1a298f8 100644 --- a/sys/dev/usb/wlan/if_zyd.c +++ b/sys/dev/usb/wlan/if_zyd.c @@ -381,7 +381,7 @@ zyd_attach(device_t dev) ifp->if_init = zyd_init; ifp->if_ioctl = zyd_ioctl; ifp->if_start = zyd_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); IFQ_SET_READY(&ifp->if_snd); ic = ifp->if_l2com; diff --git a/sys/dev/vx/if_vx.c b/sys/dev/vx/if_vx.c index 0dea9bf..1ea0faf 100644 --- a/sys/dev/vx/if_vx.c +++ b/sys/dev/vx/if_vx.c @@ -189,7 +189,7 @@ vx_attach(device_t dev) } ifp->if_mtu = ETHERMTU; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = vx_start; ifp->if_ioctl = vx_ioctl; diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c index 616c5d7..fe0d903 100644 --- a/sys/dev/wi/if_wi.c +++ b/sys/dev/wi/if_wi.c @@ -333,8 +333,8 @@ wi_attach(device_t dev) ifp->if_ioctl = wi_ioctl; ifp->if_start = wi_start; ifp->if_init = wi_init; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ic->ic_ifp = ifp; diff --git a/sys/dev/wl/if_wl.c b/sys/dev/wl/if_wl.c index ed291ed..a95997e 100644 --- a/sys/dev/wl/if_wl.c +++ b/sys/dev/wl/if_wl.c @@ -559,7 +559,7 @@ wlattach(device_t device) ifp->if_init = wlinit; ifp->if_start = wlstart; ifp->if_ioctl = wlioctl; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; /* no entries ifp->if_done ifp->if_reset diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c index 9bf9342..f6edc91 100644 --- a/sys/dev/wpi/if_wpi.c +++ b/sys/dev/wpi/if_wpi.c @@ -661,8 +661,8 @@ wpi_attach(device_t dev) ifp->if_init = wpi_init; ifp->if_ioctl = wpi_ioctl; ifp->if_start = wpi_start; - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ieee80211_ifattach(ic, macaddr); diff --git a/sys/dev/xe/if_xe.c b/sys/dev/xe/if_xe.c index f18fd98..77b953a 100644 --- a/sys/dev/xe/if_xe.c +++ b/sys/dev/xe/if_xe.c @@ -254,7 +254,7 @@ xe_attach(device_t dev) scp->ifp->if_ioctl = xe_ioctl; scp->ifp->if_init = xe_init; scp->ifp->if_baudrate = 100000000; - IFQ_SET_MAXLEN(&scp->ifp->if_snd, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&scp->ifp->if_snd, ifqmaxlen); /* Initialise the ifmedia structure */ ifmedia_init(scp->ifm, 0, xe_media_change, xe_media_status); diff --git a/sys/mips/adm5120/if_admsw.c b/sys/mips/adm5120/if_admsw.c index 164e840..472a804 100644 --- a/sys/mips/adm5120/if_admsw.c +++ b/sys/mips/adm5120/if_admsw.c @@ -540,8 +540,8 @@ admsw_attach(device_t dev) ifp->if_init = admsw_init; ifp->if_mtu = ETHERMTU; ifp->if_baudrate = IF_Mbps(100); - IFQ_SET_MAXLEN(&ifp->if_snd, max(ADMSW_NTXLDESC, IFQ_MAXLEN)); - ifp->if_snd.ifq_drv_maxlen = max(ADMSW_NTXLDESC, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&ifp->if_snd, max(ADMSW_NTXLDESC, ifqmaxlen)); + ifp->if_snd.ifq_drv_maxlen = max(ADMSW_NTXLDESC, ifqmaxlen); IFQ_SET_READY(&ifp->if_snd); ifp->if_capabilities |= IFCAP_VLAN_MTU; diff --git a/sys/mips/atheros/if_arge.c b/sys/mips/atheros/if_arge.c index 4367bfb..eef1dcf 100644 --- a/sys/mips/atheros/if_arge.c +++ b/sys/mips/atheros/if_arge.c @@ -312,8 +312,8 @@ arge_attach(device_t dev) sc->arge_if_flags = ifp->if_flags; /* XXX: add real size */ - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); ifp->if_capenable = ifp->if_capabilities; diff --git a/sys/net/if.c b/sys/net/if.c index 1acfb24..780f2c2 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -104,6 +104,10 @@ struct ifindex_entry { SYSCTL_NODE(_net, PF_LINK, link, CTLFLAG_RW, 0, "Link layers"); SYSCTL_NODE(_net_link, 0, generic, CTLFLAG_RW, 0, "Generic link-management"); +TUNABLE_INT("net.link.ifqmaxlen", &ifqmaxlen); +SYSCTL_UINT(_net_link, OID_AUTO, ifqmaxlen, CTLFLAG_RDTUN, + &ifqmaxlen, 0, "max send queue size"); + /* Log link state change events */ static int log_link_state_change = 1; diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c index 94fb03d..61f7cb7 100644 --- a/sys/net/if_ef.c +++ b/sys/net/if_ef.c @@ -129,7 +129,7 @@ ef_attach(struct efnet *sc) ifp->if_start = ef_start; ifp->if_init = ef_init; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); /* * Attach the interface diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index ae0ff4e..7683839 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -185,7 +185,7 @@ gif_clone_create(ifc, unit, params) GIF2IFP(sc)->if_ioctl = gif_ioctl; GIF2IFP(sc)->if_start = gif_start; GIF2IFP(sc)->if_output = gif_output; - GIF2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN; + GIF2IFP(sc)->if_snd.ifq_maxlen = ifqmaxlen; if_attach(GIF2IFP(sc)); bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t)); if (ng_gif_attach_p != NULL) diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index bac3d795..1f1e108 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -184,7 +184,7 @@ gre_clone_create(ifc, unit, params) GRE2IFP(sc)->if_softc = sc; if_initname(GRE2IFP(sc), ifc->ifc_name, unit); - GRE2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN; + GRE2IFP(sc)->if_snd.ifq_maxlen = ifqmaxlen; GRE2IFP(sc)->if_addrlen = 0; GRE2IFP(sc)->if_hdrlen = 24; /* IP + GRE */ GRE2IFP(sc)->if_mtu = GREMTU; diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c index 5c082c4..1ef5581 100644 --- a/sys/net/if_stf.c +++ b/sys/net/if_stf.c @@ -252,7 +252,7 @@ stf_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) ifp->if_mtu = IPV6_MMTU; ifp->if_ioctl = stf_ioctl; ifp->if_output = stf_output; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); return (0); diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c index 3d5669c..97ff7c2 100644 --- a/sys/net80211/ieee80211.c +++ b/sys/net80211/ieee80211.c @@ -394,8 +394,8 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap, ifp->if_ioctl = ieee80211_ioctl; ifp->if_init = ieee80211_init; /* NB: input+output filled in by ether_ifattach */ - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); vap->iv_ifp = ifp; diff --git a/sys/netgraph/ng_eiface.c b/sys/netgraph/ng_eiface.c index 72cc55c..4239328 100644 --- a/sys/netgraph/ng_eiface.c +++ b/sys/netgraph/ng_eiface.c @@ -369,7 +369,7 @@ ng_eiface_constructor(node_p node) ifp->if_output = ether_output; ifp->if_start = ng_eiface_start; ifp->if_ioctl = ng_eiface_ioctl; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_flags = (IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST); /* Give this node the same name as the interface (if possible) */ diff --git a/sys/netgraph/ng_fec.c b/sys/netgraph/ng_fec.c index 919947a..ce5a2d5 100644 --- a/sys/netgraph/ng_fec.c +++ b/sys/netgraph/ng_fec.c @@ -1227,7 +1227,7 @@ ng_fec_constructor(node_p node) ifp->if_start = ng_fec_start; ifp->if_ioctl = ng_fec_ioctl; ifp->if_init = ng_fec_init; - ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + ifp->if_snd.ifq_maxlen = ifqmaxlen; ifp->if_mtu = NG_FEC_MTU_DEFAULT; ifp->if_flags = (IFF_SIMPLEX|IFF_BROADCAST|IFF_MULTICAST); ifp->if_addrlen = 0; /* XXX */ diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c index d53bf76..f94fd14 100644 --- a/sys/netgraph/ng_iface.c +++ b/sys/netgraph/ng_iface.c @@ -564,8 +564,8 @@ ng_iface_constructor(node_p node) ifp->if_addrlen = 0; /* XXX */ ifp->if_hdrlen = 0; /* XXX */ ifp->if_baudrate = 64000; /* XXX */ - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); /* Give this node the same name as the interface (if possible) */ diff --git a/sys/netgraph/ng_tty.c b/sys/netgraph/ng_tty.c index 2fa33fc..8408317 100644 --- a/sys/netgraph/ng_tty.c +++ b/sys/netgraph/ng_tty.c @@ -164,7 +164,7 @@ ngt_constructor(node_p node) sc->node = node; mtx_init(&sc->outq.ifq_mtx, "ng_tty node+queue", NULL, MTX_DEF); - IFQ_SET_MAXLEN(&sc->outq, IFQ_MAXLEN); + IFQ_SET_MAXLEN(&sc->outq, ifqmaxlen); return (0); } diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c index 8b22516..cd7609d 100644 --- a/sys/pci/if_rl.c +++ b/sys/pci/if_rl.c @@ -942,8 +942,8 @@ rl_attach(device_t dev) #ifdef DEVICE_POLLING ifp->if_capabilities |= IFCAP_POLLING; #endif - IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); - ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); + ifp->if_snd.ifq_drv_maxlen = ifqmaxlen; IFQ_SET_READY(&ifp->if_snd); /* -- cgit v1.1 From c3022adc569bbca9f31a89fd15aa761addfebbbd Mon Sep 17 00:00:00 2001 From: mm Date: Mon, 3 May 2010 07:39:51 +0000 Subject: Code indent according to style(9). PR: bin/146186 Submitted by: myself Approved by: delphij (mentor) MFC after: 2 weeks --- lib/libpam/modules/pam_krb5/pam_krb5.c | 46 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.c b/lib/libpam/modules/pam_krb5/pam_krb5.c index 9623a17..439fcf9 100644 --- a/lib/libpam/modules/pam_krb5/pam_krb5.c +++ b/lib/libpam/modules/pam_krb5/pam_krb5.c @@ -199,33 +199,33 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, PAM_LOG("Skipping local user check"); else { - /* Verify the local user exists (AFTER getting the password) */ - if (strchr(user, '@')) { - /* get a local account name for this principal */ - krbret = krb5_aname_to_localname(pam_context, princ, - sizeof(luser), luser); - if (krbret != 0) { - PAM_VERBOSE_ERROR("Kerberos 5 error"); - PAM_LOG("Error krb5_aname_to_localname(): %s", - krb5_get_err_text(pam_context, krbret)); - retval = PAM_USER_UNKNOWN; - goto cleanup2; - } + /* Verify the local user exists (AFTER getting the password) */ + if (strchr(user, '@')) { + /* get a local account name for this principal */ + krbret = krb5_aname_to_localname(pam_context, princ, + sizeof(luser), luser); + if (krbret != 0) { + PAM_VERBOSE_ERROR("Kerberos 5 error"); + PAM_LOG("Error krb5_aname_to_localname(): %s", + krb5_get_err_text(pam_context, krbret)); + retval = PAM_USER_UNKNOWN; + goto cleanup2; + } - retval = pam_set_item(pamh, PAM_USER, luser); - if (retval != PAM_SUCCESS) - goto cleanup2; + retval = pam_set_item(pamh, PAM_USER, luser); + if (retval != PAM_SUCCESS) + goto cleanup2; - PAM_LOG("PAM_USER Redone"); - } + PAM_LOG("PAM_USER Redone"); + } - pwd = getpwnam(user); - if (pwd == NULL) { - retval = PAM_USER_UNKNOWN; - goto cleanup2; - } + pwd = getpwnam(user); + if (pwd == NULL) { + retval = PAM_USER_UNKNOWN; + goto cleanup2; + } - PAM_LOG("Done getpwnam()"); + PAM_LOG("Done getpwnam()"); } /* Get a TGT */ -- cgit v1.1 From cc08eec05b45978c89b49c1439ac21ff9ff81b1c Mon Sep 17 00:00:00 2001 From: delphij Date: Mon, 3 May 2010 09:49:42 +0000 Subject: Bump .Dd date. Forgotten by: delphij --- lib/libpam/modules/pam_krb5/pam_krb5.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/libpam/modules/pam_krb5/pam_krb5.8 b/lib/libpam/modules/pam_krb5/pam_krb5.8 index a182e62e..bd7ac5b 100644 --- a/lib/libpam/modules/pam_krb5/pam_krb5.8 +++ b/lib/libpam/modules/pam_krb5/pam_krb5.8 @@ -1,7 +1,7 @@ .\" .\" $Id: pam_krb5.5,v 1.5 2000/01/05 00:59:56 fcusack Exp $ .\" $FreeBSD$ -.Dd January 15, 1999 +.Dd May 3, 2010 .Dt PAM_KRB5 8 .Os .Sh NAME -- cgit v1.1 From 88731dce0c39d93cd448cfebc49b26c074fec690 Mon Sep 17 00:00:00 2001 From: netchild Date: Mon, 3 May 2010 14:19:58 +0000 Subject: - #ifdef out the cliplist part, skype seems like using an uninitialized variable and can cause problems, without the cliplist handling it works without problems - improve the cliplist error handling - fix VIDIOCGTUNER and VIDIOCSMICROCODE (still no hardware available to test) Submitted by: J.R. Oldroyd X-MFC after: soon (together with all the v4l stuff) --- sys/compat/linux/linux_ioctl.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 6600976..261126b 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -2628,6 +2628,7 @@ bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt) return (0); } +#ifdef COMPAT_LINUX_V4L_CLIPLIST static int linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc) { @@ -2638,6 +2639,7 @@ linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc) vc->next = PTRIN(lvc->next); /* possible pointer size conversion */ return (0); } +#endif static int linux_to_bsd_v4l_window(struct l_video_window *lvw, struct video_window *vw) @@ -2698,6 +2700,7 @@ linux_to_bsd_v4l_code(struct l_video_code *lvc, struct video_code *vc) return (0); } +#ifdef COMPAT_LINUX_V4L_CLIPLIST static int linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc) { @@ -2772,15 +2775,18 @@ linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw) * example of cliplist use. */ plvc = PTRIN(lvw->clips); + vw->clips = NULL; ppvc = &(vw->clips); while (clipcount-- > 0) { - if (plvc == 0) + if (plvc == 0) { error = EFAULT; - if (!error) - error = linux_v4l_clip_copy(plvc, ppvc); - if (error) { - linux_v4l_cliplist_free(vw); break; + } else { + error = linux_v4l_clip_copy(plvc, ppvc); + if (error) { + linux_v4l_cliplist_free(vw); + break; + } } ppvc = &((*ppvc)->next); plvc = PTRIN(((struct l_video_clip *) plvc)->next); @@ -2795,6 +2801,7 @@ linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw) } return (error); } +#endif static int linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) @@ -2818,6 +2825,12 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) case LINUX_VIDIOCGTUNER: if ((error = fget(td, args->fd, &fp)) != 0) return (error); + error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun)); + if (error) { + fdrop(fp, td); + return (error); + } + linux_to_bsd_v4l_tuner(&l_vtun, &vtun); error = fo_ioctl(fp, VIDIOCGTUNER, &vtun, td->td_ucred, td); if (!error) { bsd_to_linux_v4l_tuner(&vtun, &l_vtun); @@ -2836,7 +2849,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) return (error); } linux_to_bsd_v4l_tuner(&l_vtun, &vtun); - error = fo_ioctl(fp, VIDIOCSMICROCODE, &vtun, td->td_ucred, td); + error = fo_ioctl(fp, VIDIOCSTUNER, &vtun, td->td_ucred, td); fdrop(fp, td); return (error); @@ -2865,14 +2878,18 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) return (error); } linux_to_bsd_v4l_window(&l_vwin, &vwin); +#ifdef COMPAT_LINUX_V4L_CLIPLIST error = linux_v4l_cliplist_copy(&l_vwin, &vwin); if (error) { fdrop(fp, td); return (error); } +#endif error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td); fdrop(fp, td); +#ifdef COMPAT_LINUX_V4L_CLIPLIST linux_v4l_cliplist_free(&vwin); +#endif return (error); case LINUX_VIDIOCGFBUF: @@ -2924,7 +2941,7 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args) return (error); } linux_to_bsd_v4l_code(&l_vcode, &vcode); - error = fo_ioctl(fp, VIDIOCSTUNER, &vcode, td->td_ucred, td); + error = fo_ioctl(fp, VIDIOCSMICROCODE, &vcode, td->td_ucred, td); fdrop(fp, td); return (error); -- cgit v1.1 From 6e9b1a98198b959748ee45e847e15c3ad02dbb6b Mon Sep 17 00:00:00 2001 From: kib Date: Mon, 3 May 2010 14:30:49 +0000 Subject: Style and comment adjustements. Suggested and reviewed by: bde MFC after: 3 days --- sys/amd64/amd64/exception.S | 79 ++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index 0d5a50d..7b1fed8 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -50,14 +50,14 @@ .bss .globl dtrace_invop_jump_addr .align 8 - .type dtrace_invop_jump_addr, @object - .size dtrace_invop_jump_addr, 8 + .type dtrace_invop_jump_addr,@object + .size dtrace_invop_jump_addr,8 dtrace_invop_jump_addr: .zero 8 .globl dtrace_invop_calltrap_addr .align 8 - .type dtrace_invop_calltrap_addr, @object - .size dtrace_invop_calltrap_addr, 8 + .type dtrace_invop_calltrap_addr,@object + .size dtrace_invop_calltrap_addr,8 dtrace_invop_calltrap_addr: .zero 8 #endif @@ -157,7 +157,6 @@ IDTVEC(align) * kernel from userland. Reenable interrupts if they were enabled * before the trap. This approximates SDT_SYS386TGT on the i386 port. */ - SUPERALIGN_TEXT .globl alltraps .type alltraps,@function @@ -211,16 +210,16 @@ alltraps_pushregs_no_rdi: * Set our jump address for the jump back in the event that * the breakpoint wasn't caused by DTrace at all. */ - movq $calltrap, dtrace_invop_calltrap_addr(%rip) + movq $calltrap,dtrace_invop_calltrap_addr(%rip) /* Jump to the code hooked in by DTrace. */ - movq dtrace_invop_jump_addr, %rax + movq dtrace_invop_jump_addr,%rax jmpq *dtrace_invop_jump_addr #endif .globl calltrap .type calltrap,@function calltrap: - movq %rsp, %rdi + movq %rsp,%rdi call trap MEXITCOUNT jmp doreti /* Handle any pending ASTs */ @@ -274,9 +273,11 @@ IDTVEC(dblfault) testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */ jz 1f /* already running with kernel GS.base */ swapgs -1: movq %rsp, %rdi +1: + movq %rsp,%rdi call dblfault_handler -2: hlt +2: + hlt jmp 2b IDTVEC(page) @@ -369,7 +370,7 @@ IDTVEC(fast_syscall) movq %r15,TF_R15(%rsp) /* C preserved */ movl $TF_HASSEGS,TF_FLAGS(%rsp) FAKE_MCOUNT(TF_RIP(%rsp)) - movq %rsp, %rdi + movq %rsp,%rdi call syscall movq PCPU(CURPCB),%rax andq $~PCB_FULLCTX,PCB_FLAGS(%rax) @@ -456,7 +457,7 @@ nmi_fromuserspace: /* Note: this label is also used by ddb and gdb: */ nmi_calltrap: FAKE_MCOUNT(TF_RIP(%rsp)) - movq %rsp, %rdi + movq %rsp,%rdi call trap MEXITCOUNT #ifdef HWPMC_HOOKS @@ -555,9 +556,9 @@ nmi_restoreregs: iretq ENTRY(fork_trampoline) - movq %r12, %rdi /* function */ - movq %rbx, %rsi /* arg1 */ - movq %rsp, %rdx /* trapframe pointer */ + movq %r12,%rdi /* function */ + movq %rbx,%rsi /* arg1 */ + movq %rsp,%rdx /* trapframe pointer */ call fork_exit MEXITCOUNT jmp doreti /* Handle any ASTs */ @@ -628,7 +629,7 @@ doreti_ast: testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax) je doreti_exit sti - movq %rsp, %rdi /* pass a pointer to the trapframe */ + movq %rsp,%rdi /* pass a pointer to the trapframe */ call ast jmp doreti_ast @@ -648,8 +649,8 @@ doreti_exit: * Do not reload segment registers for kernel. * Since we do not reload segments registers with sane * values on kernel entry, descriptors referenced by - * segments registers may be not valid. This is fatal - * for the usermode, but is innocent for the kernel. + * segments registers might be not valid. This is fatal + * for user mode, but is not a problem for the kernel. */ testb $SEL_RPL_MASK,TF_CS(%rsp) jz ld_regs @@ -662,14 +663,16 @@ do_segs: /* Restore %fs and fsbase */ movw TF_FS(%rsp),%ax .globl ld_fs -ld_fs: movw %ax,%fs +ld_fs: + movw %ax,%fs cmpw $KUF32SEL,%ax jne 1f movl $MSR_FSBASE,%ecx movl PCB_FSBASE(%r8),%eax movl PCB_FSBASE+4(%r8),%edx .globl ld_fsbase -ld_fsbase: wrmsr +ld_fsbase: + wrmsr 1: /* Restore %gs and gsbase */ movw TF_GS(%rsp),%si @@ -678,7 +681,8 @@ ld_fsbase: wrmsr movl $MSR_GSBASE,%ecx rdmsr .globl ld_gs -ld_gs: movw %si,%gs +ld_gs: + movw %si,%gs wrmsr popfq cmpw $KUG32SEL,%si @@ -687,12 +691,17 @@ ld_gs: movw %si,%gs movl PCB_GSBASE(%r8),%eax movl PCB_GSBASE+4(%r8),%edx .globl ld_gsbase -ld_gsbase: wrmsr -1: .globl ld_es -ld_es: movw TF_ES(%rsp),%es +ld_gsbase: + wrmsr +1: + .globl ld_es +ld_es: + movw TF_ES(%rsp),%es .globl ld_ds -ld_ds: movw TF_DS(%rsp),%ds -ld_regs:movq TF_RDI(%rsp),%rdi +ld_ds: + movw TF_DS(%rsp),%ds +ld_regs: + movq TF_RDI(%rsp),%rdi movq TF_RSI(%rsp),%rsi movq TF_RDX(%rsp),%rdx movq TF_RCX(%rsp),%rcx @@ -711,7 +720,8 @@ ld_regs:movq TF_RDI(%rsp),%rdi jz 1f /* keep running with kernel GS.base */ cli swapgs -1: addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */ +1: + addq $TF_RIP,%rsp /* skip over tf_err, tf_trapno */ .globl doreti_iret doreti_iret: iretq @@ -738,7 +748,8 @@ doreti_iret_fault: testl $PSL_I,TF_RFLAGS(%rsp) jz 1f sti -1: movw %fs,TF_FS(%rsp) +1: + movw %fs,TF_FS(%rsp) movw %gs,TF_GS(%rsp) movw %es,TF_ES(%rsp) movw %ds,TF_DS(%rsp) @@ -768,7 +779,7 @@ doreti_iret_fault: .globl ds_load_fault ds_load_fault: movl $T_PROTFLT,TF_TRAPNO(%rsp) - movq %rsp, %rdi + movq %rsp,%rdi call trap movw $KUDSEL,TF_DS(%rsp) jmp doreti @@ -777,7 +788,7 @@ ds_load_fault: .globl es_load_fault es_load_fault: movl $T_PROTFLT,TF_TRAPNO(%rsp) - movq %rsp, %rdi + movq %rsp,%rdi call trap movw $KUDSEL,TF_ES(%rsp) jmp doreti @@ -786,7 +797,7 @@ es_load_fault: .globl fs_load_fault fs_load_fault: movl $T_PROTFLT,TF_TRAPNO(%rsp) - movq %rsp, %rdi + movq %rsp,%rdi call trap movw $KUF32SEL,TF_FS(%rsp) jmp doreti @@ -796,7 +807,7 @@ fs_load_fault: gs_load_fault: popfq movl $T_PROTFLT,TF_TRAPNO(%rsp) - movq %rsp, %rdi + movq %rsp,%rdi call trap movw $KUG32SEL,TF_GS(%rsp) jmp doreti @@ -805,7 +816,7 @@ gs_load_fault: .globl fsbase_load_fault fsbase_load_fault: movl $T_PROTFLT,TF_TRAPNO(%rsp) - movq %rsp, %rdi + movq %rsp,%rdi call trap movq PCPU(CURTHREAD),%r8 movq TD_PCB(%r8),%r8 @@ -816,7 +827,7 @@ fsbase_load_fault: .globl gsbase_load_fault gsbase_load_fault: movl $T_PROTFLT,TF_TRAPNO(%rsp) - movq %rsp, %rdi + movq %rsp,%rdi call trap movq PCPU(CURTHREAD),%r8 movq TD_PCB(%r8),%r8 -- cgit v1.1 From 425dc5ab94cdbb6f198795a09b2c4330721536c0 Mon Sep 17 00:00:00 2001 From: alc Date: Mon, 3 May 2010 15:51:59 +0000 Subject: Neither the page lock nor the page queues lock is required to unwire and free a VM_ALLOC_NOOBJ page. (Such pages are unmanaged.) --- sys/dev/ti/if_ti.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c index 20130bc..7eeee36 100644 --- a/sys/dev/ti/if_ti.c +++ b/sys/dev/ti/if_ti.c @@ -1488,10 +1488,8 @@ ti_newbuf_jumbo(sc, idx, m_old) } sf[i] = sf_buf_alloc(frame, SFB_NOWAIT); if (sf[i] == NULL) { - vm_page_lock_queues(); vm_page_unwire(frame, 0); vm_page_free(frame); - vm_page_unlock_queues(); device_printf(sc->ti_dev, "buffer allocation " "failed -- packet dropped!\n"); printf(" index %d page %d\n", idx, i); -- cgit v1.1 From e50916c7a291f469ef1a4e154080873a81efcbc0 Mon Sep 17 00:00:00 2001 From: zec Date: Mon, 3 May 2010 16:08:24 +0000 Subject: When destroying a vnet, shut down all netgraph nodes tied to that vnet before proceeding with dismantling other protocol domains. This change only affects options VIMAGE builds. Reviewed by: julian, bz MFC after: 3 days --- sys/netgraph/ng_base.c | 52 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/sys/netgraph/ng_base.c b/sys/netgraph/ng_base.c index fdfe878..2a93e58 100644 --- a/sys/netgraph/ng_base.c +++ b/sys/netgraph/ng_base.c @@ -3067,28 +3067,42 @@ ng_mod_event(module_t mod, int event, void *data) static void vnet_netgraph_uninit(const void *unused __unused) { -#if 0 - node_p node, last_killed = NULL; - - /* XXXRW: utterly bogus. */ - while ((node = LIST_FIRST(&V_ng_allnodes)) != NULL) { - if (node == last_killed) { - /* This should never happen */ - node->nd_flags |= NGF_REALLY_DIE; - printf("netgraph node %s needs NGF_REALLY_DIE\n", - node->nd_name); + node_p node = NULL, last_killed = NULL; + int i; + + do { + /* Find a node to kill */ + mtx_lock(&ng_namehash_mtx); + for (i = 0; i < NG_NAME_HASH_SIZE; i++) { + LIST_FOREACH(node, &V_ng_name_hash[i], nd_nodes) { + if (node != &ng_deadnode) { + NG_NODE_REF(node); + break; + } + } + if (node != NULL) + break; + } + mtx_unlock(&ng_namehash_mtx); + + /* Attempt to kill it only if it is a regular node */ + if (node != NULL) { + if (node == last_killed) { + /* This should never happen */ + printf("ng node %s needs" + "NGF_REALLY_DIE\n", node->nd_name); + if (node->nd_flags & NGF_REALLY_DIE) + panic("ng node %s won't die", + node->nd_name); + node->nd_flags |= NGF_REALLY_DIE; + } ng_rmnode(node, NULL, NULL, 0); - /* This must never happen */ - if (node == LIST_FIRST(&V_ng_allnodes)) - panic("netgraph node %s won't die", - node->nd_name); + NG_NODE_UNREF(node); + last_killed = node; } - ng_rmnode(node, NULL, NULL, 0); - last_killed = node; - } -#endif + } while (node != NULL); } -VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_NETGRAPH, SI_ORDER_ANY, +VNET_SYSUNINIT(vnet_netgraph_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, vnet_netgraph_uninit, NULL); #endif /* VIMAGE */ -- cgit v1.1 From 1923b6ded3da335e5752c75a0ad1b1219e63521b Mon Sep 17 00:00:00 2001 From: alc Date: Mon, 3 May 2010 16:41:11 +0000 Subject: Acquire the page lock around vm_page_unwire() and vm_page_wire(). Reviewed by: kib --- sys/fs/tmpfs/tmpfs_vnops.c | 4 ++++ sys/kern/vfs_bio.c | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 3d3755d..2d6005a 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -460,9 +460,11 @@ tmpfs_nocacheread(vm_object_t tobj, vm_pindex_t idx, error = uiomove_fromphys(&m, offset, tlen, uio); VM_OBJECT_LOCK(tobj); out: + vm_page_lock(m); vm_page_lock_queues(); vm_page_unwire(m, TRUE); vm_page_unlock_queues(); + vm_page_unlock(m); vm_page_wakeup(m); vm_object_pip_subtract(tobj, 1); VM_OBJECT_UNLOCK(tobj); @@ -691,6 +693,7 @@ nocache: out: if (vobj != NULL) VM_OBJECT_LOCK(vobj); + vm_page_lock(tpg); vm_page_lock_queues(); if (error == 0) { KASSERT(tpg->valid == VM_PAGE_BITS_ALL, @@ -699,6 +702,7 @@ out: } vm_page_unwire(tpg, TRUE); vm_page_unlock_queues(); + vm_page_unlock(tpg); vm_page_wakeup(tpg); if (vpg != NULL) vm_page_wakeup(vpg); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 1048998..5db2d9e 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -2942,7 +2942,6 @@ allocbuf(struct buf *bp, int size) vm_page_t m; VM_OBJECT_LOCK(bp->b_bufobj->bo_object); - vm_page_lock_queues(); for (i = desiredpages; i < bp->b_npages; i++) { /* * the page is not freed here -- it @@ -2952,13 +2951,17 @@ allocbuf(struct buf *bp, int size) m = bp->b_pages[i]; KASSERT(m != bogus_page, ("allocbuf: bogus page found")); - while (vm_page_sleep_if_busy(m, TRUE, "biodep")) - vm_page_lock_queues(); + while (vm_page_sleep_if_busy(m, TRUE, + "biodep")) + continue; bp->b_pages[i] = NULL; + vm_page_lock(m); + vm_page_lock_queues(); vm_page_unwire(m, 0); + vm_page_unlock_queues(); + vm_page_unlock(m); } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object); pmap_qremove((vm_offset_t) trunc_page((vm_offset_t)bp->b_data) + (desiredpages << PAGE_SHIFT), (bp->b_npages - desiredpages)); @@ -3039,9 +3042,11 @@ allocbuf(struct buf *bp, int size) /* * We have a good page. */ + vm_page_lock(m); vm_page_lock_queues(); vm_page_wire(m); vm_page_unlock_queues(); + vm_page_unlock(m); bp->b_pages[bp->b_npages] = m; ++bp->b_npages; } -- cgit v1.1 From 77a3b0ef9e6b06d4ee34650022fbf4cf4af410c9 Mon Sep 17 00:00:00 2001 From: alc Date: Mon, 3 May 2010 16:55:50 +0000 Subject: Acquire the page lock around vm_page_unwire(). For consistency, extend the scope of the object lock in agp_i810.c. (In this specific case, the scope of the object lock shouldn't matter, but I don't want to create a bad example that might be copied to a case where it did matter.) Reviewed by: kib --- sys/dev/agp/agp.c | 4 ++++ sys/dev/agp/agp_i810.c | 4 +++- sys/dev/drm/via_dmablit.c | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c index c992c93..89b68b0 100644 --- a/sys/dev/agp/agp.c +++ b/sys/dev/agp/agp.c @@ -623,9 +623,11 @@ bad: m = vm_page_lookup(mem->am_obj, OFF_TO_IDX(k)); if (k >= i) vm_page_wakeup(m); + vm_page_lock(m); vm_page_lock_queues(); vm_page_unwire(m, 0); vm_page_unlock_queues(); + vm_page_unlock(m); } VM_OBJECT_UNLOCK(mem->am_obj); @@ -657,9 +659,11 @@ agp_generic_unbind_memory(device_t dev, struct agp_memory *mem) VM_OBJECT_LOCK(mem->am_obj); for (i = 0; i < mem->am_size; i += PAGE_SIZE) { m = vm_page_lookup(mem->am_obj, atop(i)); + vm_page_lock(m); vm_page_lock_queues(); vm_page_unwire(m, 0); vm_page_unlock_queues(); + vm_page_unlock(m); } VM_OBJECT_UNLOCK(mem->am_obj); diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c index 95a9cc4..44eb50d 100644 --- a/sys/dev/agp/agp_i810.c +++ b/sys/dev/agp/agp_i810.c @@ -1010,10 +1010,12 @@ agp_i810_free_memory(device_t dev, struct agp_memory *mem) VM_OBJECT_LOCK(mem->am_obj); m = vm_page_lookup(mem->am_obj, 0); - VM_OBJECT_UNLOCK(mem->am_obj); + vm_page_lock(m); vm_page_lock_queues(); vm_page_unwire(m, 0); vm_page_unlock_queues(); + vm_page_unlock(m); + VM_OBJECT_UNLOCK(mem->am_obj); } else { contigfree(sc->argb_cursor, mem->am_size, M_AGP); sc->argb_cursor = NULL; diff --git a/sys/dev/drm/via_dmablit.c b/sys/dev/drm/via_dmablit.c index 3a66b26..72d914e 100644 --- a/sys/dev/drm/via_dmablit.c +++ b/sys/dev/drm/via_dmablit.c @@ -178,9 +178,11 @@ via_free_sg_info(drm_via_sg_info_t *vsg) case dr_via_pages_locked: for (i=0; i < vsg->num_pages; ++i) { if ( NULL != (page = vsg->pages[i])) { + vm_page_lock(page); vm_page_lock_queues(); vm_page_unwire(page, 0); vm_page_unlock_queues(); + vm_page_unlock(page); } } case dr_via_pages_alloc: -- cgit v1.1 From 0ec9744723453231e9fd60b03b8c68d4ce625cf7 Mon Sep 17 00:00:00 2001 From: alc Date: Mon, 3 May 2010 17:35:31 +0000 Subject: It makes more sense for the object-based backend allocator to use OBJT_PHYS objects instead of OBJT_DEFAULT objects because we never reclaim or pageout the allocated pages. Moreover, they are mapped with pmap_qenter(), which creates unmanaged mappings. Reviewed by: kib --- sys/vm/uma_core.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/sys/vm/uma_core.c b/sys/vm/uma_core.c index 00a8276..e1b9a08 100644 --- a/sys/vm/uma_core.c +++ b/sys/vm/uma_core.c @@ -1022,12 +1022,8 @@ obj_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) while (pages != startpages) { pages--; p = TAILQ_LAST(&object->memq, pglist); - vm_page_lock(p); - vm_page_lock_queues(); vm_page_unwire(p, 0); vm_page_free(p); - vm_page_unlock_queues(); - vm_page_unlock(p); } retkva = 0; goto done; @@ -2893,13 +2889,11 @@ uma_zone_set_obj(uma_zone_t zone, struct vm_object *obj, int count) if (kva == 0) return (0); - if (obj == NULL) { - obj = vm_object_allocate(OBJT_DEFAULT, - pages); - } else { + if (obj == NULL) + obj = vm_object_allocate(OBJT_PHYS, pages); + else { VM_OBJECT_LOCK_INIT(obj, "uma object"); - _vm_object_allocate(OBJT_DEFAULT, - pages, obj); + _vm_object_allocate(OBJT_PHYS, pages, obj); } ZONE_LOCK(zone); keg->uk_kva = kva; -- cgit v1.1 From 33bb944de87dcb5fa7c7c5c260ca36e8b5ad739f Mon Sep 17 00:00:00 2001 From: alc Date: Mon, 3 May 2010 17:55:32 +0000 Subject: Acquire the page lock around vm_page_wire() in vm_page_grab(). Assert that the page lock is held in vm_page_wire(). --- sys/vm/vm_page.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index acec3b7..e18e7ba 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1544,6 +1544,7 @@ vm_page_wire(vm_page_t m) * it is already off the queues). */ mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); if (m->flags & PG_FICTITIOUS) return; if (m->wire_count == 0) { @@ -1914,9 +1915,11 @@ retrylookup: goto retrylookup; } else { if ((allocflags & VM_ALLOC_WIRED) != 0) { + vm_page_lock(m); vm_page_lock_queues(); vm_page_wire(m); vm_page_unlock_queues(); + vm_page_unlock(m); } if ((allocflags & VM_ALLOC_NOBUSY) == 0) vm_page_busy(m); -- cgit v1.1 From ba89ec54691d267a0696f1b817ec27de69cd28ef Mon Sep 17 00:00:00 2001 From: kan Date: Mon, 3 May 2010 18:04:17 +0000 Subject: Do not encode more than CTF_MAX_VLEN(1023) enum members. CTF can not represent enums with more than CTF_MAX_VLEN members, but ctfconvert will happily ignore that limitation and create CTF section no other tool can interpret. This change is different from similar change from upstream, which just returns an error if big enum is encountered. Doing that means that every FreeBSD kernel with compiled in hwpmc will have no useable CTF information due to pmc_event enum having 1236+ members. --- cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c index 6a9d67a..d95dd1d 100644 --- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c +++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c @@ -355,14 +355,21 @@ write_type(void *arg1, void *arg2) for (i = 0, ep = tp->t_emem; ep != NULL; ep = ep->el_next) i++; /* count up enum members */ + if (i > CTF_MAX_VLEN) { + warning("enum %s has too many values: %d > %d\n", + tdesc_name(tp), i, CTF_MAX_VLEN); + i = CTF_MAX_VLEN; + } + ctt.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, isroot, i); write_sized_type_rec(b, &ctt, tp->t_size); - for (ep = tp->t_emem; ep != NULL; ep = ep->el_next) { + for (ep = tp->t_emem; ep != NULL && i > 0; ep = ep->el_next) { offset = strtab_insert(&b->ctb_strtab, ep->el_name); cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset); cte.cte_value = ep->el_number; ctf_buf_write(b, &cte, sizeof (cte)); + i--; } break; -- cgit v1.1 From 801d761a223441f19bbdaabe1c327b4c37b619be Mon Sep 17 00:00:00 2001 From: marius Date: Mon, 3 May 2010 18:39:40 +0000 Subject: On sparc64 obtain the initiator ID from the Open Firmware device tree in order to match what the PROM built-in driver uses. Approved by: mjacob --- sys/dev/isp/isp_pci.c | 9 +++++++++ sys/dev/isp/isp_sbus.c | 8 +++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index 8410ea6..e152e99 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -46,6 +46,11 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef __sparc64__ +#include +#include +#endif + #include static uint32_t isp_pci_rd_reg(ispsoftc_t *, int); @@ -517,7 +522,11 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp) if (IS_FC(isp)) { ISP_FC_PC(isp, chan)->default_id = 109 - chan; } else { +#ifdef __sparc64__ + ISP_SPI_PC(isp, chan)->iid = OF_getscsinitid(dev); +#else ISP_SPI_PC(isp, chan)->iid = 7; +#endif } } else { if (IS_FC(isp)) { diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c index 895645a..34dcc09 100644 --- a/sys/dev/isp/isp_sbus.c +++ b/sys/dev/isp/isp_sbus.c @@ -41,8 +41,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include +#include #include #include #include @@ -264,11 +266,7 @@ isp_sbus_attach(device_t dev) isp->isp_confopts |= ISP_CFG_OWNLOOPID; } if (default_id == -1) { - /* - * XXX: should be a way to get properties w/o having - * XXX: to call OF_xxx functions - */ - default_id = 7; + default_id = OF_getscsinitid(dev); } ISP_SPI_PC(isp, 0)->iid = default_id; -- cgit v1.1 From 6ca323ef63a448a489c16f9cbb57db639aa48201 Mon Sep 17 00:00:00 2001 From: kib Date: Mon, 3 May 2010 19:19:58 +0000 Subject: Handle busy status of the page in a way expected for pager_getpage(). Flush requested page, unbusy other pages, do not clear m->busy. Reviewed by: alc MFC after: 1 week --- sys/vm/phys_pager.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/vm/phys_pager.c b/sys/vm/phys_pager.c index 42cdab3..97674e3 100644 --- a/sys/vm/phys_pager.c +++ b/sys/vm/phys_pager.c @@ -152,10 +152,10 @@ phys_pager_getpages(vm_object_t object, vm_page_t *m, int count, int reqpage) KASSERT(m[i]->dirty == 0, ("phys_pager_getpages: dirty page %p", m[i])); /* The requested page must remain busy, the others not. */ - if (reqpage != i) { - m[i]->oflags &= ~VPO_BUSY; - m[i]->busy = 0; - } + if (i == reqpage) + vm_page_flash(m[i]); + else + vm_page_wakeup(m[i]); } return (VM_PAGER_OK); } -- cgit v1.1 From 44c384aeff9f351d68878b89edebf255a4d96fe8 Mon Sep 17 00:00:00 2001 From: kib Date: Mon, 3 May 2010 20:31:13 +0000 Subject: Lock the page around vm_page_activate() and vm_page_deactivate() calls where it was missed. The wrapped fragments now protect wire_count with page lock. Reviewed by: alc --- sys/dev/md/md.c | 2 ++ sys/fs/nfsclient/nfs_clbio.c | 8 ++++++-- sys/fs/nwfs/nwfs_io.c | 8 ++++++-- sys/fs/smbfs/smbfs_io.c | 8 ++++++-- sys/nfsclient/nfs_bio.c | 8 ++++++-- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 78f2af3..edd687f 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -665,11 +665,13 @@ mdstart_swap(struct md_s *sc, struct bio *bp) sf_buf_free(sf); sched_unpin(); vm_page_wakeup(m); + vm_page_lock(m); vm_page_lock_queues(); vm_page_activate(m); if (bp->bio_cmd == BIO_WRITE) vm_page_dirty(m); vm_page_unlock_queues(); + vm_page_unlock(m); /* Actions on further pages start at offset 0 */ p += PAGE_SIZE - offs; diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c index 2401c88..e23da72 100644 --- a/sys/fs/nfsclient/nfs_clbio.c +++ b/sys/fs/nfsclient/nfs_clbio.c @@ -192,12 +192,14 @@ ncl_getpages(struct vop_getpages_args *ap) size = count - uio.uio_resid; VM_OBJECT_LOCK(object); - vm_page_lock_queues(); for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { vm_page_t m; nextoff = toff + PAGE_SIZE; m = pages[i]; + vm_page_lock(m); + vm_page_lock_queues(); + if (nextoff <= size) { /* * Read operation filled an entire page @@ -244,8 +246,10 @@ ncl_getpages(struct vop_getpages_args *ap) vm_page_free(m); } } + + vm_page_unlock_queues(); + vm_page_unlock(m); } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return (0); } diff --git a/sys/fs/nwfs/nwfs_io.c b/sys/fs/nwfs/nwfs_io.c index 75b1c18..ef1c800 100644 --- a/sys/fs/nwfs/nwfs_io.c +++ b/sys/fs/nwfs/nwfs_io.c @@ -449,12 +449,14 @@ nwfs_getpages(ap) size = count - uio.uio_resid; - vm_page_lock_queues(); for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { vm_page_t m; nextoff = toff + PAGE_SIZE; m = pages[i]; + vm_page_lock(m); + vm_page_lock_queues(); + if (nextoff <= size) { m->valid = VM_PAGE_BITS_ALL; KASSERT(m->dirty == 0, @@ -489,8 +491,10 @@ nwfs_getpages(ap) vm_page_free(m); } } + + vm_page_unlock_queues(); + vm_page_unlock(m); } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return 0; #endif /* NWFS_RWCACHE */ diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c index df779a6..6537ed4 100644 --- a/sys/fs/smbfs/smbfs_io.c +++ b/sys/fs/smbfs/smbfs_io.c @@ -500,12 +500,14 @@ smbfs_getpages(ap) size = count - uio.uio_resid; - vm_page_lock_queues(); for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { vm_page_t m; nextoff = toff + PAGE_SIZE; m = pages[i]; + vm_page_lock(m); + vm_page_lock_queues(); + if (nextoff <= size) { /* * Read operation filled an entire page @@ -553,8 +555,10 @@ smbfs_getpages(ap) vm_page_free(m); } } + + vm_page_unlock_queues(); + vm_page_unlock(m); } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return 0; #endif /* SMBFS_RWGENERIC */ diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index cec0220..3a0705e 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -189,12 +189,14 @@ nfs_getpages(struct vop_getpages_args *ap) size = count - uio.uio_resid; VM_OBJECT_LOCK(object); - vm_page_lock_queues(); for (i = 0, toff = 0; i < npages; i++, toff = nextoff) { vm_page_t m; nextoff = toff + PAGE_SIZE; m = pages[i]; + vm_page_lock(m); + vm_page_lock_queues(); + if (nextoff <= size) { /* * Read operation filled an entire page @@ -241,8 +243,10 @@ nfs_getpages(struct vop_getpages_args *ap) vm_page_free(m); } } + + vm_page_unlock_queues(); + vm_page_unlock(m); } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return (0); } -- cgit v1.1 From 62ac1402386af7474fef7be2630ba8f48ac444e9 Mon Sep 17 00:00:00 2001 From: marius Date: Mon, 3 May 2010 20:57:16 +0000 Subject: - Don't set CAS_PCS_DATAPATH to anything except CAS_PCS_DATAPATH_SERDES on Cassini using the external PCS SERDES otherwise unaligned access traps and other strange effects happen with some machines. Don't touch the MIF which is unused in that case either. These changes require the PHY type to use to be determined via the OFW device tree or from the VPD in machines without the former. - Disable the SERDES pins of Saturn when not used in order to save power and ensure they are enabled otherwise. - In cas_attach() use the correct register offset for CAS_PCS_CONF_EN. - Add some bus space barriers missing in the PCS code path. These changes make the Sun GigaSwift Ethernet 1.0 MMF cards as well as the on-board interfaces found in Sun Fire B100s Blade Server work. PR: 144867 --- sys/dev/cas/if_cas.c | 232 +++++++++++++++++++++++++++++++++--------------- sys/dev/cas/if_casreg.h | 12 +++ 2 files changed, 174 insertions(+), 70 deletions(-) diff --git a/sys/dev/cas/if_cas.c b/sys/dev/cas/if_cas.c index edcfec4..3522f7c 100644 --- a/sys/dev/cas/if_cas.c +++ b/sys/dev/cas/if_cas.c @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); #include #if defined(__powerpc__) || defined(__sparc64__) +#include #include #include #endif @@ -321,55 +322,82 @@ cas_attach(struct cas_softc *sc) } } - CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_MII); - - cas_mifinit(sc); - - /* - * Look for an external PHY. - */ - error = ENXIO; - v = CAS_READ_4(sc, CAS_MIF_CONF); - if ((v & CAS_MIF_CONF_MDI1) != 0) { - v |= CAS_MIF_CONF_PHY_SELECT; - CAS_WRITE_4(sc, CAS_MIF_CONF, v); - switch (sc->sc_variant) { - default: - sc->sc_phyad = -1; - break; + if ((sc->sc_flags & CAS_SERDES) == 0) { + CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_MII); + CAS_BARRIER(sc, CAS_PCS_DATAPATH, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); + cas_mifinit(sc); + /* + * Look for an external PHY. + */ + error = ENXIO; + v = CAS_READ_4(sc, CAS_MIF_CONF); + if ((v & CAS_MIF_CONF_MDI1) != 0) { + v |= CAS_MIF_CONF_PHY_SELECT; + CAS_WRITE_4(sc, CAS_MIF_CONF, v); + CAS_BARRIER(sc, CAS_MIF_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); + /* Enable/unfreeze the GMII pins of Saturn. */ + if (sc->sc_variant == CAS_SATURN) { + CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0); + CAS_BARRIER(sc, CAS_SATURN_PCFG, 4, + BUS_SPACE_BARRIER_READ | + BUS_SPACE_BARRIER_WRITE); + } + switch (sc->sc_variant) { + default: + sc->sc_phyad = -1; + break; + } + error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, + cas_mediachange, cas_mediastatus); } - error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, - cas_mediachange, cas_mediastatus); - } - - /* - * Fall back on an internal PHY if no external PHY was found. - */ - if (error != 0 && (v & CAS_MIF_CONF_MDI0) != 0) { - v &= ~CAS_MIF_CONF_PHY_SELECT; - CAS_WRITE_4(sc, CAS_MIF_CONF, v); - switch (sc->sc_variant) { - default: - sc->sc_phyad = -1; - break; + /* + * Fall back on an internal PHY if no external PHY was found. + */ + if (error != 0 && (v & CAS_MIF_CONF_MDI0) != 0) { + v &= ~CAS_MIF_CONF_PHY_SELECT; + CAS_WRITE_4(sc, CAS_MIF_CONF, v); + CAS_BARRIER(sc, CAS_MIF_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); + /* Freeze the GMII pins of Saturn for saving power. */ + if (sc->sc_variant == CAS_SATURN) { + CAS_WRITE_4(sc, CAS_SATURN_PCFG, + CAS_SATURN_PCFG_FSI); + CAS_BARRIER(sc, CAS_SATURN_PCFG, 4, + BUS_SPACE_BARRIER_READ | + BUS_SPACE_BARRIER_WRITE); + } + switch (sc->sc_variant) { + default: + sc->sc_phyad = -1; + break; + } + error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, + cas_mediachange, cas_mediastatus); } - error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, - cas_mediachange, cas_mediastatus); - } - - /* - * Try the external PCS SERDES if we didn't find any PHYs. - */ - if (error != 0) { + } else { + /* + * Use the external PCS SERDES. + */ CAS_WRITE_4(sc, CAS_PCS_DATAPATH, CAS_PCS_DATAPATH_SERDES); + CAS_BARRIER(sc, CAS_PCS_DATAPATH, 4, BUS_SPACE_BARRIER_WRITE); + /* Enable/unfreeze the SERDES pins of Saturn. */ + if (sc->sc_variant == CAS_SATURN) { + CAS_WRITE_4(sc, CAS_SATURN_PCFG, 0); + CAS_BARRIER(sc, CAS_SATURN_PCFG, 4, + BUS_SPACE_BARRIER_WRITE); + } CAS_WRITE_4(sc, CAS_PCS_SERDES_CTRL, CAS_PCS_SERDES_CTRL_ESD); - CAS_WRITE_4(sc, CAS_PCS_CONF_EN, CAS_PCS_CONF_EN); - sc->sc_flags |= CAS_SERDES; + CAS_BARRIER(sc, CAS_PCS_SERDES_CTRL, 4, + BUS_SPACE_BARRIER_WRITE); + CAS_WRITE_4(sc, CAS_PCS_CONF, CAS_PCS_CONF_EN); + CAS_BARRIER(sc, CAS_PCS_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); sc->sc_phyad = CAS_PHYAD_EXTERNAL; error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, cas_mediachange, cas_mediastatus); } - if (error != 0) { device_printf(sc->sc_dev, "PHY probe failed: %d\n", error); goto fail_rxmap; @@ -956,8 +984,9 @@ cas_init_locked(struct cas_softc *sc) __func__); #endif - /* Re-initialize the MIF. */ - cas_mifinit(sc); + if ((sc->sc_flags & CAS_SERDES) == 0) + /* Re-initialize the MIF. */ + cas_mifinit(sc); /* step 3. Setup data structures in host memory. */ cas_meminit(sc); @@ -2105,6 +2134,8 @@ cas_mifinit(struct cas_softc *sc) /* Configure the MIF in frame mode. */ CAS_WRITE_4(sc, CAS_MIF_CONF, CAS_READ_4(sc, CAS_MIF_CONF) & ~CAS_MIF_CONF_BB_MODE); + CAS_BARRIER(sc, CAS_MIF_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); } /* @@ -2219,10 +2250,16 @@ cas_mii_writereg(device_t dev, int phy, int reg, int val) CAS_BARRIER(sc, CAS_PCS_CONF, 4, BUS_SPACE_BARRIER_WRITE); CAS_WRITE_4(sc, CAS_PCS_ANAR, val); + CAS_BARRIER(sc, CAS_PCS_ANAR, 4, + BUS_SPACE_BARRIER_WRITE); CAS_WRITE_4(sc, CAS_PCS_SERDES_CTRL, CAS_PCS_SERDES_CTRL_ESD); + CAS_BARRIER(sc, CAS_PCS_CONF, 4, + BUS_SPACE_BARRIER_WRITE); CAS_WRITE_4(sc, CAS_PCS_CONF, CAS_PCS_CONF_EN); + CAS_BARRIER(sc, CAS_PCS_CONF, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); return (0); case MII_ANLPAR: reg = CAS_PCS_ANLPAR; @@ -2233,6 +2270,8 @@ cas_mii_writereg(device_t dev, int phy, int reg, int val) return (0); } CAS_WRITE_4(sc, reg, val); + CAS_BARRIER(sc, reg, 4, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); return (0); } @@ -2630,15 +2669,20 @@ static struct resource_spec cas_pci_res_spec[] = { { -1, 0 } }; +#define CAS_LOCAL_MAC_ADDRESS "local-mac-address" +#define CAS_PHY_INTERFACE "phy-interface" +#define CAS_PHY_TYPE "phy-type" +#define CAS_PHY_TYPE_PCS "pcs" + static int cas_pci_attach(device_t dev) { + char buf[sizeof(CAS_LOCAL_MAC_ADDRESS)]; struct cas_softc *sc; int i; #if !(defined(__powerpc__) || defined(__sparc64__)) u_char enaddr[4][ETHER_ADDR_LEN]; - char lma[sizeof("local-mac-address")]; - int found, j; + u_int j, k, lma, pcs[4], phy; #endif sc = device_get_softc(dev); @@ -2679,13 +2723,20 @@ cas_pci_attach(device_t dev) #if defined(__powerpc__) || defined(__sparc64__) OF_getetheraddr(dev, sc->sc_enaddr); + if (OF_getprop(ofw_bus_get_node(dev), CAS_PHY_INTERFACE, buf, + sizeof(buf)) > 0 || OF_getprop(ofw_bus_get_node(dev), + CAS_PHY_TYPE, buf, sizeof(buf)) > 0) { + buf[sizeof(buf) - 1] = '\0'; + if (strcmp(buf, CAS_PHY_TYPE_PCS) == 0) + sc->sc_flags |= CAS_SERDES; + } #else /* - * Dig out VPD (vital product data) and read the MAX address. - * The VPD resides in the PCI Expansion ROM (PCI FCode) and - * can't be accessed via the PCI capability pointer. - * SUNW,pci-ce and SUNW,pci-qge use the Enhanced VPD format - * described in US Patent 7149820. + * Dig out VPD (vital product data) and read the MAC address as well + * as the PHY type. The VPD resides in the PCI Expansion ROM (PCI + * FCode) and can't be accessed via the PCI capability pointer. + * SUNW,pci-ce and SUNW,pci-qge use the Enhanced VPD format described + * in the free US Patent 7149820. */ #define PCI_ROMHDR_SIZE 0x1c @@ -2719,7 +2770,10 @@ cas_pci_attach(device_t dev) #define CAS_ROM_READ_4(sc, offs) \ CAS_READ_4((sc), CAS_PCI_ROM_OFFSET + (offs)) - found = 0; + lma = phy = 0; + memset(enaddr, 0, sizeof(enaddr)); + memset(pcs, 0, sizeof(pcs)); + /* Enable PCI Expansion ROM access. */ CAS_WRITE_4(sc, CAS_BIM_LDEV_OEN, CAS_BIM_LDEV_OEN_PAD | CAS_BIM_LDEV_OEN_PROM); @@ -2768,23 +2822,51 @@ cas_pci_attach(device_t dev) if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE) != 'I') /* no instance property */ continue; - if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) != 'B') - /* no byte array */ - continue; - if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 4) != - ETHER_ADDR_LEN) - continue; - bus_read_region_1(sc->sc_res[CAS_RES_MEM], - CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5, - lma, sizeof(lma)); - if (strcmp(lma, "local-mac-address") != 0) - continue; - bus_read_region_1(sc->sc_res[CAS_RES_MEM], - CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5 + - sizeof(lma), enaddr[found], - sizeof(enaddr[found])); - if (found++ == 4) - break; + if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) == 'B') { + /* byte array */ + if (CAS_ROM_READ_1(sc, + j + PCI_VPD_SIZE + 4) != ETHER_ADDR_LEN) + continue; + bus_read_region_1(sc->sc_res[CAS_RES_MEM], + CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5, + buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + if (strcmp(buf, CAS_LOCAL_MAC_ADDRESS) != 0) + continue; + bus_read_region_1(sc->sc_res[CAS_RES_MEM], + CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + + 5 + sizeof(CAS_LOCAL_MAC_ADDRESS), + enaddr[lma], sizeof(enaddr[lma])); + lma++; + if (lma == 4 && phy == 4) + break; + } else if (CAS_ROM_READ_1(sc, j + PCI_VPD_SIZE + 3) == + 'S') { + /* string */ + if (CAS_ROM_READ_1(sc, + j + PCI_VPD_SIZE + 4) != + sizeof(CAS_PHY_TYPE_PCS)) + continue; + bus_read_region_1(sc->sc_res[CAS_RES_MEM], + CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + 5, + buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + if (strcmp(buf, CAS_PHY_INTERFACE) == 0) + k = sizeof(CAS_PHY_INTERFACE); + else if (strcmp(buf, CAS_PHY_TYPE) == 0) + k = sizeof(CAS_PHY_TYPE); + else + continue; + bus_read_region_1(sc->sc_res[CAS_RES_MEM], + CAS_PCI_ROM_OFFSET + j + PCI_VPD_SIZE + + 5 + k, buf, sizeof(buf)); + buf[sizeof(buf) - 1] = '\0'; + if (strcmp(buf, CAS_PHY_TYPE_PCS) == 0) + pcs[phy] = 1; + phy++; + if (lma == 4 && phy == 4) + break; + } } break; default: @@ -2795,14 +2877,24 @@ cas_pci_attach(device_t dev) fail_prom: CAS_WRITE_4(sc, CAS_BIM_LDEV_OEN, 0); - if (found == 0) { + if (lma == 0) { device_printf(dev, "could not determine Ethernet address\n"); goto fail; } i = 0; - if (found > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr)) + if (lma > 1 && pci_get_slot(dev) < sizeof(enaddr) / sizeof(*enaddr)) i = pci_get_slot(dev); memcpy(sc->sc_enaddr, enaddr[i], ETHER_ADDR_LEN); + + if (phy == 0) { + device_printf(dev, "could not determine PHY type\n"); + goto fail; + } + i = 0; + if (phy > 1 && pci_get_slot(dev) < sizeof(pcs) / sizeof(*pcs)) + i = pci_get_slot(dev); + if (pcs[i] != 0) + sc->sc_flags |= CAS_SERDES; #endif if (cas_attach(sc) != 0) { diff --git a/sys/dev/cas/if_casreg.h b/sys/dev/cas/if_casreg.h index 97250e0..0d1c1d8 100644 --- a/sys/dev/cas/if_casreg.h +++ b/sys/dev/cas/if_casreg.h @@ -68,6 +68,7 @@ #define CAS_STATUS4 0x105c /* interrupt status 4 for INTD */ #define CAS_CLEAR_ALIAS4 0x1060 /* clear mask alias 4 for INTD */ #define CAS_STATUS_ALIAS4 0x1064 /* interrupt status alias 4 for INTD */ +#define CAS_SATURN_PCFG 0x106c /* internal MACPHY pin configuration */ #define CAS_CAW_RX_WGHT_MASK 0x00000003 /* RX DMA factor for... */ #define CAS_CAW_RX_WGHT_SHFT 0 /* ...weighted round robin */ @@ -171,6 +172,17 @@ /* INTn enable bit for CAS_INTMASK[2-4] */ #define CAS_INTMASKN_EN 0x00000080 /* INT[B-D] enable */ +#define CAS_SATURN_PCFG_TLA 0x00000001 /* PHY activity LED */ +#define CAS_SATURN_PCFG_FLA 0x00000002 /* PHY 10MBit/sec LED */ +#define CAS_SATURN_PCFG_CLA 0x00000004 /* PHY 100MBit/sec LED */ +#define CAS_SATURN_PCFG_LLA 0x00000008 /* PHY 1000MBit/sec LED */ +#define CAS_SATURN_PCFG_RLA 0x00000010 /* PHY full-duplex LED */ +#define CAS_SATURN_PCFG_PDS 0x00000020 /* PHY debug mode */ +#define CAS_SATURN_PCFG_MTP 0x00000080 /* test point select */ +#define CAS_SATURN_PCFG_GMO 0x00000100 /* GMII observe */ +#define CAS_SATURN_PCFG_FSI 0x00000200 /* freeze GMII/SERDES */ +#define CAS_SATURN_PCFG_LAD 0x00000800 /* MAC LED control active low */ + /* TX DMA registers */ #define CAS_TX_CONF 0x2004 /* TX configuration */ #define CAS_TX_FIFO_WR 0x2014 /* FIFO write pointer */ -- cgit v1.1 From 6cc3e84fc57d3e53aacd21e1bfe70e3c371f5568 Mon Sep 17 00:00:00 2001 From: marius Date: Mon, 3 May 2010 20:59:27 +0000 Subject: Sun GigaSwift Ethernet 1.0 MMF work with r207585 in place. --- share/man/man4/cas.4 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/share/man/man4/cas.4 b/share/man/man4/cas.4 index 7851a99..cc050c9 100644 --- a/share/man/man4/cas.4 +++ b/share/man/man4/cas.4 @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 15, 2009 +.Dd May 3, 2010 .Dt CAS 4 .Os .Sh NAME @@ -91,6 +91,9 @@ driver at this time: .Pp .Bl -bullet -compact .It +Sun GigaSwift Ethernet 1.0 MMF (Cassini Kuheen) +(part no.\& 501-5524) +.It Sun GigaSwift Ethernet 1.0 UTP (Cassini) (part no.\& 501-5902) .It -- cgit v1.1 From 501d94ef3e63bec25d5648e2565cfc1b931d745f Mon Sep 17 00:00:00 2001 From: emaste Date: Mon, 3 May 2010 22:32:26 +0000 Subject: Update GRANDPARENTED text to match the contents of tzdata/factory r19879. This eliminates "warning: time zone abbreviation differs from POSIX" on installworld to an empty filesystem. Reviewed by: edwin MFC after: 1 week --- contrib/tzcode/zic/private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/tzcode/zic/private.h b/contrib/tzcode/zic/private.h index ecbf612..d00bf9b 100644 --- a/contrib/tzcode/zic/private.h +++ b/contrib/tzcode/zic/private.h @@ -34,7 +34,7 @@ static const char privatehid[] = "@(#)private.h 8.6"; #endif /* !defined NOID */ #endif /* !defined lint */ -#define GRANDPARENTED "Local time zone must be set--see zic manual page" +#define GRANDPARENTED "Local time zone must be set--use tzsetup" /* ** Defaults for preprocessor symbols. -- cgit v1.1 From 955bde9203045e8ccb881251aaa8dd6b3b1f8fcb Mon Sep 17 00:00:00 2001 From: dougb Date: Tue, 4 May 2010 01:46:58 +0000 Subject: Make address assignment via ipv6_prefix_IF work again --- etc/network.subr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/etc/network.subr b/etc/network.subr index 52c99db..d0b309a 100644 --- a/etc/network.subr +++ b/etc/network.subr @@ -399,6 +399,8 @@ ipv6if() $_if|"$_if "*|*" $_if"|*" $_if "*|[Aa][Uu][Tt][Oo]) # True if $ifconfig_IF_ipv6 is defined. _tmpargs=`_ifconfig_getargs $_if ipv6` + # Also true if ipv6_prefix_IF is defined + [ -n "$_tmpargs" ] || _tmpargs=`get_if_var $_if ipv6_prefix_IF` ;; esac -- cgit v1.1 From b4c448d619110c73d14b1d3e70dbb616e4e20ed5 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 4 May 2010 05:47:17 +0000 Subject: Move definition of struct rusage_ext before struct thread. MFC after: 1 week --- sys/sys/proc.h | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/sys/sys/proc.h b/sys/sys/proc.h index fb31cfc..24c918e 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -173,6 +173,27 @@ struct kdtrace_thread; struct cpuset; /* + * XXX: Does this belong in resource.h or resourcevar.h instead? + * Resource usage extension. The times in rusage structs in the kernel are + * never up to date. The actual times are kept as runtimes and tick counts + * (with control info in the "previous" times), and are converted when + * userland asks for rusage info. Backwards compatibility prevents putting + * this directly in the user-visible rusage struct. + * + * Locking for p_rux: (cj) means (j) for p_rux and (c) for p_crux. + * Locking for td_rux: (t) for all fields. + */ +struct rusage_ext { + u_int64_t rux_runtime; /* (cj) Real time. */ + u_int64_t rux_uticks; /* (cj) Statclock hits in user mode. */ + u_int64_t rux_sticks; /* (cj) Statclock hits in sys mode. */ + u_int64_t rux_iticks; /* (cj) Statclock hits in intr mode. */ + u_int64_t rux_uu; /* (c) Previous user time in usec. */ + u_int64_t rux_su; /* (c) Previous sys time in usec. */ + u_int64_t rux_tu; /* (c) Previous total time in usec. */ +}; + +/* * Kernel runnable context (thread). * This is what is put to sleep and reactivated. * Thread context. Processes may have multiple threads. @@ -426,26 +447,6 @@ do { \ #define TD_SET_CAN_RUN(td) (td)->td_state = TDS_CAN_RUN /* - * XXX: Does this belong in resource.h or resourcevar.h instead? - * Resource usage extension. The times in rusage structs in the kernel are - * never up to date. The actual times are kept as runtimes and tick counts - * (with control info in the "previous" times), and are converted when - * userland asks for rusage info. Backwards compatibility prevents putting - * this directly in the user-visible rusage struct. - * - * Locking: (cj) means (j) for p_rux and (c) for p_crux. - */ -struct rusage_ext { - u_int64_t rux_runtime; /* (cj) Real time. */ - u_int64_t rux_uticks; /* (cj) Statclock hits in user mode. */ - u_int64_t rux_sticks; /* (cj) Statclock hits in sys mode. */ - u_int64_t rux_iticks; /* (cj) Statclock hits in intr mode. */ - u_int64_t rux_uu; /* (c) Previous user time in usec. */ - u_int64_t rux_su; /* (c) Previous sys time in usec. */ - u_int64_t rux_tu; /* (c) Previous total time in usec. */ -}; - -/* * Process structure. */ struct proc { -- cgit v1.1 From d84ce0b37bb086689cb7019c3e58d907993c5e09 Mon Sep 17 00:00:00 2001 From: alc Date: Tue, 4 May 2010 05:55:19 +0000 Subject: Add lock assertions. --- sys/vm/vm_page.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index e18e7ba..d9288d9 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1385,6 +1385,7 @@ vm_page_activate(vm_page_t m) { mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); if (VM_PAGE_GETKNOWNQUEUE2(m) != PQ_ACTIVE) { vm_pageq_remove(m); if (m->wire_count == 0 && (m->flags & PG_UNMANAGED) == 0) { @@ -1588,8 +1589,10 @@ void vm_page_unwire(vm_page_t m, int activate) { - if ((m->flags & PG_UNMANAGED) == 0) + if ((m->flags & PG_UNMANAGED) == 0) { mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); + } if (m->flags & PG_FICTITIOUS) return; if (m->wire_count > 0) { @@ -1626,6 +1629,7 @@ _vm_page_deactivate(vm_page_t m, int athead) { mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); /* * Ignore if already inactive. @@ -1845,6 +1849,8 @@ vm_page_dontneed(vm_page_t m) int head; mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); + VM_OBJECT_LOCK_ASSERT(m->object, MA_OWNED); dnw = ++dnweight; /* -- cgit v1.1 From b13e838a49a86619bcc78aaa13a3fdcc17293aa5 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 4 May 2010 05:55:37 +0000 Subject: Implement RUSAGE_THREAD. Add td_rux to keep extended runtime and ticks information for thread to allow calcru1() (re)use. Rename ruxagg()->ruxagg_locked(), ruxagg_tlock()->ruxagg() [1]. The ruxagg_locked() function no longer clears thread ticks nor td_incruntime. Requested by: attilio [1] Discussed with: attilio, bde Reviewed by: bde Based on submission by: Alexander Krizhanovsky MFC after: 1 week X-MFC-Note: td_rux shall be moved to the end of struct thread --- sys/kern/kern_resource.c | 33 ++++++++++++++++++++++----------- sys/kern/kern_thread.c | 2 +- sys/sys/proc.h | 3 ++- sys/sys/resource.h | 1 + sys/sys/resourcevar.h | 2 +- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index a3ed75d..0bc78d0 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -76,7 +76,7 @@ static void calcru1(struct proc *p, struct rusage_ext *ruxp, struct timeval *up, struct timeval *sp); static int donice(struct thread *td, struct proc *chgp, int n); static struct uidinfo *uilookup(uid_t uid); -static void ruxagg_tlock(struct proc *p, struct thread *td); +static void ruxagg(struct proc *p, struct thread *td); /* * Resource controls and accounting. @@ -630,7 +630,7 @@ lim_cb(void *arg) return; PROC_SLOCK(p); FOREACH_THREAD_IN_PROC(p, td) { - ruxagg_tlock(p, td); + ruxagg(p, td); } PROC_SUNLOCK(p); if (p->p_rux.rux_runtime > p->p_cpulimit * cpu_tickrate()) { @@ -841,7 +841,7 @@ calcru(struct proc *p, struct timeval *up, struct timeval *sp) FOREACH_THREAD_IN_PROC(p, td) { if (td->td_incruntime == 0) continue; - ruxagg_tlock(p, td); + ruxagg(p, td); } calcru1(p, &p->p_rux, up, sp); } @@ -961,6 +961,16 @@ kern_getrusage(struct thread *td, int who, struct rusage *rup) calccru(p, &rup->ru_utime, &rup->ru_stime); break; + case RUSAGE_THREAD: + PROC_SLOCK(p); + ruxagg(p, td); + PROC_SUNLOCK(p); + thread_lock(td); + *rup = td->td_ru; + calcru1(p, &td->td_rux, &rup->ru_utime, &rup->ru_stime); + thread_unlock(td); + break; + default: error = EINVAL; } @@ -1001,7 +1011,7 @@ ruadd(struct rusage *ru, struct rusage_ext *rux, struct rusage *ru2, * Aggregate tick counts into the proc's rusage_ext. */ void -ruxagg(struct rusage_ext *rux, struct thread *td) +ruxagg_locked(struct rusage_ext *rux, struct thread *td) { THREAD_LOCK_ASSERT(td, MA_OWNED); @@ -1010,18 +1020,19 @@ ruxagg(struct rusage_ext *rux, struct thread *td) rux->rux_uticks += td->td_uticks; rux->rux_sticks += td->td_sticks; rux->rux_iticks += td->td_iticks; - td->td_incruntime = 0; - td->td_uticks = 0; - td->td_iticks = 0; - td->td_sticks = 0; } static void -ruxagg_tlock(struct proc *p, struct thread *td) +ruxagg(struct proc *p, struct thread *td) { thread_lock(td); - ruxagg(&p->p_rux, td); + ruxagg_locked(&p->p_rux, td); + ruxagg_locked(&td->td_rux, td); + td->td_incruntime = 0; + td->td_uticks = 0; + td->td_iticks = 0; + td->td_sticks = 0; thread_unlock(td); } @@ -1039,7 +1050,7 @@ rufetch(struct proc *p, struct rusage *ru) *ru = p->p_ru; if (p->p_numthreads > 0) { FOREACH_THREAD_IN_PROC(p, td) { - ruxagg_tlock(p, td); + ruxagg(p, td); rucollect(ru, &td->td_ru); } } diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 9be4c2f3e..b32c584 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -432,7 +432,7 @@ thread_exit(void) PROC_UNLOCK(p); thread_lock(td); /* Save our tick information with both the thread and proc locked */ - ruxagg(&p->p_rux, td); + ruxagg_locked(&p->p_rux, td); PROC_SUNLOCK(p); td->td_state = TDS_INACTIVE; #ifdef WITNESS diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 24c918e..e32e494 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -240,7 +240,8 @@ struct thread { u_int td_estcpu; /* (t) estimated cpu utilization */ int td_slptick; /* (t) Time at sleep. */ int td_blktick; /* (t) Time spent blocked. */ - struct rusage td_ru; /* (t) rusage information */ + struct rusage td_ru; /* (t) rusage information. */ + struct rusage_ext td_rux; /* (t) Internal rusage information. */ uint64_t td_incruntime; /* (t) Cpu ticks to transfer to proc. */ uint64_t td_runtime; /* (t) How many cpu ticks we've run. */ u_int td_pticks; /* (t) Statclock hits for profiling */ diff --git a/sys/sys/resource.h b/sys/sys/resource.h index 9af96af..e703744 100644 --- a/sys/sys/resource.h +++ b/sys/sys/resource.h @@ -56,6 +56,7 @@ #define RUSAGE_SELF 0 #define RUSAGE_CHILDREN -1 +#define RUSAGE_THREAD 1 struct rusage { struct timeval ru_utime; /* user time used */ diff --git a/sys/sys/resourcevar.h b/sys/sys/resourcevar.h index 21728aa..95a9b49 100644 --- a/sys/sys/resourcevar.h +++ b/sys/sys/resourcevar.h @@ -131,7 +131,7 @@ void rucollect(struct rusage *ru, struct rusage *ru2); void rufetch(struct proc *p, struct rusage *ru); void rufetchcalc(struct proc *p, struct rusage *ru, struct timeval *up, struct timeval *sp); -void ruxagg(struct rusage_ext *rux, struct thread *td); +void ruxagg_locked(struct rusage_ext *rux, struct thread *td); int suswintr(void *base, int word); struct uidinfo *uifind(uid_t uid); -- cgit v1.1 From 7ef4b25b493ecc8b5b7b82de0819410d04bfb4a4 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 4 May 2010 06:00:39 +0000 Subject: Use td_rux.rux_runtime for ki_runtime instead of redoing calculation. Submitted by: bde MFC after: 1 week --- sys/kern/kern_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 49a3097..6c50f1f 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -901,7 +901,7 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread) kp->ki_pri.pri_user = td->td_user_pri; if (preferthread) { - kp->ki_runtime = cputick2usec(td->td_runtime); + kp->ki_runtime = td->td_rux.rux_runtime; kp->ki_pctcpu = sched_pctcpu(td); kp->ki_estcpu = td->td_estcpu; } -- cgit v1.1 From ed0171604743ee3c9a1dadd422311f569b021ffe Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 4 May 2010 06:01:25 +0000 Subject: Document RUSAGE_THREAD. Reviewed by: bde MFC after: 1 week --- lib/libc/sys/getrusage.2 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/libc/sys/getrusage.2 b/lib/libc/sys/getrusage.2 index bdf5d45..423503f 100644 --- a/lib/libc/sys/getrusage.2 +++ b/lib/libc/sys/getrusage.2 @@ -28,7 +28,7 @@ .\" @(#)getrusage.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd June 4, 1993 +.Dd May 1, 2010 .Dt GETRUSAGE 2 .Os .Sh NAME @@ -42,6 +42,7 @@ .In sys/resource.h .Fd "#define RUSAGE_SELF 0" .Fd "#define RUSAGE_CHILDREN -1" +.Fd "#define RUSAGE_THREAD 1" .Ft int .Fn getrusage "int who" "struct rusage *rusage" .Sh DESCRIPTION @@ -49,11 +50,12 @@ The .Fn getrusage system call returns information describing the resources utilized by the current -process, or all its terminated child processes. +thread, the current process, or all its terminated child processes. The .Fa who argument is either -.Dv RUSAGE_SELF +.Dv RUSAGE_THREAD , +.Dv RUSAGE_SELF , or .Dv RUSAGE_CHILDREN . The buffer to which @@ -175,6 +177,10 @@ The .Fn getrusage system call appeared in .Bx 4.2 . +The +.Dv RUSAGE_THREAD +facility first appeared in +.Fx 8.1 . .Sh BUGS There is no way to obtain information about a child process that has not yet terminated. -- cgit v1.1 From e5f4727bbf133c7d282ecf204252dffd31efc2e0 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 4 May 2010 06:04:33 +0000 Subject: Remove a comment that merely repeats code. Submitted by: bde MFC after: 1 week --- sys/kern/kern_thread.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index b32c584..dd5cb62 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -431,7 +431,6 @@ thread_exit(void) #endif PROC_UNLOCK(p); thread_lock(td); - /* Save our tick information with both the thread and proc locked */ ruxagg_locked(&p->p_rux, td); PROC_SUNLOCK(p); td->td_state = TDS_INACTIVE; -- cgit v1.1 From 26be0345aa14384c33fae1f5a109807c74c4fe07 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 4 May 2010 06:06:01 +0000 Subject: Fix typo in comment. MFC after: 3 days --- sys/kern/kern_thread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index dd5cb62..d7a9199 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -398,7 +398,7 @@ thread_exit(void) /* * The test below is NOT true if we are the - * sole exiting thread. P_STOPPED_SNGL is unset + * sole exiting thread. P_STOPPED_SINGLE is unset * in exit1() after it is the only survivor. */ if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) { -- cgit v1.1 From 338b266e1a4c51244efd34c38dab2946bab967da Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 4 May 2010 06:13:17 +0000 Subject: Go ahead and merge the work edwin@ on tftpd into the tree. It is a lot better than what's in the tree now. Edwin tested it at a prior employer, but can't test it today. I've found that it works a lot better with the various uboot versions that I've used in my embedded work. Here's the pkg-descr from the port that describes the changes: It all started when we got some new routers, which told me the following when trying to upload configuration or download images from it: The TFTP server doesn't support the blocksize option. My curiousity was triggered, it took me some reading of RFCs and other documentation to find out what was possible and what could be done. Was plain TFTP very simple in its handshake, TFTP with options was kind of messy because of its backwards capability: The first packet returned could either be an acknowledgement of options, or the first data packet. Going through the source code of src/libexec/tftpd and going through the code of src/usr.bin/tftp showed that there was a lot of duplicate code, and the addition of options would only increase the amount of duplicate code. After all, both the client and the server can act as a sender and receiver. At the end, it ended up with a nearly complete rewrite of the tftp client and server. It has been tested against the following TFTP clients and servers: - Itself (yay!) - The standard FreeBSD tftp client and server - The Fedora Core 6 tftp client and server - Cisco router tftp client - Extreme Networks tftp client It supports the following RFCs: RFC1350 - THE TFTP PROTOCOL (REVISION 2) RFC2347 - TFTP Option Extension RFC2348 - TFTP Blocksize Option RFC2349 - TFTP Timeout Interval and Transfer Size Options RFC3617 - Uniform Resource Identifier (URI) Scheme and Applicability Statement for the Trivial File Transfer Protocol (TFTP) It supports the following unofficial TFTP Options as described at http://www.compuphase.com/tftp.htm: blksize2 - Block size restricted to powers of 2, excluding protocol headers rollover - Block counter roll-over (roll back to zero or to one) From the tftp program point of view the following things are changed: - New commands: "blocksize", "blocksize2", "rollover" and "options" - Development features: "debug" and "packetdrop" If you try this tftp/tftpd implementation, please let me know if it works (or doesn't work) and against which implementaion so I can get a list of confirmed working systems. Author: Edwin Groothuis --- usr.bin/tftp/Makefile | 6 +- usr.bin/tftp/main.c | 656 +++++++++++++++++++++++++++++++++++++------------- usr.bin/tftp/tftp.1 | 60 +++-- usr.bin/tftp/tftp.c | 576 ++++++++++++++------------------------------ 4 files changed, 696 insertions(+), 602 deletions(-) diff --git a/usr.bin/tftp/Makefile b/usr.bin/tftp/Makefile index a51afed..9be599a 100644 --- a/usr.bin/tftp/Makefile +++ b/usr.bin/tftp/Makefile @@ -1,9 +1,13 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 # $FreeBSD$ +CFLAGS=-g -Wall +WARNS= 3 PROG= tftp -SRCS= main.c tftp.c tftpsubs.c +SRCS= main.c tftp.c tftp-utils.c tftp-io.c tftp-file.c tftp-transfer.c tftp-options.c DPADD= ${LIBEDIT} ${LIBTERMCAP} LDADD= -ledit -ltermcap +CFLAGS+=-I${.CURDIR}/../../libexec/tftpd -I${.CURDIR}/../../usr.bin/tftp +.PATH: ${.CURDIR}/../../libexec/tftpd .include diff --git a/usr.bin/tftp/main.c b/usr.bin/tftp/main.c index f01d3d8..26ca0244 100644 --- a/usr.bin/tftp/main.c +++ b/usr.bin/tftp/main.c @@ -54,12 +54,14 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include - #include +#include #include #include @@ -72,119 +74,212 @@ __FBSDID("$FreeBSD$"); #include #include -#include "extern.h" +#include "tftp-utils.h" +#include "tftp-io.h" +#include "tftp-options.h" +#include "tftp.h" #define MAXLINE 200 #define TIMEOUT 5 /* secs between rexmt's */ -struct sockaddr_storage peeraddr; -int f; -int trace; -int verbose; -int connected; -char mode[32]; -char line[MAXLINE]; -int margc; +static struct sockaddr_storage peeraddr; +static int connected; +static char mode[32]; +jmp_buf toplevel; +volatile int txrx_error; +static int peer; + #define MAX_MARGV 20 -char *margv[MAX_MARGV]; -jmp_buf toplevel; -volatile int txrx_error; - -void get(int, char **); -void help(int, char **); -void intr(int); -void modecmd(int, char **); -void put(int, char **); -void quit(int, char **); -void setascii(int, char **); -void setbinary(int, char **); -void setpeer0(char *, const char *); -void setpeer(int, char **); -void setrexmt(int, char **); -void settimeout(int, char **); -void settrace(int, char **); -void setverbose(int, char **); -void status(int, char **); +static int margc; +static char *margv[MAX_MARGV]; + +int verbose; +char *port = NULL; + +static void get(int, char **); +static void help(int, char **); +static void intr(int); +static void modecmd(int, char **); +static void put(int, char **); +static void quit(int, char **); +static void setascii(int, char **); +static void setbinary(int, char **); +static void setpeer0(char *, const char *); +static void setpeer(int, char **); +static void settimeoutpacket(int, char **); +static void settimeoutnetwork(int, char **); +static void setdebug(int, char **); +static void setverbose(int, char **); +static void showstatus(int, char **); +static void setblocksize(int, char **); +static void setblocksize2(int, char **); +static void setoptions(int, char **); +static void setrollover(int, char **); +static void setpacketdrop(int, char **); static void command(void) __dead2; static const char *command_prompt(void); -static void getusage(const char *); -static void makeargv(void); -static void putusage(const char *); +static void urihandling(char *URI); +static void getusage(char *); +static void makeargv(char *line); +static void putusage(char *); static void settftpmode(const char *); -char *tail(char *); -struct cmd *getcmd(char *); +static char *tail(char *); +static struct cmd *getcmd(char *); #define HELPINDENT (sizeof("connect")) struct cmd { const char *name; - char *help; void (*handler)(int, char **); + const char *help; }; -char vhelp[] = "toggle verbose mode"; -char thelp[] = "toggle packet tracing"; -char chelp[] = "connect to remote tftp"; -char qhelp[] = "exit tftp"; -char hhelp[] = "print help information"; -char shelp[] = "send file"; -char rhelp[] = "receive file"; -char mhelp[] = "set file transfer mode"; -char sthelp[] = "show current status"; -char xhelp[] = "set per-packet retransmission timeout"; -char ihelp[] = "set total retransmission timeout"; -char ashelp[] = "set mode to netascii"; -char bnhelp[] = "set mode to octet"; - -struct cmd cmdtab[] = { - { "connect", chelp, setpeer }, - { "mode", mhelp, modecmd }, - { "put", shelp, put }, - { "get", rhelp, get }, - { "quit", qhelp, quit }, - { "verbose", vhelp, setverbose }, - { "trace", thelp, settrace }, - { "status", sthelp, status }, - { "binary", bnhelp, setbinary }, - { "ascii", ashelp, setascii }, - { "rexmt", xhelp, setrexmt }, - { "timeout", ihelp, settimeout }, - { "?", hhelp, help }, - { NULL, NULL, NULL } +static struct cmd cmdtab[] = { + { "connect", setpeer, "connect to remote tftp" }, + { "mode", modecmd, "set file transfer mode" }, + { "put", put, "send file" }, + { "get", get, "receive file" }, + { "quit", quit, "exit tftp" }, + { "verbose", setverbose, "toggle verbose mode" }, + { "status", showstatus, "show current status" }, + { "binary", setbinary, "set mode to octet" }, + { "ascii", setascii, "set mode to netascii" }, + { "rexmt", settimeoutpacket, + "set per-packet retransmission timeout[-]" }, + { "timeout", settimeoutnetwork, + "set total retransmission timeout" }, + { "trace", setdebug, "enable 'debug packet'[-]" }, + { "debug", setdebug, "enable verbose output" }, + { "blocksize", setblocksize, "set blocksize[*]" }, + { "blocksize2", setblocksize2, "set blocksize as a power of 2[**]" }, + { "rollover", setrollover, "rollover after 64K packets[**]" }, + { "options", setoptions, + "enable or disable RFC2347 style options" }, + { "help", help, "print help information" }, + { "packetdrop", setpacketdrop, "artifical packetloss feature" }, + { "?", help, "print help information" }, + { NULL, NULL, NULL } +}; + +static struct modes { + const char *m_name; + const char *m_mode; +} modes[] = { + { "ascii", "netascii" }, + { "netascii", "netascii" }, + { "binary", "octet" }, + { "image", "octet" }, + { "octet", "octet" }, + { NULL, NULL } }; int main(int argc, char *argv[]) { - f = -1; + + acting_as_client = 1; + peer = -1; strcpy(mode, "netascii"); signal(SIGINT, intr); if (argc > 1) { if (setjmp(toplevel) != 0) exit(txrx_error); + + if (strncmp(argv[1], "tftp://", 7) == 0) { + urihandling(argv[1]); + exit(txrx_error); + } + setpeer(argc, argv); } if (setjmp(toplevel) != 0) (void)putchar('\n'); + + init_options(); command(); } -char hostname[MAXHOSTNAMELEN]; +/* + * RFC3617 handling of TFTP URIs: + * + * tftpURI = "tftp://" host "/" file [ mode ] + * mode = ";" "mode=" ( "netascii" / "octet" ) + * file = *( unreserved / escaped ) + * host = + * unreserved = + * escaped = + * + * We are cheating a little bit by allowing any mode as specified in the + * modes table defined earlier on in this file and mapping it on the real + * mode. + */ +static void +urihandling(char *URI) +{ + char uri[ARG_MAX]; + char *host = NULL; + char *path = NULL; + char *options = NULL; + char *mode = "octet"; + char *s; + char line[MAXLINE]; + int i; + + strncpy(uri, URI, ARG_MAX); + host = uri + 7; + + if ((s = strchr(host, '/')) == NULL) { + fprintf(stderr, + "Invalid URI: Couldn't find / after hostname\n"); + exit(1); + } + *s = '\0'; + path = s + 1; + + if ((s = strchr(path, ';')) != NULL) { + *s = '\0'; + options = s + 1; -void -setpeer0(char *host, const char *port) + if (strncmp(options, "mode=", 5) == 0) { + mode = options; + mode += 5; + + for (i = 0; modes[i].m_name != NULL; i++) { + if (strcmp(modes[i].m_name, mode) == 0) + break; + } + if (modes[i].m_name == NULL) { + fprintf(stderr, "Invalid mode: '%s'\n", mode); + exit(1); + } + settftpmode(modes[i].m_mode); + } + } else { + settftpmode("octet"); + } + + setpeer0(host, NULL); + + sprintf(line, "get %s", path); + makeargv(line); + get(margc, margv); +} + +static char hostname[MAXHOSTNAMELEN]; + +static void +setpeer0(char *host, const char *lport) { struct addrinfo hints, *res0, *res; int error; - struct sockaddr_storage ss; const char *cause = "unknown"; if (connected) { - close(f); - f = -1; + close(peer); + peer = -1; } connected = 0; @@ -193,9 +288,9 @@ setpeer0(char *host, const char *port) hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; hints.ai_flags = AI_CANONNAME; - if (!port) - port = "tftp"; - error = getaddrinfo(host, port, &hints, &res0); + if (!lport) + lport = "tftp"; + error = getaddrinfo(host, lport, &hints, &res0); if (error) { warnx("%s", gai_strerror(error)); return; @@ -204,50 +299,53 @@ setpeer0(char *host, const char *port) for (res = res0; res; res = res->ai_next) { if (res->ai_addrlen > sizeof(peeraddr)) continue; - f = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (f < 0) { + peer = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (peer < 0) { cause = "socket"; continue; } - memset(&ss, 0, sizeof(ss)); - ss.ss_family = res->ai_family; - ss.ss_len = res->ai_addrlen; - if (bind(f, (struct sockaddr *)&ss, ss.ss_len) < 0) { + memset(&peer_sock, 0, sizeof(peer_sock)); + peer_sock.ss_family = res->ai_family; + peer_sock.ss_len = res->ai_addrlen; + if (bind(peer, (struct sockaddr *)&peer_sock, peer_sock.ss_len) < 0) { cause = "bind"; - close(f); - f = -1; + close(peer); + peer = -1; continue; } break; } - if (f < 0) + if (peer < 0) warn("%s", cause); else { /* res->ai_addr <= sizeof(peeraddr) is guaranteed */ - memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); + memcpy(&peer_sock, res->ai_addr, res->ai_addrlen); if (res->ai_canonname) { - (void) strlcpy(hostname, res->ai_canonname, + (void) strncpy(hostname, res->ai_canonname, sizeof(hostname)); } else - (void) strlcpy(hostname, host, sizeof(hostname)); + (void) strncpy(hostname, host, sizeof(hostname)); + hostname[sizeof(hostname)-1] = 0; connected = 1; } freeaddrinfo(res0); } -void +static void setpeer(int argc, char *argv[]) { + char line[MAXLINE]; if (argc < 2) { strcpy(line, "Connect "); printf("(to) "); fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); - makeargv(); + makeargv(line); argc = margc; argv = margv; } @@ -255,26 +353,14 @@ setpeer(int argc, char *argv[]) printf("usage: %s [host [port]]\n", argv[0]); return; } - if (argc == 3) + if (argc == 3) { + port = argv[2]; setpeer0(argv[1], argv[2]); - else + } else setpeer0(argv[1], NULL); } -struct modes { - const char *m_name; - const char *m_mode; -} modes[] = { - { "ascii", "netascii" }, - { "netascii", "netascii" }, - { "binary", "octet" }, - { "image", "octet" }, - { "octet", "octet" }, -/* { "mail", "mail" }, */ - { 0, 0 } -}; - -void +static void modecmd(int argc, char *argv[]) { struct modes *p; @@ -298,7 +384,7 @@ modecmd(int argc, char *argv[]) printf("usage: %s [", argv[0]); sep = " "; - for (p = modes; p->m_name; p++) { + for (p = modes; p->m_name != NULL; p++) { printf("%s%s", sep, p->m_name); if (*sep == ' ') sep = " | "; @@ -307,14 +393,14 @@ modecmd(int argc, char *argv[]) return; } -void +static void setbinary(int argc __unused, char *argv[] __unused) { settftpmode("octet"); } -void +static void setascii(int argc __unused, char *argv[] __unused) { @@ -324,6 +410,7 @@ setascii(int argc __unused, char *argv[] __unused) static void settftpmode(const char *newmode) { + strcpy(mode, newmode); if (verbose) printf("mode set to %s\n", mode); @@ -333,18 +420,20 @@ settftpmode(const char *newmode) /* * Send file(s). */ -void +static void put(int argc, char *argv[]) { - int fd; - int n; - char *cp, *targ; + int fd; + int n; + char *cp, *targ; + char line[MAXLINE]; + struct stat sb; if (argc < 2) { strcpy(line, "send "); printf("(file) "); fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); - makeargv(); + makeargv(line); argc = margc; argv = margv; } @@ -381,10 +470,14 @@ put(int argc, char *argv[]) warn("%s", cp); return; } + + stat(cp, &sb); + asprintf(&options[OPT_TSIZE].o_request, "%ju", sb.st_size); + if (verbose) printf("putting %s to %s:%s [%s]\n", - cp, hostname, targ, mode); - xmitfile(fd, targ, mode); + cp, hostname, targ, mode); + xmitfile(peer, port, fd, targ, mode); return; } /* this assumes the target is a directory */ @@ -398,36 +491,43 @@ put(int argc, char *argv[]) warn("%s", argv[n]); continue; } + + stat(cp, &sb); + asprintf(&options[OPT_TSIZE].o_request, "%ju", sb.st_size); + if (verbose) printf("putting %s to %s:%s [%s]\n", - argv[n], hostname, targ, mode); - xmitfile(fd, targ, mode); + argv[n], hostname, targ, mode); + xmitfile(peer, port, fd, targ, mode); } } static void -putusage(const char *s) +putusage(char *s) { - printf("usage: %s file [[host:]remotename]\n", s); + + printf("usage: %s file [remotename]\n", s); + printf(" %s file host:remotename\n", s); printf(" %s file1 file2 ... fileN [[host:]remote-directory]\n", s); } /* * Receive file(s). */ -void +static void get(int argc, char *argv[]) { int fd; int n; char *cp; char *src; + char line[MAXLINE]; if (argc < 2) { strcpy(line, "get "); printf("(files) "); fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); - makeargv(); + makeargv(line); argc = margc; argv = margv; } @@ -438,6 +538,8 @@ get(int argc, char *argv[]) if (!connected) { for (n = 1; n < argc ; n++) if (rindex(argv[n], ':') == 0) { + printf("No remote host specified and " + "no host given for file '%s'\n", argv[n]); getusage(argv[0]); return; } @@ -468,8 +570,8 @@ get(int argc, char *argv[]) } if (verbose) printf("getting from %s:%s to %s [%s]\n", - hostname, src, cp, mode); - recvfile(fd, src, mode); + hostname, src, cp, mode); + recvfile(peer, port, fd, src, mode); break; } cp = tail(src); /* new .. jdg */ @@ -480,30 +582,31 @@ get(int argc, char *argv[]) } if (verbose) printf("getting from %s:%s to %s [%s]\n", - hostname, src, cp, mode); - recvfile(fd, src, mode); + hostname, src, cp, mode); + recvfile(peer, port, fd, src, mode); } } static void -getusage(const char *s) +getusage(char *s) { - printf("usage: %s [host:]file [localname]\n", s); + + printf("usage: %s file [localname]\n", s); + printf(" %s [host:]file [localname]\n", s); printf(" %s [host1:]file1 [host2:]file2 ... [hostN:]fileN\n", s); } -int rexmtval = TIMEOUT; - -void -setrexmt(int argc, char *argv[]) +static void +settimeoutpacket(int argc, char *argv[]) { int t; + char line[MAXLINE]; if (argc < 2) { - strcpy(line, "Rexmt-timeout "); + strcpy(line, "Packet timeout "); printf("(value) "); fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); - makeargv(); + makeargv(line); argc = margc; argv = margv; } @@ -512,24 +615,25 @@ setrexmt(int argc, char *argv[]) return; } t = atoi(argv[1]); - if (t < 0) + if (t < 0) { printf("%s: bad value\n", argv[1]); - else - rexmtval = t; -} + return; + } -int maxtimeout = 5 * TIMEOUT; + settimeouts(t, timeoutnetwork, maxtimeouts); +} -void -settimeout(int argc, char *argv[]) +static void +settimeoutnetwork(int argc, char *argv[]) { int t; + char line[MAXLINE]; if (argc < 2) { - strcpy(line, "Maximum-timeout "); + strcpy(line, "Network timeout "); printf("(value) "); fgets(&line[strlen(line)], sizeof line - strlen(line), stdin); - makeargv(); + makeargv(line); argc = margc; argv = margv; } @@ -538,26 +642,36 @@ settimeout(int argc, char *argv[]) return; } t = atoi(argv[1]); - if (t < 0) + if (t < 0) { printf("%s: bad value\n", argv[1]); - else - maxtimeout = t; + return; + } + + settimeouts(timeoutpacket, t, maxtimeouts); } -void -status(int argc __unused, char *argv[] __unused) +static void +showstatus(int argc __unused, char *argv[] __unused) { - if (connected) - printf("Connected to %s.\n", hostname); - else - printf("Not connected.\n"); - printf("Mode: %s Verbose: %s Tracing: %s\n", mode, - verbose ? "on" : "off", trace ? "on" : "off"); - printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", - rexmtval, maxtimeout); + + printf("Remote host: %s\n", + connected ? hostname : "none specified yet"); + printf("RFC2347 Options support: %s\n", + options_rfc_enabled ? "enabled" : "disabled"); + printf("Non-RFC defined options support: %s\n", + options_extra_enabled ? "enabled" : "disabled"); + printf("Mode: %s\n", mode); + printf("Verbose: %s\n", verbose ? "on" : "off"); + printf("Debug: %s\n", debug_show(debug)); + printf("Artificial packetloss: %d in 100 packets\n", + packetdroppercentage); + printf("Segment size: %d bytes\n", segsize); + printf("Network timeout: %d seconds\n", timeoutpacket); + printf("Maximum network timeout: %d seconds\n", timeoutnetwork); + printf("Maximum timeouts: %d \n", maxtimeouts); } -void +static void intr(int dummy __unused) { @@ -566,7 +680,7 @@ intr(int dummy __unused) longjmp(toplevel, -1); } -char * +static char * tail(char *filename) { char *s; @@ -583,7 +697,7 @@ tail(char *filename) } static const char * -command_prompt(void) +command_prompt() { return ("tftp> "); @@ -602,6 +716,7 @@ command(void) const char *bp; char *cp; int len, num, vrbose; + char line[MAXLINE]; vrbose = isatty(0); if (vrbose) { @@ -623,6 +738,7 @@ command(void) line[len] = '\0'; history(hist, &he, H_ENTER, bp); } else { + line[0] = 0; if (fgets(line, sizeof line , stdin) == 0) { if (feof(stdin)) { exit(txrx_error); @@ -635,7 +751,7 @@ command(void) *cp = '\0'; if (line[0] == 0) continue; - makeargv(); + makeargv(line); if (margc == 0) continue; c = getcmd(margv[0]); @@ -651,7 +767,7 @@ command(void) } } -struct cmd * +static struct cmd * getcmd(char *name) { const char *p, *q; @@ -683,15 +799,15 @@ getcmd(char *name) * Slice a string up into argc/argv. */ static void -makeargv(void) +makeargv(char *line) { char *cp; char **argp = margv; margc = 0; - if ((cp = strchr(line, '\n'))) + if ((cp = strchr(line, '\n')) != NULL) *cp = '\0'; - for (cp = line; margc < MAX_MARGV - 1 && *cp;) { + for (cp = line; margc < MAX_MARGV - 1 && *cp != '\0';) { while (isspace(*cp)) cp++; if (*cp == '\0') @@ -707,16 +823,17 @@ makeargv(void) *argp++ = 0; } -void +static void quit(int argc __unused, char *argv[] __unused) { + exit(txrx_error); } /* * Help command. */ -void +static void help(int argc, char *argv[]) { struct cmd *c; @@ -725,6 +842,10 @@ help(int argc, char *argv[]) printf("Commands may be abbreviated. Commands are:\n\n"); for (c = cmdtab; c->name; c++) printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help); + + printf("\n[-] : You shouldn't use these ones anymore.\n"); + printf("[*] : RFC2834 options support required.\n"); + printf("[**] : Non-standard RFC2834 option.\n"); return; } while (--argc > 0) { @@ -732,24 +853,211 @@ help(int argc, char *argv[]) arg = *++argv; c = getcmd(arg); if (c == (struct cmd *)-1) - printf("?Ambiguous help command %s\n", arg); + printf("?Ambiguous help command: %s\n", arg); else if (c == (struct cmd *)0) - printf("?Invalid help command %s\n", arg); + printf("?Invalid help command: %s\n", arg); else printf("%s\n", c->help); } } -void -settrace(int argc __unused, char **argv __unused) +static void +setverbose(int argc __unused, char *argv[] __unused) { - trace = !trace; - printf("Packet tracing %s.\n", trace ? "on" : "off"); -} -void -setverbose(int argc __unused, char **argv __unused) -{ verbose = !verbose; printf("Verbose mode %s.\n", verbose ? "on" : "off"); } + +static void +setoptions(int argc, char *argv[]) +{ + + if (argc == 2) { + if (strcasecmp(argv[1], "enable") == 0 || + strcasecmp(argv[1], "on") == 0) { + options_extra_enabled = 1; + options_rfc_enabled = 1; + } + if (strcasecmp(argv[1], "disable") == 0 || + strcasecmp(argv[1], "off") == 0) { + options_extra_enabled = 0; + options_rfc_enabled = 0; + } + if (strcasecmp(argv[1], "extra") == 0) + options_extra_enabled = !options_extra_enabled; + } + printf("Support for RFC2347 style options are now %s.\n", + options_rfc_enabled ? "enabled" : "disabled"); + printf("Support for non-RFC defined options are now %s.\n", + options_extra_enabled ? "enabled" : "disabled"); + + printf("\nThe following options are available:\n" + "\toptions on : enable support for RFC2347 style options\n" + "\toptions off : disable support for RFC2347 style options\n" + "\toptions extra : toggle support for non-RFC defined options\n" + ); +} + +static void +setrollover(int argc, char *argv[]) +{ + + if (argc == 2) { + if (strcasecmp(argv[1], "never") == 0 || + strcasecmp(argv[1], "none") == 0) { + free(options[OPT_ROLLOVER].o_request); + options[OPT_ROLLOVER].o_request = NULL; + } + if (strcasecmp(argv[1], "1") == 0) { + free(options[OPT_ROLLOVER].o_request); + options[OPT_ROLLOVER].o_request = strdup("1"); + } + if (strcasecmp(argv[1], "0") == 0) { + free(options[OPT_ROLLOVER].o_request); + options[OPT_ROLLOVER].o_request = strdup("0"); + } + } + printf("Support for the rollover options is %s.\n", + options[OPT_ROLLOVER].o_request != NULL ? "enabled" : "disabled"); + if (options[OPT_ROLLOVER].o_request != NULL) + printf("Block rollover will be to block %s.\n", + options[OPT_ROLLOVER].o_request); + + + printf("\nThe following rollover options are available:\n" + "\trollover 0 : rollover to block zero (default)\n" + "\trollover 1 : rollover to block one\n" + "\trollover never : do not support the rollover option\n" + "\trollover none : do not support the rollover option\n" + ); +} + +static void +setdebug(int argc, char *argv[]) +{ + int i; + + if (argc != 1) { + i = 1; + while (i < argc) + debug ^= debug_find(argv[i++]); + } + printf("The following debugging is enabled: %s\n", debug_show(debug)); + + printf("\nThe following debugs are available:\n"); + i = 0; + while (debugs[i].name != NULL) { + printf("\t%s\t%s\n", debugs[i].name, debugs[i].desc); + i++; + } +} + +static void +setblocksize(int argc, char *argv[]) +{ + + if (!options_rfc_enabled) + printf("RFC2347 style options are not enabled " + "(but proceding anyway)\n"); + + if (argc != 1) { + int size = atoi(argv[1]); + size_t max; + char maxbuffer[100]; + int *maxdgram; + + max = sizeof(maxbuffer); + if (sysctlbyname("net.inet.udp.maxdgram", + maxbuffer, &max, NULL, 0) < 0) { + perror("sysctl: net.inet.udp.maxdgram"); + return; + } + maxdgram = (int *)maxbuffer; + + if (size < BLKSIZE_MIN || size > BLKSIZE_MAX) { + printf("Blocksize should be between %d and %d bytes.\n", + BLKSIZE_MIN, BLKSIZE_MAX); + return; + } else if (size > *maxdgram - 4) { + printf("Blocksize can't be bigger than %d bytes due " + "to the net.inet.udp.maxdgram sysctl limitation.\n", + *maxdgram - 4); + asprintf(&options[OPT_BLKSIZE].o_request, + "%d", *maxdgram - 4); + } else { + asprintf(&options[OPT_BLKSIZE].o_request, "%d", size); + } + } + printf("Blocksize is now %s bytes.\n", options[OPT_BLKSIZE].o_request); +} + +static void +setblocksize2(int argc, char *argv[]) +{ + + if (!options_rfc_enabled || !options_extra_enabled) + printf( + "RFC2347 style or non-RFC defined options are not enabled " + "(but proceding anyway)\n"); + + if (argc != 1) { + int size = atoi(argv[1]); + int i; + size_t max; + char maxbuffer[100]; + int *maxdgram; + + int sizes[] = { + 8, 16, 32, 64, 128, 256, 512, 1024, + 2048, 4096, 8192, 16384, 32768, 0 + }; + + max = sizeof(maxbuffer); + if (sysctlbyname("net.inet.udp.maxdgram", + maxbuffer, &max, NULL, 0) < 0) { + perror("sysctl: net.inet.udp.maxdgram"); + return; + } + maxdgram = (int *)maxbuffer; + + for (i = 0; sizes[i] != 0; i++) { + if (sizes[i] == size) break; + } + if (sizes[i] == 0) { + printf("Blocksize2 should be a power of two between " + "8 and 32768.\n"); + return; + } + + if (size < BLKSIZE_MIN || size > BLKSIZE_MAX) { + printf("Blocksize2 should be between " + "%d and %d bytes.\n", BLKSIZE_MIN, BLKSIZE_MAX); + return; + } else if (size > *maxdgram - 4) { + printf("Blocksize2 can't be bigger than %d bytes due " + "to the net.inet.udp.maxdgram sysctl limitation.\n", + *maxdgram - 4); + for (i = 0; sizes[i+1] != 0; i++) { + if (*maxdgram < sizes[i+1]) break; + } + asprintf(&options[OPT_BLKSIZE2].o_request, + "%d", sizes[i]); + } else { + asprintf(&options[OPT_BLKSIZE2].o_request, "%d", size); + } + } + printf("Blocksize2 is now %s bytes.\n", + options[OPT_BLKSIZE2].o_request); +} + +static void +setpacketdrop(int argc, char *argv[]) +{ + + if (argc != 1) + packetdroppercentage = atoi(argv[1]); + + printf("Randomly %d in 100 packets will be dropped\n", + packetdroppercentage); +} diff --git a/usr.bin/tftp/tftp.1 b/usr.bin/tftp/tftp.1 index 8924eb5..04daa87 100644 --- a/usr.bin/tftp/tftp.1 +++ b/usr.bin/tftp/tftp.1 @@ -37,7 +37,7 @@ .Os .Sh NAME .Nm tftp -.Nd "trivial file transfer program" +.Nd trivial file transfer program .Sh SYNOPSIS .Nm .Op Ar host Op Ar port @@ -55,28 +55,26 @@ may be specified on the command line, in which case uses .Ar host as the default host for future transfers (see the -.Ic connect +.Cm connect command below). .Sh COMMANDS Once .Nm is running, it issues the prompt -.Dq Li "tftp> " +.Dq Li tftp> and recognizes the following commands: .Pp -.Bl -tag -width ".Ic verbose" -compact -.It Ic \&? Ar command-name ... +.Bl -tag -width verbose -compact +.It Cm \&? Ar command-name ... Print help information. .Pp -.It Ic ascii -Shorthand for -.Ic mode Cm ascii . +.It Cm ascii +Shorthand for "mode ascii" .Pp -.It Ic binary -Shorthand for -.Ic mode Cm binary . +.It Cm binary +Shorthand for "mode binary" .Pp -.It Ic connect Ar host Op Ar port +.It Cm connect Ar host Op Ar port Set the .Ar host (and optionally @@ -88,19 +86,19 @@ protocol, unlike the .Tn FTP protocol, does not maintain connections between transfers; thus, the -.Ic connect +.Cm connect command does not actually create a connection, but merely remembers what host is to be used for transfers. You do not have to use the -.Ic connect +.Cm connect command; the remote host can be specified as part of the -.Ic get +.Cm get or -.Ic put +.Cm put commands. .Pp -.It Ic get Oo Ar host : Oc Ns Ar file Op Ar localname -.It Ic get Xo +.It Cm get Oo Ar host : Oc Ns Ar file Op Ar localname +.It Cm get Xo .Oo Ar host1 : Oc Ns Ar file1 .Oo Ar host2 : Oc Ns Ar file2 ... .Oo Ar hostN : Oc Ns Ar fileN @@ -126,18 +124,18 @@ to disambiguate the colons used in the IPv6 address from the colon separating the host and the filename. .Pp -.It Ic mode Ar transfer-mode +.It Cm mode Ar transfer-mode Set the mode for transfers; .Ar transfer-mode may be one of -.Cm ascii +.Em ascii or -.Cm binary . +.Em binary . The default is -.Cm ascii . +.Em ascii . .Pp -.It Ic put Ar file Op Oo Ar host : Oc Ns Ar remotename -.It Ic put Ar file1 file2 ... fileN Op Oo Ar host : Oc Ns Ar remote-directory +.It Cm put Ar file Op Oo Ar host : Oc Ns Ar remotename +.It Cm put Ar file1 file2 ... fileN Op Oo Ar host : Oc Ns Ar remote-directory Put a file or set of files to the remote host. When .Ar remotename @@ -152,27 +150,27 @@ machine. To specify an IPv6 numeric address for a .Ar host , see the example under the -.Ic get +.Cm get command. .Pp -.It Ic quit +.It Cm quit Exit .Nm . An end of file also exits. .Pp -.It Ic rexmt Ar retransmission-timeout +.It Cm rexmt Ar retransmission-timeout Set the per-packet retransmission timeout, in seconds. .Pp -.It Ic status +.It Cm status Show current status. .Pp -.It Ic timeout Ar total-transmission-timeout +.It Cm timeout Ar total-transmission-timeout Set the total transmission timeout, in seconds. .Pp -.It Ic trace +.It Cm trace Toggle packet tracing. .Pp -.It Ic verbose +.It Cm verbose Toggle verbose mode. .El .Sh HISTORY diff --git a/usr.bin/tftp/tftp.c b/usr.bin/tftp/tftp.c index 4300902..29ba2b2 100644 --- a/usr.bin/tftp/tftp.c +++ b/usr.bin/tftp/tftp.c @@ -45,446 +45,230 @@ __FBSDID("$FreeBSD$"); /* * TFTP User Program -- Protocol Machines */ -#include #include -#include +#include #include -#include #include #include -#include -#include -#include +#include #include +#include #include -#include -#include +#include -#include "extern.h" -#include "tftpsubs.h" - -extern struct sockaddr_storage peeraddr; /* filled in by main */ -extern int f; /* the opened socket */ -extern int trace; -extern int verbose; -extern int rexmtval; -extern int maxtimeout; -extern volatile int txrx_error; - -#define PKTSIZE SEGSIZE+4 -char ackbuf[PKTSIZE]; -int timeout; -jmp_buf toplevel; -jmp_buf timeoutbuf; - -static void nak(int, const struct sockaddr *); -static int makerequest(int, const char *, struct tftphdr *, const char *); -static void printstats(const char *, unsigned long); -static void startclock(void); -static void stopclock(void); -static void timer(int); -static void tpacket(const char *, struct tftphdr *, int); -static int cmpport(const struct sockaddr *, const struct sockaddr *); +#include "tftp.h" +#include "tftp-file.h" +#include "tftp-utils.h" +#include "tftp-io.h" +#include "tftp-transfer.h" +#include "tftp-options.h" /* * Send the requested file. */ void -xmitfile(int fd, const char *name, const char *mode) +xmitfile(int peer, char *port, int fd, char *name, char *mode) { - struct tftphdr *ap; /* data and ack packets */ - struct tftphdr *dp; - int n; - volatile unsigned short block; - volatile int size, convert; - volatile unsigned long amount; - struct sockaddr_storage from; - socklen_t fromlen; - FILE *file; - struct sockaddr_storage peer; + struct tftphdr *rp; + int n, i; + uint16_t block; + uint32_t amount; struct sockaddr_storage serv; /* valid server port number */ + char recvbuffer[MAXPKTSIZE]; + struct tftp_stats tftp_stats; + + stats_init(&tftp_stats); - startclock(); /* start stat's clock */ - dp = r_init(); /* reset fillbuf/read-ahead code */ - ap = (struct tftphdr *)ackbuf; - file = fdopen(fd, "r"); - convert = !strcmp(mode, "netascii"); - block = 0; - amount = 0; - memcpy(&peer, &peeraddr, peeraddr.ss_len); memset(&serv, 0, sizeof(serv)); + rp = (struct tftphdr *)recvbuffer; + + if (port == NULL) { + struct servent *se; + se = getservbyname("tftp", "udp"); + ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; + } else + ((struct sockaddr_in *)&peer_sock)->sin_port = + htons(atoi(port)); + + for (i = 0; i < 12; i++) { + struct sockaddr_storage from; + + /* Tell the other side what we want to do */ + if (debug&DEBUG_SIMPLE) + printf("Sending %s\n", name); + + n = send_wrq(peer, name, mode); + if (n > 0) { + printf("Cannot send WRQ packet\n"); + return; + } - signal(SIGALRM, timer); - do { - if (block == 0) - size = makerequest(WRQ, name, dp, mode) - 4; - else { - /* size = read(fd, dp->th_data, SEGSIZE); */ - size = readit(file, &dp, convert); - if (size < 0) { - nak(errno + 100, (struct sockaddr *)&peer); - break; - } - dp->th_opcode = htons((u_short)DATA); - dp->th_block = htons((u_short)block); + /* + * The first packet we receive has the new destination port + * we have to send the next packets to. + */ + n = receive_packet(peer, recvbuffer, + MAXPKTSIZE, &from, timeoutpacket); + + /* We got some data! */ + if (n >= 0) { + ((struct sockaddr_in *)&peer_sock)->sin_port = + ((struct sockaddr_in *)&from)->sin_port; + break; } - timeout = 0; - (void) setjmp(timeoutbuf); -send_data: - if (trace) - tpacket("sent", dp, size + 4); - n = sendto(f, dp, size + 4, 0, - (struct sockaddr *)&peer, peer.ss_len); - if (n != size + 4) { - warn("sendto"); - txrx_error = 1; - goto abort; + + /* This should be retried */ + if (n == RP_TIMEOUT) { + printf("Try %d, didn't receive answer from remote.\n", + i + 1); + continue; } - read_ahead(file, convert); - for ( ; ; ) { - alarm(rexmtval); - do { - fromlen = sizeof(from); - n = recvfrom(f, ackbuf, sizeof(ackbuf), 0, - (struct sockaddr *)&from, &fromlen); - } while (n <= 0); - alarm(0); - if (n < 0) { - warn("recvfrom"); - txrx_error = 1; - goto abort; - } - if (!serv.ss_family) - serv = from; - else if (!cmpport((struct sockaddr *)&serv, - (struct sockaddr *)&from)) { - warn("server port mismatch"); - txrx_error = 1; - goto abort; - } - peer = from; - if (trace) - tpacket("received", ap, n); - /* should verify packet came from server */ - ap->th_opcode = ntohs(ap->th_opcode); - ap->th_block = ntohs(ap->th_block); - if (ap->th_opcode == ERROR) { - printf("Error code %d: %s\n", ap->th_code, - ap->th_msg); - txrx_error = 1; - goto abort; - } - if (ap->th_opcode == ACK) { - int j; - - if (ap->th_block == block) { - break; - } - /* On an error, try to synchronize - * both sides. - */ - j = synchnet(f); - if (j && trace) { - printf("discarded %d packets\n", - j); - } - if (ap->th_block == (block-1)) { - goto send_data; - } - } + + /* Everything else is fatal */ + break; + } + if (i == 12) { + printf("Transfer timed out.\n"); + return; + } + if (rp->th_opcode == ERROR) { + printf("Got ERROR, aborted\n"); + return; + } + + /* + * If the first packet is an OACK instead of an ACK packet, + * handle it different. + */ + if (rp->th_opcode == OACK) { + if (!options_rfc_enabled) { + printf("Got OACK while options are not enabled!\n"); + send_error(peer, EBADOP); + return; } - if (block > 0) - amount += size; - block++; - } while (size == SEGSIZE || block == 1); -abort: - fclose(file); - stopclock(); - if (amount > 0) - printstats("Sent", amount); -} -/* - * Receive a file. - */ -void -recvfile(int fd, const char *name, const char *mode) -{ - struct tftphdr *ap; - struct tftphdr *dp; - int n; - volatile unsigned short block; - volatile int size, firsttrip; - volatile unsigned long amount; - struct sockaddr_storage from; - socklen_t fromlen; - FILE *file; - volatile int convert; /* true if converting crlf -> lf */ - struct sockaddr_storage peer; - struct sockaddr_storage serv; /* valid server port number */ + parse_options(peer, rp->th_stuff, n + 2); + } + + if (read_init(fd, NULL, mode) < 0) { + warn("read_init()"); + return; + } - startclock(); - dp = w_init(); - ap = (struct tftphdr *)ackbuf; - file = fdopen(fd, "w"); - convert = !strcmp(mode, "netascii"); block = 1; - firsttrip = 1; - amount = 0; - memcpy(&peer, &peeraddr, peeraddr.ss_len); - memset(&serv, 0, sizeof(serv)); + tftp_send(peer, &block, &tftp_stats); - signal(SIGALRM, timer); - do { - if (firsttrip) { - size = makerequest(RRQ, name, ap, mode); - firsttrip = 0; - } else { - ap->th_opcode = htons((u_short)ACK); - ap->th_block = htons((u_short)(block)); - size = 4; - block++; - } - timeout = 0; - (void) setjmp(timeoutbuf); -send_ack: - if (trace) - tpacket("sent", ap, size); - if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peer, - peer.ss_len) != size) { - alarm(0); - warn("sendto"); - txrx_error = 1; - goto abort; - } - write_behind(file, convert); - for ( ; ; ) { - alarm(rexmtval); - do { - fromlen = sizeof(from); - n = recvfrom(f, dp, PKTSIZE, 0, - (struct sockaddr *)&from, &fromlen); - } while (n <= 0); - alarm(0); - if (n < 0) { - warn("recvfrom"); - txrx_error = 1; - goto abort; - } - if (!serv.ss_family) - serv = from; - else if (!cmpport((struct sockaddr *)&serv, - (struct sockaddr *)&from)) { - warn("server port mismatch"); - txrx_error = 1; - goto abort; - } - peer = from; - if (trace) - tpacket("received", dp, n); - /* should verify client address */ - dp->th_opcode = ntohs(dp->th_opcode); - dp->th_block = ntohs(dp->th_block); - if (dp->th_opcode == ERROR) { - printf("Error code %d: %s\n", dp->th_code, - dp->th_msg); - txrx_error = 1; - goto abort; - } - if (dp->th_opcode == DATA) { - int j; - - if (dp->th_block == block) { - break; /* have next packet */ - } - /* On an error, try to synchronize - * both sides. - */ - j = synchnet(f); - if (j && trace) { - printf("discarded %d packets\n", j); - } - if (dp->th_block == (block-1)) { - goto send_ack; /* resend ack */ - } - } - } - /* size = write(fd, dp->th_data, n - 4); */ - size = writeit(file, &dp, n - 4, convert); - if (size < 0) { - nak(errno + 100, (struct sockaddr *)&peer); - break; - } - amount += size; - } while (size == SEGSIZE); -abort: /* ok to ack, since user */ - ap->th_opcode = htons((u_short)ACK); /* has seen err msg */ - ap->th_block = htons((u_short)block); - (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peer, - peer.ss_len); - write_behind(file, convert); /* flush last buffer */ - fclose(file); - stopclock(); + read_close(); if (amount > 0) - printstats("Received", amount); -} + printstats("Sent", verbose, &tftp_stats); -static int -makerequest(int request, const char *name, struct tftphdr *tp, const char *mode) -{ - char *cp; - - tp->th_opcode = htons((u_short)request); - cp = tp->th_stuff; - strcpy(cp, name); - cp += strlen(name); - *cp++ = '\0'; - strcpy(cp, mode); - cp += strlen(mode); - *cp++ = '\0'; - return (cp - (char *)tp); + txrx_error = 1; } -struct errmsg { - int e_code; - const char *e_msg; -} errmsgs[] = { - { EUNDEF, "Undefined error code" }, - { ENOTFOUND, "File not found" }, - { EACCESS, "Access violation" }, - { ENOSPACE, "Disk full or allocation exceeded" }, - { EBADOP, "Illegal TFTP operation" }, - { EBADID, "Unknown transfer ID" }, - { EEXISTS, "File already exists" }, - { ENOUSER, "No such user" }, - { -1, 0 } -}; - /* - * Send a nak packet (error message). - * Error code passed in is one of the - * standard TFTP codes, or a UNIX errno - * offset by 100. + * Receive a file. */ -static void -nak(int error, const struct sockaddr *peer) -{ - struct errmsg *pe; - struct tftphdr *tp; - int length; - - tp = (struct tftphdr *)ackbuf; - tp->th_opcode = htons((u_short)ERROR); - tp->th_code = htons((u_short)error); - for (pe = errmsgs; pe->e_code >= 0; pe++) - if (pe->e_code == error) - break; - if (pe->e_code < 0) { - pe->e_msg = strerror(error - 100); - tp->th_code = EUNDEF; - } - strcpy(tp->th_msg, pe->e_msg); - length = strlen(pe->e_msg) + 4; - if (trace) - tpacket("sent", tp, length); - if (sendto(f, ackbuf, length, 0, peer, peer->sa_len) != length) - warn("nak"); -} - -static void -tpacket(const char *s, struct tftphdr *tp, int n) +void +recvfile(int peer, char *port, int fd, char *name, char *mode) { - static const char *opcodes[] = - { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR" }; - char *cp, *file; - u_short op = ntohs(tp->th_opcode); - - if (op < RRQ || op > ERROR) - printf("%s opcode=%x ", s, op); - else - printf("%s %s ", s, opcodes[op]); - switch (op) { - - case RRQ: - case WRQ: - n -= 2; - file = cp = tp->th_stuff; - cp = index(cp, '\0'); - printf("\n", file, cp + 1); - break; + struct tftphdr *rp; + uint16_t block; + char recvbuffer[MAXPKTSIZE]; + int n, i; + struct tftp_stats tftp_stats; + + stats_init(&tftp_stats); + + rp = (struct tftphdr *)recvbuffer; + + if (port == NULL) { + struct servent *se; + se = getservbyname("tftp", "udp"); + ((struct sockaddr_in *)&peer_sock)->sin_port = se->s_port; + } else + ((struct sockaddr_in *)&peer_sock)->sin_port = + htons(atoi(port)); + + for (i = 0; i < 12; i++) { + struct sockaddr_storage from; + + /* Tell the other side what we want to do */ + if (debug&DEBUG_SIMPLE) + printf("Requesting %s\n", name); + + n = send_rrq(peer, name, mode); + if (n > 0) { + printf("Cannot send RRQ packet\n"); + return; + } - case DATA: - printf("\n", ntohs(tp->th_block), n - 4); - break; + /* + * The first packet we receive has the new destination port + * we have to send the next packets to. + */ + n = receive_packet(peer, recvbuffer, + MAXPKTSIZE, &from, timeoutpacket); + + /* We got something useful! */ + if (n >= 0) { + ((struct sockaddr_in *)&peer_sock)->sin_port = + ((struct sockaddr_in *)&from)->sin_port; + break; + } - case ACK: - printf("\n", ntohs(tp->th_block)); - break; + /* We should retry if this happens */ + if (n == RP_TIMEOUT) { + printf("Try %d, didn't receive answer from remote.\n", + i + 1); + continue; + } - case ERROR: - printf("\n", ntohs(tp->th_code), tp->th_msg); + /* Otherwise it is a fatal error */ break; } -} - -struct timeval tstart; -struct timeval tstop; - -static void -startclock(void) -{ - (void)gettimeofday(&tstart, NULL); -} - -static void -stopclock(void) -{ + if (rp->th_opcode == ERROR) { + tftp_log(LOG_ERR, "Error code %d: %s", rp->th_code, rp->th_msg); + return; + } - (void)gettimeofday(&tstop, NULL); -} + if (write_init(fd, NULL, mode) < 0) { + warn("write_init"); + return; + } -static void -printstats(const char *direction, unsigned long amount) -{ - double delta; - /* compute delta in 1/10's second units */ - delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000)) - - ((tstart.tv_sec*10.)+(tstart.tv_usec/100000)); - delta = delta/10.; /* back to seconds */ - printf("%s %ld bytes in %.1f seconds", direction, amount, delta); - if (verbose) - printf(" [%.0f bits/sec]", (amount*8.)/delta); - putchar('\n'); -} + stats_init(&tftp_stats); + + /* + * If the first packet is an OACK packet instead of an DATA packet, + * handle it different. + */ + if (rp->th_opcode == OACK) { + if (!options_rfc_enabled) { + printf("Got OACK while options are not enabled!\n"); + send_error(peer, EBADOP); + return; + } -static void -timer(int sig __unused) -{ + parse_options(peer, rp->th_stuff, n + 2); - timeout += rexmtval; - if (timeout >= maxtimeout) { - printf("Transfer timed out.\n"); - longjmp(toplevel, -1); + n = send_ack(peer, 0); + if (n > 0) { + printf("Cannot send ACK on OACK.\n"); + return; + } + block = 0; + tftp_receive(peer, &block, &tftp_stats, NULL, 0); + } else { + block = 1; + tftp_receive(peer, &block, &tftp_stats, rp, n); } - txrx_error = 1; - longjmp(timeoutbuf, 1); -} - -static int -cmpport(const struct sockaddr *sa, const struct sockaddr *sb) -{ - char a[NI_MAXSERV], b[NI_MAXSERV]; - - if (getnameinfo(sa, sa->sa_len, NULL, 0, a, sizeof(a), NI_NUMERICSERV)) - return 0; - if (getnameinfo(sb, sb->sa_len, NULL, 0, b, sizeof(b), NI_NUMERICSERV)) - return 0; - if (strcmp(a, b) != 0) - return 0; - return 1; + write_close(); + if (tftp_stats.amount > 0) + printstats("Received", verbose, &tftp_stats); + return; } -- cgit v1.1 From ff6273a4391b5559f8a5e847e32a80b51605974f Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 4 May 2010 06:19:19 +0000 Subject: Go ahead and merge the work edwin@ on tftpd into the tree. It is a lot better than what's in the tree now. Edwin tested it at a prior employer, but can't test it today. I've found that it works a lot better with the various uboot versions that I've used in my embedded work. Here's the pkg-descr from the port that describes the changes: It all started when we got some new routers, which told me the following when trying to upload configuration or download images from it: The TFTP server doesn't support the blocksize option. My curiousity was triggered, it took me some reading of RFCs and other documentation to find out what was possible and what could be done. Was plain TFTP very simple in its handshake, TFTP with options was kind of messy because of its backwards capability: The first packet returned could either be an acknowledgement of options, or the first data packet. Going through the source code of src/libexec/tftpd and going through the code of src/usr.bin/tftp showed that there was a lot of duplicate code, and the addition of options would only increase the amount of duplicate code. After all, both the client and the server can act as a sender and receiver. At the end, it ended up with a nearly complete rewrite of the tftp client and server. It has been tested against the following TFTP clients and servers: - Itself (yay!) - The standard FreeBSD tftp client and server - The Fedora Core 6 tftp client and server - Cisco router tftp client - Extreme Networks tftp client It supports the following RFCs: RFC1350 - THE TFTP PROTOCOL (REVISION 2) RFC2347 - TFTP Option Extension RFC2348 - TFTP Blocksize Option RFC2349 - TFTP Timeout Interval and Transfer Size Options RFC3617 - Uniform Resource Identifier (URI) Scheme and Applicability Statement for the Trivial File Transfer Protocol (TFTP) It supports the following unofficial TFTP Options as described at http://www.compuphase.com/tftp.htm: blksize2 - Block size restricted to powers of 2, excluding protocol headers rollover - Block counter roll-over (roll back to zero or to one) From the tftp program point of view the following things are changed: - New commands: "blocksize", "blocksize2", "rollover" and "options" - Development features: "debug" and "packetdrop" If you try this tftp/tftpd implementation, please let me know if it works (or doesn't work) and against which implementaion so I can get a list of confirmed working systems. Author: Edwin Groothuis --- libexec/tftpd/Makefile | 13 +- libexec/tftpd/tftpd.8 | 17 +- libexec/tftpd/tftpd.c | 826 ++++++++++++++++++++----------------------------- 3 files changed, 354 insertions(+), 502 deletions(-) diff --git a/libexec/tftpd/Makefile b/libexec/tftpd/Makefile index 6c29243..b9db2a9 100644 --- a/libexec/tftpd/Makefile +++ b/libexec/tftpd/Makefile @@ -2,15 +2,14 @@ # $FreeBSD$ PROG= tftpd -SRCS= tftpd.c tftpsubs.c -DPADD= ${LIBUTIL} -LDADD= -lutil - -WARNS?= 1 +SRCS= tftpd.c tftp-io.c tftp-utils.c tftp-file.c tftp-transfer.c tftp-options.c +WARNS= 3 WFORMAT=0 - MAN= tftpd.8 -CFLAGS+=-I${.CURDIR}/../../usr.bin/tftp +CFLAGS=-g -Wall +CFLAGS+=-I${.CURDIR}/../../usr.bin/tftp -I${.CURDIR}/../../libexec/tftpd .PATH: ${.CURDIR}/../../usr.bin/tftp +COPTFLAGS = -O +LDFLAGS= -lwrap .include diff --git a/libexec/tftpd/tftpd.8 b/libexec/tftpd/tftpd.8 index f9d7aec..08f40f3 100644 --- a/libexec/tftpd/tftpd.8 +++ b/libexec/tftpd/tftpd.8 @@ -40,7 +40,7 @@ .Nd Internet Trivial File Transfer Protocol server .Sh SYNOPSIS .Nm tftpd -.Op Fl cClnwW +.Op Fl cdClnow .Op Fl F Ar strftime-format .Op Fl s Ar directory .Op Fl u Ar user @@ -150,6 +150,9 @@ compatible format string for the creation of the suffix if .Fl W is specified. By default the string "%Y%m%d" is used. +.It Fl d +Enables debug output. +If specified twice, it will log DATA and ACK packets too. .It Fl l Log all requests using .Xr syslog 3 @@ -164,6 +167,8 @@ must also be enabled in the syslog configuration file, .It Fl n Suppress negative acknowledgement of requests for nonexistent relative filenames. +.It Fl o +Disable support for RFC2347 style TFTP Options. .It Fl s Ar directory Cause .Nm @@ -240,10 +245,16 @@ and the and .Fl W options were introduced in -.Fx 8.0 . +.Fx 7 . .Pp +Support for Timeout Interval and Transfer Size Options (RFC2349) +was introduced in +.Fx 5.0 , +support for the TFTP Blocksize Option (RFC2348) and the blksize2 option +was introduced in +.Fx 7 . .Sh BUGS Files larger than 33488896 octets (65535 blocks) cannot be transferred -without client and server supporting blocksize negotiation (RFC1783). +without client and server supporting blocksize negotiation (RFC2348). .Pp Many tftp clients will not transfer files over 16744448 octets (32767 blocks). diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c index 027e4bc..93943f5 100644 --- a/libexec/tftpd/tftpd.c +++ b/libexec/tftpd/tftpd.c @@ -41,9 +41,9 @@ static const char copyright[] = #if 0 static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93"; #endif -static const char rcsid[] = - "$FreeBSD$"; #endif /* not lint */ +#include +__FBSDID("$FreeBSD$"); /* * Trivial file transfer protocol server. @@ -56,43 +56,30 @@ static const char rcsid[] = #include #include #include -#include -#include #include #include -#include #include #include #include -#include #include #include -#include -#include #include #include #include #include +#include #include -#include "tftpsubs.h" +#include "tftp-file.h" +#include "tftp-io.h" +#include "tftp-utils.h" +#include "tftp-transfer.h" +#include "tftp-options.h" -#define TIMEOUT 5 -#define MAX_TIMEOUTS 5 - -int peer; -int rexmtval = TIMEOUT; -int max_rexmtval = 2*TIMEOUT; - -#define PKTSIZE SEGSIZE+4 -char buf[PKTSIZE]; -char ackbuf[PKTSIZE]; -struct sockaddr_storage from; - -void tftp(struct tftphdr *, int); -static void unmappedaddr(struct sockaddr_in6 *); +static void tftp_wrq(int peer, char *, ssize_t); +static void tftp_rrq(int peer, char *, ssize_t); /* * Null-terminated directory prefix list for absolute pathname requests and @@ -112,31 +99,44 @@ static int ipchroot; static int create_new = 0; static char *newfile_format = "%Y%m%d"; static int increase_name = 0; -static mode_t mask = S_IWGRP|S_IWOTH; +static mode_t mask = S_IWGRP | S_IWOTH; -static const char *errtomsg(int); -static void nak(int); -static void oack(void); +struct formats; +static void tftp_recvfile(int peer, const char *mode); +static void tftp_xmitfile(int peer, const char *mode); +static int validate_access(int peer, char **, int); +static char peername[NI_MAXHOST]; + +FILE *file; -static void timer(int); -static void justquit(int); +struct formats { + const char *f_mode; + int f_convert; +} formats[] = { + { "netascii", 1 }, + { "octet", 0 }, + { NULL, 0 } +}; int main(int argc, char *argv[]) { struct tftphdr *tp; - socklen_t fromlen, len; - int n; - int ch, on; - struct sockaddr_storage me; - char *chroot_dir = NULL; - struct passwd *nobody; - const char *chuser = "nobody"; + int peer; + socklen_t peerlen, len; + ssize_t n; + int ch; + char *chroot_dir = NULL; + struct passwd *nobody; + const char *chuser = "nobody"; + char recvbuffer[MAXPKTSIZE]; + int allow_ro = 1, allow_wo = 1; tzset(); /* syslog in localtime */ + acting_as_client = 0; - openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); - while ((ch = getopt(argc, argv, "cCF:lns:u:U:wW")) != -1) { + tftp_openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); + while ((ch = getopt(argc, argv, "cCd:F:lnoOp:s:u:U:wW")) != -1) { switch (ch) { case 'c': ipchroot = 1; @@ -144,6 +144,12 @@ main(int argc, char *argv[]) case 'C': ipchroot = 2; break; + case 'd': + if (atoi(optarg) != 0) + debug += atoi(optarg); + else + debug |= debug_finds(optarg); + break; case 'F': newfile_format = optarg; break; @@ -153,6 +159,18 @@ main(int argc, char *argv[]) case 'n': suppress_naks = 1; break; + case 'o': + options_rfc_enabled = 0; + break; + case 'O': + options_extra_enabled = 0; + break; + case 'p': + packetdroppercentage = atoi(optarg); + tftp_log(LOG_INFO, + "Randomly dropping %d out of 100 packets", + packetdroppercentage); + break; case 's': chroot_dir = optarg; break; @@ -170,7 +188,8 @@ main(int argc, char *argv[]) increase_name = 1; break; default: - syslog(LOG_WARNING, "ignoring unknown option -%c", ch); + tftp_log(LOG_WARNING, + "ignoring unknown option -%c", ch); } } if (optind < argc) { @@ -191,24 +210,31 @@ main(int argc, char *argv[]) dirs->len = 1; } if (ipchroot > 0 && chroot_dir == NULL) { - syslog(LOG_ERR, "-c requires -s"); + tftp_log(LOG_ERR, "-c requires -s"); exit(1); } umask(mask); - on = 1; - if (ioctl(0, FIONBIO, &on) < 0) { - syslog(LOG_ERR, "ioctl(FIONBIO): %m"); - exit(1); + { + int on = 1; + if (ioctl(0, FIONBIO, &on) < 0) { + tftp_log(LOG_ERR, "ioctl(FIONBIO): %s", strerror(errno)); + exit(1); + } } - fromlen = sizeof (from); - n = recvfrom(0, buf, sizeof (buf), 0, - (struct sockaddr *)&from, &fromlen); + + /* Find out who we are talking to and what we are going to do */ + peerlen = sizeof(peer_sock); + n = recvfrom(0, recvbuffer, MAXPKTSIZE, 0, + (struct sockaddr *)&peer_sock, &peerlen); if (n < 0) { - syslog(LOG_ERR, "recvfrom: %m"); + tftp_log(LOG_ERR, "recvfrom: %s", strerror(errno)); exit(1); } + getnameinfo((struct sockaddr *)&peer_sock, peer_sock.ss_len, + peername, sizeof(peername), NULL, 0, NI_NUMERICHOST); + /* * Now that we have read the message out of the UDP * socket, we fork and exit. Thus, inetd will go back @@ -240,9 +266,9 @@ main(int argc, char *argv[]) * than one tftpd being started up to service * a single request from a single client. */ - fromlen = sizeof from; - i = recvfrom(0, buf, sizeof (buf), 0, - (struct sockaddr *)&from, &fromlen); + peerlen = sizeof peer_sock; + i = recvfrom(0, recvbuffer, MAXPKTSIZE, 0, + (struct sockaddr *)&peer_sock, &peerlen); if (i > 0) { n = i; } @@ -251,7 +277,7 @@ main(int argc, char *argv[]) } } if (pid < 0) { - syslog(LOG_ERR, "fork: %m"); + tftp_log(LOG_ERR, "fork: %s", strerror(errno)); exit(1); } else if (pid != 0) { exit(0); @@ -259,6 +285,55 @@ main(int argc, char *argv[]) } /* + * See if the client is allowed to talk to me. + * (This needs to be done before the chroot()) + */ + { + struct request_info req; + + request_init(&req, RQ_CLIENT_ADDR, peername, 0); + request_set(&req, RQ_DAEMON, "tftpd", 0); + + if (hosts_access(&req) == 0) { + if (debug&DEBUG_ACCESS) + tftp_log(LOG_WARNING, + "Access denied by 'tftpd' entry " + "in /etc/hosts.allow"); + + /* + * Full access might be disabled, but maybe the + * client is allowed to do read-only access. + */ + request_set(&req, RQ_DAEMON, "tftpd-ro", 0); + allow_ro = hosts_access(&req); + + request_set(&req, RQ_DAEMON, "tftpd-wo", 0); + allow_wo = hosts_access(&req); + + if (allow_ro == 0 && allow_wo == 0) { + tftp_log(LOG_WARNING, + "Unauthorized access from %s", peername); + exit(1); + } + + if (debug&DEBUG_ACCESS) { + if (allow_ro) + tftp_log(LOG_WARNING, + "But allowed readonly access " + "via 'tftpd-ro' entry"); + if (allow_wo) + tftp_log(LOG_WARNING, + "But allowed writeonly access " + "via 'tftpd-wo' entry"); + } + } else + if (debug&DEBUG_ACCESS) + tftp_log(LOG_WARNING, + "Full access allowed" + "in /etc/hosts.allow"); + } + + /* * Since we exit here, we should do that only after the above * recvfrom to keep inetd from constantly forking should there * be a problem. See the above comment about system clogging. @@ -271,7 +346,8 @@ main(int argc, char *argv[]) struct sockaddr_storage ss; char hbuf[NI_MAXHOST]; - memcpy(&ss, &from, from.ss_len); + statret = -1; + memcpy(&ss, &peer_sock, peer_sock.ss_len); unmappedaddr((struct sockaddr_in6 *)&ss); getnameinfo((struct sockaddr *)&ss, ss.ss_len, hbuf, sizeof(hbuf), NULL, 0, @@ -285,11 +361,12 @@ main(int argc, char *argv[]) } /* Must get this before chroot because /etc might go away */ if ((nobody = getpwnam(chuser)) == NULL) { - syslog(LOG_ERR, "%s: no such user", chuser); + tftp_log(LOG_ERR, "%s: no such user", chuser); exit(1); } if (chroot(chroot_dir)) { - syslog(LOG_ERR, "chroot: %s: %m", chroot_dir); + tftp_log(LOG_ERR, "chroot: %s: %s", + chroot_dir, strerror(errno)); exit(1); } chdir("/"); @@ -297,44 +374,56 @@ main(int argc, char *argv[]) setuid(nobody->pw_uid); } - len = sizeof(me); - if (getsockname(0, (struct sockaddr *)&me, &len) == 0) { - switch (me.ss_family) { + len = sizeof(me_sock); + if (getsockname(0, (struct sockaddr *)&me_sock, &len) == 0) { + switch (me_sock.ss_family) { case AF_INET: - ((struct sockaddr_in *)&me)->sin_port = 0; + ((struct sockaddr_in *)&me_sock)->sin_port = 0; break; case AF_INET6: - ((struct sockaddr_in6 *)&me)->sin6_port = 0; + ((struct sockaddr_in6 *)&me_sock)->sin6_port = 0; break; default: /* unsupported */ break; } } else { - memset(&me, 0, sizeof(me)); - me.ss_family = from.ss_family; - me.ss_len = from.ss_len; + memset(&me_sock, 0, sizeof(me_sock)); + me_sock.ss_family = peer_sock.ss_family; + me_sock.ss_len = peer_sock.ss_len; } - alarm(0); close(0); close(1); - peer = socket(from.ss_family, SOCK_DGRAM, 0); + peer = socket(peer_sock.ss_family, SOCK_DGRAM, 0); if (peer < 0) { - syslog(LOG_ERR, "socket: %m"); - exit(1); - } - if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) { - syslog(LOG_ERR, "bind: %m"); + tftp_log(LOG_ERR, "socket: %s", strerror(errno)); exit(1); } - if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) { - syslog(LOG_ERR, "connect: %m"); + if (bind(peer, (struct sockaddr *)&me_sock, me_sock.ss_len) < 0) { + tftp_log(LOG_ERR, "bind: %s", strerror(errno)); exit(1); } - tp = (struct tftphdr *)buf; + + tp = (struct tftphdr *)recvbuffer; tp->th_opcode = ntohs(tp->th_opcode); - if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) - tftp(tp, n); + if (tp->th_opcode == RRQ) { + if (allow_ro) + tftp_rrq(peer, tp->th_stuff, n - 1); + else { + tftp_log(LOG_WARNING, + "%s read access denied", peername); + exit(1); + } + } + if (tp->th_opcode == WRQ) { + if (allow_wo) + tftp_wrq(peer, tp->th_stuff, n - 1); + else { + tftp_log(LOG_WARNING, + "%s write access denied", peername); + exit(1); + } + } exit(1); } @@ -369,138 +458,145 @@ reduce_path(char *fn) } } -struct formats; -int validate_access(char **, int); -void xmitfile(struct formats *); -void recvfile(struct formats *); +static char * +parse_header(int peer, char *recvbuffer, ssize_t size, + char **filename, char **mode) +{ + char *cp; + int i; + struct formats *pf; -struct formats { - const char *f_mode; - int (*f_validate)(char **, int); - void (*f_send)(struct formats *); - void (*f_recv)(struct formats *); - int f_convert; -} formats[] = { - { "netascii", validate_access, xmitfile, recvfile, 1 }, - { "octet", validate_access, xmitfile, recvfile, 0 }, -#ifdef notdef - { "mail", validate_user, sendmail, recvmail, 1 }, -#endif - { 0, NULL, NULL, NULL, 0 } -}; + *mode = NULL; + cp = recvbuffer; -struct options { - const char *o_type; - char *o_request; - int o_reply; /* turn into union if need be */ -} options[] = { - { "tsize", NULL, 0 }, /* OPT_TSIZE */ - { "timeout", NULL, 0 }, /* OPT_TIMEOUT */ - { NULL, NULL, 0 } -}; + i = get_field(peer, recvbuffer, size); + if (i >= PATH_MAX) { + tftp_log(LOG_ERR, "Bad option - filename too long"); + send_error(peer, EBADOP); + exit(1); + } + *filename = recvbuffer; + tftp_log(LOG_INFO, "Filename: '%s'", *filename); + cp += i; -enum opt_enum { - OPT_TSIZE = 0, - OPT_TIMEOUT, -}; + i = get_field(peer, cp, size); + *mode = cp; + cp += i; + + /* Find the file transfer mode */ + for (cp = *mode; *cp; cp++) + if (isupper(*cp)) + *cp = tolower(*cp); + for (pf = formats; pf->f_mode; pf++) + if (strcmp(pf->f_mode, *mode) == 0) + break; + if (pf->f_mode == NULL) { + tftp_log(LOG_ERR, + "Bad option - Unknown transfer mode (%s)", *mode); + send_error(peer, EBADOP); + exit(1); + } + tftp_log(LOG_INFO, "Mode: '%s'", *mode); + + return (cp + 1); +} /* - * Handle initial connection protocol. + * WRQ - receive a file from the client */ void -tftp(struct tftphdr *tp, int size) +tftp_wrq(int peer, char *recvbuffer, ssize_t size) { char *cp; - int i, first = 1, has_options = 0, ecode; - struct formats *pf; - char *filename, *mode, *option, *ccp; + int has_options = 0, ecode; + char *filename, *mode; char fnbuf[PATH_MAX]; - cp = tp->th_stuff; -again: - while (cp < buf + size) { - if (*cp == '\0') - break; - cp++; - } - if (*cp != '\0') { - nak(EBADOP); - exit(1); - } - i = cp - tp->th_stuff; - if (i >= sizeof(fnbuf)) { - nak(EBADOP); - exit(1); - } - memcpy(fnbuf, tp->th_stuff, i); - fnbuf[i] = '\0'; + cp = parse_header(peer, recvbuffer, size, &filename, &mode); + size -= (cp - recvbuffer) + 1; + + strcpy(fnbuf, filename); reduce_path(fnbuf); filename = fnbuf; - if (first) { - mode = ++cp; - first = 0; - goto again; + + if (size > 0) { + if (options_rfc_enabled) + has_options = !parse_options(peer, cp, size); + else + tftp_log(LOG_INFO, "Options found but not enabled"); } - for (cp = mode; *cp; cp++) - if (isupper(*cp)) - *cp = tolower(*cp); - for (pf = formats; pf->f_mode; pf++) - if (strcmp(pf->f_mode, mode) == 0) - break; - if (pf->f_mode == 0) { - nak(EBADOP); - exit(1); + + ecode = validate_access(peer, &filename, WRQ); + if (ecode == 0) { + if (has_options) + send_oack(peer); + else + send_ack(peer, 0); } - while (++cp < buf + size) { - for (i = 2, ccp = cp; i > 0; ccp++) { - if (ccp >= buf + size) { - /* - * Don't reject the request, just stop trying - * to parse the option and get on with it. - * Some Apple Open Firmware versions have - * trailing garbage on the end of otherwise - * valid requests. - */ - goto option_fail; - } else if (*ccp == '\0') - i--; - } - for (option = cp; *cp; cp++) - if (isupper(*cp)) - *cp = tolower(*cp); - for (i = 0; options[i].o_type != NULL; i++) - if (strcmp(option, options[i].o_type) == 0) { - options[i].o_request = ++cp; - has_options = 1; - } - cp = ccp-1; + if (logging) { + tftp_log(LOG_INFO, "%s: write request for %s: %s", peername, + filename, errtomsg(ecode)); } -option_fail: - if (options[OPT_TIMEOUT].o_request) { - int to = atoi(options[OPT_TIMEOUT].o_request); - if (to < 1 || to > 255) { - nak(EBADOP); - exit(1); - } - else if (to <= max_rexmtval) - options[OPT_TIMEOUT].o_reply = rexmtval = to; + tftp_recvfile(peer, mode); + exit(0); +} + +/* + * RRQ - send a file to the client + */ +void +tftp_rrq(int peer, char *recvbuffer, ssize_t size) +{ + char *cp; + int has_options = 0, ecode; + char *filename, *mode; + char fnbuf[PATH_MAX]; + + cp = parse_header(peer, recvbuffer, size, &filename, &mode); + size -= (cp - recvbuffer) + 1; + + strcpy(fnbuf, filename); + reduce_path(fnbuf); + filename = fnbuf; + + if (size > 0) { + if (options_rfc_enabled) + has_options = !parse_options(peer, cp, size); else - options[OPT_TIMEOUT].o_request = NULL; + tftp_log(LOG_INFO, "Options found but not enabled"); } - ecode = (*pf->f_validate)(&filename, tp->th_opcode); - if (has_options && ecode == 0) - oack(); - if (logging) { - char hbuf[NI_MAXHOST]; + ecode = validate_access(peer, &filename, RRQ); + if (ecode == 0) { + if (has_options) { + int n; + char lrecvbuffer[MAXPKTSIZE]; + struct tftphdr *rp = (struct tftphdr *)lrecvbuffer; - getnameinfo((struct sockaddr *)&from, from.ss_len, - hbuf, sizeof(hbuf), NULL, 0, 0); - syslog(LOG_INFO, "%s: %s request for %s: %s", hbuf, - tp->th_opcode == WRQ ? "write" : "read", - filename, errtomsg(ecode)); + send_oack(peer); + n = receive_packet(peer, lrecvbuffer, MAXPKTSIZE, + NULL, timeoutpacket); + if (n < 0) { + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_DEBUG, "Aborting: %s", + rp_strerror(n)); + return; + } + if (rp->th_opcode != ACK) { + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_DEBUG, + "Expected ACK, got %s on OACK", + packettype(rp->th_opcode)); + return; + } + } } + + if (logging) + tftp_log(LOG_INFO, "%s: read request for %s: %s", peername, + filename, errtomsg(ecode)); + if (ecode) { /* * Avoid storms of naks to a RRQ broadcast for a relative @@ -508,19 +604,13 @@ option_fail: */ if (suppress_naks && *filename != '/' && ecode == ENOTFOUND) exit(0); - nak(ecode); + tftp_log(LOG_ERR, "Prevent NAK storm"); + send_error(peer, ecode); exit(1); } - if (tp->th_opcode == WRQ) - (*pf->f_recv)(pf); - else - (*pf->f_send)(pf); - exit(0); + tftp_xmitfile(peer, mode); } - -FILE *file; - /* * Find the next value for YYYYMMDD.nn when the file to be written should * be unique. Due to the limitations of nn, we will fail if nn reaches 100. @@ -536,8 +626,6 @@ find_next_name(char *filename, int *fd) struct tm lt; char yyyymmdd[MAXPATHLEN]; char newname[MAXPATHLEN]; - struct stat sb; - int ret; /* Create the YYYYMMDD part of the filename */ time(&tval); @@ -553,7 +641,7 @@ find_next_name(char *filename, int *fd) /* Make sure the new filename is not too long */ if (strlen(filename) > MAXPATHLEN - len - 5) { syslog(LOG_WARNING, - "Filename too long (%d characters, %d maximum)", + "Filename too long (%zd characters, %zd maximum)", strlen(filename), MAXPATHLEN - len - 5); return (EACCESS); } @@ -584,7 +672,7 @@ find_next_name(char *filename, int *fd) * given as we have no login directory. */ int -validate_access(char **filep, int mode) +validate_access(int peer, char **filep, int mode) { struct stat stbuf; int fd; @@ -660,14 +748,13 @@ validate_access(char **filep, int mode) else if (mode == RRQ) return (err); } - if (options[OPT_TSIZE].o_request) { - if (mode == RRQ) - options[OPT_TSIZE].o_reply = stbuf.st_size; - else - /* XXX Allows writes of all sizes. */ - options[OPT_TSIZE].o_reply = - atoi(options[OPT_TSIZE].o_request); - } + + /* + * This option is handled here because it (might) require(s) the + * size of the file. + */ + option_tsize(peer, NULL, mode, &stbuf); + if (mode == RRQ) fd = open(filename, O_RDONLY); else { @@ -694,305 +781,60 @@ validate_access(char **filep, int mode) return (0); } -int timeouts; -jmp_buf timeoutbuf; - -void -timer(int sig __unused) +static void +tftp_xmitfile(int peer, const char *mode) { - if (++timeouts > MAX_TIMEOUTS) - exit(1); - longjmp(timeoutbuf, 1); -} + uint16_t block; + uint32_t amount; + time_t now; + struct tftp_stats ts; -/* - * Send the requested file. - */ -void -xmitfile(struct formats *pf) -{ - struct tftphdr *dp; - struct tftphdr *ap; /* ack packet */ - int size, n; - volatile unsigned short block; - - signal(SIGALRM, timer); - dp = r_init(); - ap = (struct tftphdr *)ackbuf; - block = 1; - do { - size = readit(file, &dp, pf->f_convert); - if (size < 0) { - nak(errno + 100); - goto abort; - } - dp->th_opcode = htons((u_short)DATA); - dp->th_block = htons((u_short)block); - timeouts = 0; - (void)setjmp(timeoutbuf); - -send_data: - { - int i, t = 1; - for (i = 0; ; i++){ - if (send(peer, dp, size + 4, 0) != size + 4) { - sleep(t); - t = (t < 32) ? t<< 1 : t; - if (i >= 12) { - syslog(LOG_ERR, "write: %m"); - goto abort; - } - } - break; - } - } - read_ahead(file, pf->f_convert); - for ( ; ; ) { - alarm(rexmtval); /* read the ack */ - n = recv(peer, ackbuf, sizeof (ackbuf), 0); - alarm(0); - if (n < 0) { - syslog(LOG_ERR, "read: %m"); - goto abort; - } - ap->th_opcode = ntohs((u_short)ap->th_opcode); - ap->th_block = ntohs((u_short)ap->th_block); + now = time(NULL); + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_DEBUG, "Transmitting file"); - if (ap->th_opcode == ERROR) - goto abort; - - if (ap->th_opcode == ACK) { - if (ap->th_block == block) - break; - /* Re-synchronize with the other side */ - (void) synchnet(peer); - if (ap->th_block == (block -1)) - goto send_data; - } - - } - block++; - } while (size == SEGSIZE); -abort: - (void) fclose(file); + read_init(0, file, mode); + block = 1; + tftp_send(peer, &block, &ts); + read_close(); + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_INFO, "Sent %d bytes in %d seconds", + amount, time(NULL) - now); } -void -justquit(int sig __unused) +static void +tftp_recvfile(int peer, const char *mode) { - exit(0); -} + uint32_t filesize; + uint16_t block; + struct timeval now1, now2; + struct tftp_stats ts; + gettimeofday(&now1, NULL); + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_DEBUG, "Receiving file"); + + write_init(0, file, mode); -/* - * Receive a file. - */ -void -recvfile(struct formats *pf) -{ - struct tftphdr *dp; - struct tftphdr *ap; /* ack buffer */ - int n, size; - volatile unsigned short block; - - signal(SIGALRM, timer); - dp = w_init(); - ap = (struct tftphdr *)ackbuf; block = 0; - do { - timeouts = 0; - ap->th_opcode = htons((u_short)ACK); - ap->th_block = htons((u_short)block); - block++; - (void) setjmp(timeoutbuf); -send_ack: - if (send(peer, ackbuf, 4, 0) != 4) { - syslog(LOG_ERR, "write: %m"); - goto abort; - } - write_behind(file, pf->f_convert); - for ( ; ; ) { - alarm(rexmtval); - n = recv(peer, dp, PKTSIZE, 0); - alarm(0); - if (n < 0) { /* really? */ - syslog(LOG_ERR, "read: %m"); - goto abort; - } - dp->th_opcode = ntohs((u_short)dp->th_opcode); - dp->th_block = ntohs((u_short)dp->th_block); - if (dp->th_opcode == ERROR) - goto abort; - if (dp->th_opcode == DATA) { - if (dp->th_block == block) { - break; /* normal */ - } - /* Re-synchronize with the other side */ - (void) synchnet(peer); - if (dp->th_block == (block-1)) - goto send_ack; /* rexmit */ - } - } - /* size = write(file, dp->th_data, n - 4); */ - size = writeit(file, &dp, n - 4, pf->f_convert); - if (size != (n-4)) { /* ahem */ - if (size < 0) nak(errno + 100); - else nak(ENOSPACE); - goto abort; - } - } while (size == SEGSIZE); - write_behind(file, pf->f_convert); - (void) fclose(file); /* close data file */ - - ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */ - ap->th_block = htons((u_short)(block)); - (void) send(peer, ackbuf, 4, 0); - - signal(SIGALRM, justquit); /* just quit on timeout */ - alarm(rexmtval); - n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */ - alarm(0); - if (n >= 4 && /* if read some data */ - dp->th_opcode == DATA && /* and got a data block */ - block == dp->th_block) { /* then my last ack was lost */ - (void) send(peer, ackbuf, 4, 0); /* resend final ack */ - } -abort: - return; -} + tftp_receive(peer, &block, &ts, NULL, 0); -struct errmsg { - int e_code; - const char *e_msg; -} errmsgs[] = { - { EUNDEF, "Undefined error code" }, - { ENOTFOUND, "File not found" }, - { EACCESS, "Access violation" }, - { ENOSPACE, "Disk full or allocation exceeded" }, - { EBADOP, "Illegal TFTP operation" }, - { EBADID, "Unknown transfer ID" }, - { EEXISTS, "File already exists" }, - { ENOUSER, "No such user" }, - { EOPTNEG, "Option negotiation" }, - { -1, 0 } -}; + write_close(); -static const char * -errtomsg(int error) -{ - static char ebuf[20]; - struct errmsg *pe; - if (error == 0) - return "success"; - for (pe = errmsgs; pe->e_code >= 0; pe++) - if (pe->e_code == error) - return pe->e_msg; - snprintf(ebuf, sizeof(buf), "error %d", error); - return ebuf; -} + if (debug&DEBUG_SIMPLE) { + double f; + if (now1.tv_usec > now2.tv_usec) { + now2.tv_usec += 1000000; + now2.tv_sec--; + } -/* - * Send a nak packet (error message). - * Error code passed in is one of the - * standard TFTP codes, or a UNIX errno - * offset by 100. - */ -static void -nak(int error) -{ - struct tftphdr *tp; - int length; - struct errmsg *pe; - - tp = (struct tftphdr *)buf; - tp->th_opcode = htons((u_short)ERROR); - tp->th_code = htons((u_short)error); - for (pe = errmsgs; pe->e_code >= 0; pe++) - if (pe->e_code == error) - break; - if (pe->e_code < 0) { - pe->e_msg = strerror(error - 100); - tp->th_code = EUNDEF; /* set 'undef' errorcode */ + f = now2.tv_sec - now1.tv_sec + + (now2.tv_usec - now1.tv_usec) / 100000.0; + tftp_log(LOG_INFO, + "Download of %d bytes in %d blocks completed after %0.1f seconds\n", + filesize, block, f); } - strcpy(tp->th_msg, pe->e_msg); - length = strlen(pe->e_msg); - tp->th_msg[length] = '\0'; - length += 5; - if (send(peer, buf, length, 0) != length) - syslog(LOG_ERR, "nak: %m"); -} -/* translate IPv4 mapped IPv6 address to IPv4 address */ -static void -unmappedaddr(struct sockaddr_in6 *sin6) -{ - struct sockaddr_in *sin4; - u_int32_t addr; - int port; - - if (sin6->sin6_family != AF_INET6 || - !IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) - return; - sin4 = (struct sockaddr_in *)sin6; - addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12]; - port = sin6->sin6_port; - memset(sin4, 0, sizeof(struct sockaddr_in)); - sin4->sin_addr.s_addr = addr; - sin4->sin_port = port; - sin4->sin_family = AF_INET; - sin4->sin_len = sizeof(struct sockaddr_in); + return; } -/* - * Send an oack packet (option acknowledgement). - */ -static void -oack(void) -{ - struct tftphdr *tp, *ap; - int size, i, n; - char *bp; - - tp = (struct tftphdr *)buf; - bp = buf + 2; - size = sizeof(buf) - 2; - tp->th_opcode = htons((u_short)OACK); - for (i = 0; options[i].o_type != NULL; i++) { - if (options[i].o_request) { - n = snprintf(bp, size, "%s%c%d", options[i].o_type, - 0, options[i].o_reply); - bp += n+1; - size -= n+1; - if (size < 0) { - syslog(LOG_ERR, "oack: buffer overflow"); - exit(1); - } - } - } - size = bp - buf; - ap = (struct tftphdr *)ackbuf; - signal(SIGALRM, timer); - timeouts = 0; - - (void)setjmp(timeoutbuf); - if (send(peer, buf, size, 0) != size) { - syslog(LOG_INFO, "oack: %m"); - exit(1); - } - - for (;;) { - alarm(rexmtval); - n = recv(peer, ackbuf, sizeof (ackbuf), 0); - alarm(0); - if (n < 0) { - syslog(LOG_ERR, "recv: %m"); - exit(1); - } - ap->th_opcode = ntohs((u_short)ap->th_opcode); - ap->th_block = ntohs((u_short)ap->th_block); - if (ap->th_opcode == ERROR) - exit(1); - if (ap->th_opcode == ACK && ap->th_block == 0) - break; - } -} -- cgit v1.1 From 497dc1cc7bb59a4cd9a4a80d03213a538e172d84 Mon Sep 17 00:00:00 2001 From: kevlo Date: Tue, 4 May 2010 10:14:05 +0000 Subject: Add support for FA626TE. Tested on GM8181 development board. --- sys/arm/arm/cpufunc.c | 99 ++++++++++++++++++++--------------------- sys/arm/arm/cpufunc_asm_fa526.S | 4 ++ sys/arm/arm/elf_trampoline.c | 2 +- sys/arm/arm/identcpu.c | 4 +- sys/arm/include/cpuconf.h | 6 ++- sys/arm/include/cpufunc.h | 12 ++--- sys/conf/options.arm | 1 + 7 files changed, 67 insertions(+), 61 deletions(-) diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index 2f4c3a1..09c2026 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -783,69 +783,66 @@ struct cpu_functions xscalec3_cpufuncs = { #endif /* CPU_XSCALE_81342 */ -#if defined(CPU_FA526) +#if defined(CPU_FA526) || defined(CPU_FA626TE) struct cpu_functions fa526_cpufuncs = { /* CPU functions */ - .cf_id = cpufunc_id, - .cf_cpwait = cpufunc_nullop, + cpufunc_id, /* id */ + cpufunc_nullop, /* cpwait */ /* MMU functions */ - .cf_control = cpufunc_control, - .cf_domains = cpufunc_domains, - .cf_setttb = fa526_setttb, - .cf_faultstatus = cpufunc_faultstatus, - .cf_faultaddress = cpufunc_faultaddress, + cpufunc_control, /* control */ + cpufunc_domains, /* domain */ + fa526_setttb, /* setttb */ + cpufunc_faultstatus, /* faultstatus */ + cpufunc_faultaddress, /* faultaddress */ /* TLB functions */ - .cf_tlb_flushID = armv4_tlb_flushID, - .cf_tlb_flushID_SE = fa526_tlb_flushID_SE, - .cf_tlb_flushI = armv4_tlb_flushI, - .cf_tlb_flushI_SE = fa526_tlb_flushI_SE, - .cf_tlb_flushD = armv4_tlb_flushD, - .cf_tlb_flushD_SE = armv4_tlb_flushD_SE, + armv4_tlb_flushID, /* tlb_flushID */ + fa526_tlb_flushID_SE, /* tlb_flushID_SE */ + armv4_tlb_flushI, /* tlb_flushI */ + fa526_tlb_flushI_SE, /* tlb_flushI_SE */ + armv4_tlb_flushD, /* tlb_flushD */ + armv4_tlb_flushD_SE, /* tlb_flushD_SE */ /* Cache operations */ - .cf_icache_sync_all = fa526_icache_sync_all, - .cf_icache_sync_range = fa526_icache_sync_range, - - .cf_dcache_wbinv_all = fa526_dcache_wbinv_all, - .cf_dcache_wbinv_range = fa526_dcache_wbinv_range, - .cf_dcache_inv_range = fa526_dcache_inv_range, - .cf_dcache_wb_range = fa526_dcache_wb_range, - - .cf_idcache_wbinv_all = fa526_idcache_wbinv_all, - .cf_idcache_wbinv_range = fa526_idcache_wbinv_range, - + fa526_icache_sync_all, /* icache_sync_all */ + fa526_icache_sync_range, /* icache_sync_range */ - .cf_l2cache_wbinv_all = cpufunc_nullop, - .cf_l2cache_wbinv_range = (void *)cpufunc_nullop, - .cf_l2cache_inv_range = (void *)cpufunc_nullop, - .cf_l2cache_wb_range = (void *)cpufunc_nullop, + fa526_dcache_wbinv_all, /* dcache_wbinv_all */ + fa526_dcache_wbinv_range, /* dcache_wbinv_range */ + fa526_dcache_inv_range, /* dcache_inv_range */ + fa526_dcache_wb_range, /* dcache_wb_range */ + fa526_idcache_wbinv_all, /* idcache_wbinv_all */ + fa526_idcache_wbinv_range, /* idcache_wbinv_range */ + cpufunc_nullop, /* l2cache_wbinv_all */ + (void *)cpufunc_nullop, /* l2cache_wbinv_range */ + (void *)cpufunc_nullop, /* l2cache_inv_range */ + (void *)cpufunc_nullop, /* l2cache_wb_range */ /* Other functions */ - .cf_flush_prefetchbuf = fa526_flush_prefetchbuf, - .cf_drain_writebuf = armv4_drain_writebuf, - .cf_flush_brnchtgt_C = cpufunc_nullop, - .cf_flush_brnchtgt_E = fa526_flush_brnchtgt_E, + fa526_flush_prefetchbuf, /* flush_prefetchbuf */ + armv4_drain_writebuf, /* drain_writebuf */ + cpufunc_nullop, /* flush_brnchtgt_C */ + fa526_flush_brnchtgt_E, /* flush_brnchtgt_E */ - .cf_sleep = fa526_cpu_sleep, + fa526_cpu_sleep, /* sleep */ /* Soft functions */ - .cf_dataabt_fixup = cpufunc_null_fixup, - .cf_prefetchabt_fixup = cpufunc_null_fixup, + cpufunc_null_fixup, /* dataabt_fixup */ + cpufunc_null_fixup, /* prefetchabt_fixup */ - .cf_context_switch = fa526_context_switch, + fa526_context_switch, /* context_switch */ - .cf_setup = fa526_setup -}; -#endif /* CPU_FA526 */ + fa526_setup /* cpu setup */ +}; +#endif /* CPU_FA526 || CPU_FA626TE */ /* @@ -856,11 +853,11 @@ struct cpu_functions cpufuncs; u_int cputype; u_int cpu_reset_needs_v4_MMU_disable; /* flag used in locore.s */ -#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \ - defined (CPU_ARM9E) || defined (CPU_ARM10) || \ - defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ - defined(CPU_FA526) || \ +#if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \ + defined (CPU_ARM9E) || defined (CPU_ARM10) || \ + defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ + defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ + defined(CPU_FA526) || defined(CPU_FA626TE) || \ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) static void get_cachetype_cp15(void); @@ -1141,8 +1138,8 @@ set_cpufuncs() goto out; } #endif /* CPU_SA1110 */ -#ifdef CPU_FA526 - if (cputype == CPU_ID_FA526) { +#if defined(CPU_FA526) || defined(CPU_FA626TE) + if (cputype == CPU_ID_FA526 || cputype == CPU_ID_FA626TE) { cpufuncs = fa526_cpufuncs; cpu_reset_needs_v4_MMU_disable = 1; /* SA needs it */ get_cachetype_cp15(); @@ -1153,7 +1150,7 @@ set_cpufuncs() goto out; } -#endif /* CPU_FA526 */ +#endif /* CPU_FA526 || CPU_FA626TE */ #ifdef CPU_IXP12X0 if (cputype == CPU_ID_IXP1200) { cpufuncs = ixp12x0_cpufuncs; @@ -1629,7 +1626,7 @@ late_abort_fixup(arg) defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \ defined(CPU_ARM10) || defined(CPU_ARM11) || \ - defined(CPU_FA526) + defined(CPU_FA526) || defined(CPU_FA626TE) #define IGN 0 #define OR 1 @@ -2095,7 +2092,7 @@ sa11x0_setup(args) } #endif /* CPU_SA1100 || CPU_SA1110 */ -#if defined(CPU_FA526) +#if defined(CPU_FA526) || defined(CPU_FA626TE) struct cpu_option fa526_options[] = { #ifdef COMPAT_12 { "nocache", IGN, BIC, (CPU_CONTROL_IC_ENABLE | @@ -2149,7 +2146,7 @@ fa526_setup(char *args) ctrl = cpuctrl; cpu_control(0xffffffff, cpuctrl); } -#endif /* CPU_FA526 */ +#endif /* CPU_FA526 || CPU_FA626TE */ #if defined(CPU_IXP12X0) diff --git a/sys/arm/arm/cpufunc_asm_fa526.S b/sys/arm/arm/cpufunc_asm_fa526.S index d68d7a6..d53d29a 100644 --- a/sys/arm/arm/cpufunc_asm_fa526.S +++ b/sys/arm/arm/cpufunc_asm_fa526.S @@ -32,7 +32,11 @@ #include __FBSDID("$FreeBSD$"); +#ifdef CPU_FA526 #define CACHELINE_SIZE 16 +#else +#define CACHELINE_SIZE 32 +#endif ENTRY(fa526_setttb) mov r1, #0 diff --git a/sys/arm/arm/elf_trampoline.c b/sys/arm/arm/elf_trampoline.c index 6addbc3..0f725c8 100644 --- a/sys/arm/arm/elf_trampoline.c +++ b/sys/arm/arm/elf_trampoline.c @@ -57,7 +57,7 @@ void __startC(void); #define cpu_idcache_wbinv_all arm8_cache_purgeID #elif defined(CPU_ARM9) #define cpu_idcache_wbinv_all arm9_idcache_wbinv_all -#elif defined(CPU_FA526) +#elif defined(CPU_FA526) || defined(CPU_FA626TE) #define cpu_idcache_wbinv_all fa526_idcache_wbinv_all #elif defined(CPU_ARM9E) #define cpu_idcache_wbinv_all armv5_ec_idcache_wbinv_all diff --git a/sys/arm/arm/identcpu.c b/sys/arm/arm/identcpu.c index 6d2a0f0..1a9c996 100644 --- a/sys/arm/arm/identcpu.c +++ b/sys/arm/arm/identcpu.c @@ -220,7 +220,9 @@ const struct cpuidtab cpuids[] = { generic_steppings }, { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S", generic_steppings }, - { CPU_ID_FA526, CPU_CLASS_ARM9, "FA526", + { CPU_ID_FA526, CPU_CLASS_ARM9, "FA526", + generic_steppings }, + { CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE", generic_steppings }, { CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T", diff --git a/sys/arm/include/cpuconf.h b/sys/arm/include/cpuconf.h index 942b591..c8a9b6e 100644 --- a/sys/arm/include/cpuconf.h +++ b/sys/arm/include/cpuconf.h @@ -62,6 +62,7 @@ defined(CPU_XSCALE_80321) + \ defined(CPU_XSCALE_PXA2X0) + \ defined(CPU_FA526) + \ + defined(CPU_FA626TE) + \ defined(CPU_XSCALE_IXP425)) /* @@ -78,7 +79,7 @@ #if (defined(CPU_ARM9E) || defined(CPU_ARM10) || \ defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) || \ - defined(CPU_XSCALE_PXA2X0)) + defined(CPU_XSCALE_PXA2X0) || defined(CPU_FA626TE)) #define ARM_ARCH_5 1 #else #define ARM_ARCH_5 0 @@ -126,7 +127,8 @@ #if (defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) || \ defined(CPU_ARM8) || defined(CPU_ARM9) || defined(CPU_ARM9E) || \ - defined(CPU_ARM10) || defined(CPU_ARM11) || defined(CPU_FA526)) + defined(CPU_ARM10) || defined(CPU_ARM11) || defined(CPU_FA526) || \ + defined(CPU_FA626TE)) #define ARM_MMU_GENERIC 1 #else #define ARM_MMU_GENERIC 0 diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index 8494966..4ab63fb 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -284,7 +284,7 @@ u_int arm8_clock_config (u_int, u_int); #endif -#ifdef CPU_FA526 +#if defined(CPU_FA526) || defined(CPU_FA626TE) void fa526_setup (char *arg); void fa526_setttb (u_int ttb); void fa526_context_switch (void); @@ -464,11 +464,11 @@ extern unsigned armv5_dcache_index_max; extern unsigned armv5_dcache_index_inc; #endif -#if defined(CPU_ARM9) || defined(CPU_ARM9E) || defined(CPU_ARM10) || \ - defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \ - defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ - defined(CPU_FA526) || \ - defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ +#if defined(CPU_ARM9) || defined(CPU_ARM9E) || defined(CPU_ARM10) || \ + defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \ + defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \ + defined(CPU_FA526) || defined(CPU_FA626TE) || \ + defined(CPU_XSCALE_PXA2X0) || defined(CPU_XSCALE_IXP425) || \ defined(CPU_XSCALE_80219) || defined(CPU_XSCALE_81342) void armv4_tlb_flushID (void); diff --git a/sys/conf/options.arm b/sys/conf/options.arm index 922d38f..6b19281 100644 --- a/sys/conf/options.arm +++ b/sys/conf/options.arm @@ -37,3 +37,4 @@ AT91_BWCT opt_at91.h AT91_TSC opt_at91.h AT91_KWIKBYTE opt_at91.h CPU_FA526 opt_global.h +CPU_FA626TE opt_global.h -- cgit v1.1 From 502f87be800745c18b2239898045c24a423da3a3 Mon Sep 17 00:00:00 2001 From: nork Date: Tue, 4 May 2010 11:25:04 +0000 Subject: Add support run services_mkdb(8). Approved by: dougb, imp (mentor) Reviewed by: ume MFC after: 2 weeks --- usr.sbin/mergemaster/mergemaster.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/usr.sbin/mergemaster/mergemaster.sh b/usr.sbin/mergemaster/mergemaster.sh index 7f06968..84ee455 100755 --- a/usr.sbin/mergemaster/mergemaster.sh +++ b/usr.sbin/mergemaster/mergemaster.sh @@ -849,6 +849,9 @@ mm_install () { /etc/login.conf) NEED_CAP_MKDB=yes ;; + /etc/services) + NEED_SERVICES_MKDB=yes + ;; /etc/master.passwd) do_install_and_rm 600 "${1}" "${DESTDIR}${INSTALL_DIR}" NEED_PWD_MKDB=yes @@ -1278,6 +1281,17 @@ case "${NEED_CAP_MKDB}" in ;; esac +case "${NEED_SERVICES_MKDB}" in +'') ;; +*) + echo '' + echo "*** You installed a services file, so make sure that you run" + echo " '/usr/sbin/services_mkdb -q -o ${DESTDIR}/var/db/services.db ${DESTDIR}/etc/services'" + echo " to rebuild your services database" + run_it_now "/usr/sbin/services_mkdb -q -o ${DESTDIR}/var/db/services.db ${DESTDIR}/etc/services" + ;; +esac + case "${NEED_PWD_MKDB}" in '') ;; *) -- cgit v1.1 From 249847477313ecfdf314f47b62fb935897c2a5f4 Mon Sep 17 00:00:00 2001 From: emaste Date: Tue, 4 May 2010 11:34:13 +0000 Subject: Restore historical behaviour of only executing chflags on files that exist. This eliminates cosmetic errors of the form "chflags: ...: No such file or directory" during an installworld to an empty destination. --- usr.bin/chpass/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/usr.bin/chpass/Makefile b/usr.bin/chpass/Makefile index a5571d7..566173e 100644 --- a/usr.bin/chpass/Makefile +++ b/usr.bin/chpass/Makefile @@ -38,7 +38,9 @@ MLINKS+= chpass.1 ypchpass.1 chpass.1 ypchfn.1 chpass.1 ypchsh.1 beforeinstall: .for i in chpass chfn chsh ypchpass ypchfn ypchsh +.if exists(${DESTDIR}${BINDIR}/$i) -chflags noschg ${DESTDIR}${BINDIR}/$i +.endif .endfor .if !defined(NO_FSCHG) -- cgit v1.1 From a5f9262d67ae99e9ce1468b626a63c5c9cafbb26 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 4 May 2010 13:07:40 +0000 Subject: Bring in new files from edwin's tftp --- libexec/tftpd/tftp-file.c | 257 +++++++++++++++++++++++ libexec/tftpd/tftp-file.h | 37 ++++ libexec/tftpd/tftp-io.c | 478 ++++++++++++++++++++++++++++++++++++++++++ libexec/tftpd/tftp-io.h | 47 +++++ libexec/tftpd/tftp-options.c | 390 ++++++++++++++++++++++++++++++++++ libexec/tftpd/tftp-options.h | 62 ++++++ libexec/tftpd/tftp-transfer.c | 318 ++++++++++++++++++++++++++++ libexec/tftpd/tftp-transfer.h | 31 +++ libexec/tftpd/tftp-utils.c | 320 ++++++++++++++++++++++++++++ libexec/tftpd/tftp-utils.h | 124 +++++++++++ 10 files changed, 2064 insertions(+) create mode 100644 libexec/tftpd/tftp-file.c create mode 100644 libexec/tftpd/tftp-file.h create mode 100644 libexec/tftpd/tftp-io.c create mode 100644 libexec/tftpd/tftp-io.h create mode 100644 libexec/tftpd/tftp-options.c create mode 100644 libexec/tftpd/tftp-options.h create mode 100644 libexec/tftpd/tftp-transfer.c create mode 100644 libexec/tftpd/tftp-transfer.h create mode 100644 libexec/tftpd/tftp-utils.c create mode 100644 libexec/tftpd/tftp-utils.h diff --git a/libexec/tftpd/tftp-file.c b/libexec/tftpd/tftp-file.c new file mode 100644 index 0000000..e0f8e78 --- /dev/null +++ b/libexec/tftpd/tftp-file.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "tftp-file.h" +#include "tftp-utils.h" + +static FILE *file; +static int convert; + +static char convbuffer[66000]; +static int gotcr = 0; + +static size_t +convert_from_net(char *buffer, size_t count) +{ + size_t i, n; + + /* + * Convert all CR/LF to LF and all CR,NUL to CR + */ + + n = 0; + for (i = 0; i < count; i++) { + + if (gotcr == 0) { + convbuffer[n++] = buffer[i]; + gotcr = (buffer[i] == '\r'); + continue; + } + + /* CR, NULL -> CR */ + if (buffer[i] == '\0') { + gotcr = 0; + continue; + } + + /* CR, LF -> LF */ + if (buffer[i] == '\n') { + if (n == 0) { + if (ftell(file) != 0) { + fseek(file, -1, SEEK_END); + convbuffer[n++] = '\n'; + } else { + /* This shouldn't happen */ + tftp_log(LOG_ERR, + "Received LF as first character"); + abort(); + } + } else + convbuffer[n-1] = '\n'; + gotcr = 0; + continue; + } + + /* Everything else just accept as is */ + convbuffer[n++] = buffer[i]; + gotcr = (buffer[i] == '\r'); + continue; + } + + return fwrite(convbuffer, 1, n, file); +} + +static size_t +convert_to_net(char *buffer, size_t count, int init) +{ + size_t i; + static size_t n = 0, read = 0; + static int newline = 0; + + if (init) { + newline = 0; + n = 0; + read = 0; + return 0 ; + } + + /* + * Convert all LF to CR,LF and all CR to CR,NUL + */ + i = 0; + + if (newline) { + buffer[i++] = newline; + newline = 0; + } + + while (i < count) { + if (n == read) { + /* When done we're done */ + if (feof(file)) break; + + /* Otherwise read another bunch */ + read = fread(convbuffer, 1, count, file); + if (read == 0) break; + n = 0; + } + + /* CR -> CR,NULL */ + if (convbuffer[n] == '\r') { + buffer[i++] = '\r'; + buffer[i++] = '\0'; + n++; + continue; + } + + /* LF -> CR,LF */ + if (convbuffer[n] == '\n') { + buffer[i++] = '\r'; + buffer[i++] = '\n'; + n++; + continue; + } + + buffer[i++] = convbuffer[n++]; + } + + if (i > count) { + /* + * Whoops... that isn't alllowed (but it will happen + * when there is a CR or LF at the end of the buffer) + */ + newline = buffer[i-1]; + } + + if (i < count) { + /* We are done! */ + return i; + } else + return count; + +} + +int +write_init(int fd, FILE *f, const char *mode) +{ + + if (f == NULL) { + file = fdopen(fd, "w"); + if (file == NULL) { + int en = errno; + tftp_log(LOG_ERR, "fdopen() failed: %s", + strerror(errno)); + return en; + } + } else + file = f; + convert = !strcmp(mode, "netascii"); + return 0; +} + +size_t +write_file(char *buffer, int count) +{ + + if (convert == 0) + return fwrite(buffer, 1, count, file); + + return convert_from_net(buffer, count); +} + +int +write_close(void) +{ + + if (fclose(file) != 0) { + tftp_log(LOG_ERR, "fclose() failed: %s", strerror(errno)); + return 1; + } + return 0; +} + +int +read_init(int fd, FILE *f, const char *mode) +{ + + convert_to_net(NULL, 0, 1); + if (f == NULL) { + file = fdopen(fd, "r"); + if (file == NULL) { + int en = errno; + tftp_log(LOG_ERR, "fdopen() failed: %s", + strerror(errno)); + return en; + } + } else + file = f; + convert = !strcmp(mode, "netascii"); + return 0; +} + +size_t +read_file(char *buffer, int count) +{ + + if (convert == 0) + return fread(buffer, 1, count, file); + + return convert_to_net(buffer, count, 0); +} + +int +read_close(void) +{ + + if (fclose(file) != 0) { + tftp_log(LOG_ERR, "fclose() failed: %s", strerror(errno)); + return 1; + } + return 0; +} + + +int +synchnet(int peer) +{ + + return 0; +} diff --git a/libexec/tftpd/tftp-file.h b/libexec/tftpd/tftp-file.h new file mode 100644 index 0000000..fcc4d0d --- /dev/null +++ b/libexec/tftpd/tftp-file.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +int write_init(int fd, FILE *f, const char *mode); +size_t write_file(char *buffer, int count); +int write_close(void); + +int read_init(int fd, FILE *f, const char *mode); +size_t read_file(char *buffer, int count); +int read_close(void); + +int synchnet(int peer); diff --git a/libexec/tftpd/tftp-io.c b/libexec/tftpd/tftp-io.c new file mode 100644 index 0000000..28628ba --- /dev/null +++ b/libexec/tftpd/tftp-io.c @@ -0,0 +1,478 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tftp-file.h" +#include "tftp-io.h" +#include "tftp-utils.h" +#include "tftp-options.h" + +struct sockaddr_storage peer_sock; +struct sockaddr_storage me_sock; + +static int send_packet(int peer, uint16_t block, char *pkt, int size); + +struct errmsg { + int e_code; + const char *e_msg; +} errmsgs[] = { + { EUNDEF, "Undefined error code" }, + { ENOTFOUND, "File not found" }, + { EACCESS, "Access violation" }, + { ENOSPACE, "Disk full or allocation exceeded" }, + { EBADOP, "Illegal TFTP operation" }, + { EBADID, "Unknown transfer ID" }, + { EEXISTS, "File already exists" }, + { ENOUSER, "No such user" }, + { EOPTNEG, "Option negotiation" }, + { -1, NULL } +}; + +#define DROPPACKET(s) \ + if (packetdroppercentage != 0 && \ + random()%100 < packetdroppercentage) { \ + tftp_log(LOG_DEBUG, "Artifical packet drop in %s", s); \ + return; \ + } +#define DROPPACKETn(s,n) \ + if (packetdroppercentage != 0 && \ + random()%100 < packetdroppercentage) { \ + tftp_log(LOG_DEBUG, "Artifical packet drop in %s", s); \ + return (n); \ + } + +const char * +errtomsg(int error) +{ + static char ebuf[40]; + struct errmsg *pe; + char buf[MAXPKTSIZE]; + + if (error == 0) + return ("success"); + for (pe = errmsgs; pe->e_code >= 0; pe++) + if (pe->e_code == error) + return (pe->e_msg); + snprintf(ebuf, sizeof(buf), "error %d", error); + return (ebuf); +} + +static int +send_packet(int peer, uint16_t block, char *pkt, int size) +{ + int i; + int t = 1; + + for (i = 0; i < 12 ; i++) { + DROPPACKETn("send_packet", 0); + + if (sendto(peer, pkt, size, 0, + (struct sockaddr *)&peer_sock, peer_sock.ss_len) + == size) { + if (i) + tftp_log(LOG_ERR, + "%s block %d, attempt %d successful", + block, i); + return (0); + } + tftp_log(LOG_ERR, + "%s block %d, attempt %d failed (Error %d: %s)", + packettype(ntohs(((struct tftphdr *)(pkt))->th_opcode)), + block, i, errno, strerror(errno)); + sleep(t); + if (t < 32) + t <<= 1; + } + tftp_log(LOG_ERR, "send_packet: %s", strerror(errno)); + return (1); +} + +/* + * Send an ERROR packet (error message). + * Error code passed in is one of the + * standard TFTP codes, or a UNIX errno + * offset by 100. + */ +void +send_error(int peer, int error) +{ + struct tftphdr *tp; + int length; + struct errmsg *pe; + char buf[MAXPKTSIZE]; + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error); + + DROPPACKET("send_error"); + + tp = (struct tftphdr *)buf; + tp->th_opcode = htons((u_short)ERROR); + tp->th_code = htons((u_short)error); + for (pe = errmsgs; pe->e_code >= 0; pe++) + if (pe->e_code == error) + break; + if (pe->e_code < 0) { + pe->e_msg = strerror(error - 100); + tp->th_code = EUNDEF; /* set 'undef' errorcode */ + } + strcpy(tp->th_msg, pe->e_msg); + length = strlen(pe->e_msg); + tp->th_msg[length] = '\0'; + length += 5; + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, "Sending ERROR %d: %s", error, tp->th_msg); + + if (sendto(peer, buf, length, 0, + (struct sockaddr *)&peer_sock, peer_sock.ss_len) != length) + tftp_log(LOG_ERR, "send_error: %s", strerror(errno)); +} + +/* + * Send an WRQ packet (write request). + */ +int +send_wrq(int peer, char *filename, char *mode) +{ + int n; + struct tftphdr *tp; + char *bp; + char buf[MAXPKTSIZE]; + int size; + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, "Sending WRQ: filename: '%s', mode '%s'", + filename, mode + ); + + DROPPACKETn("send_wrq", 1); + + tp = (struct tftphdr *)buf; + tp->th_opcode = htons((u_short)WRQ); + size = 2; + + bp = tp->th_stuff; + strcpy(bp, filename); + bp += strlen(filename); + *bp = 0; + bp++; + size += strlen(filename) + 1; + + strcpy(bp, mode); + bp += strlen(mode); + *bp = 0; + bp++; + size += strlen(mode) + 1; + + if (options_rfc_enabled) + size += make_options(peer, bp, sizeof(buf) - size); + + n = sendto(peer, buf, size, 0, + (struct sockaddr *)&peer_sock, peer_sock.ss_len); + if (n != size) { + tftp_log(LOG_ERR, "send_wrq: %s", strerror(errno)); + return (1); + } + return (0); +} + +/* + * Send an RRQ packet (write request). + */ +int +send_rrq(int peer, char *filename, char *mode) +{ + int n; + struct tftphdr *tp; + char *bp; + char buf[MAXPKTSIZE]; + int size; + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, "Sending RRQ: filename: '%s', mode '%s'", + filename, mode + ); + + DROPPACKETn("send_rrq", 1); + + tp = (struct tftphdr *)buf; + tp->th_opcode = htons((u_short)RRQ); + size = 2; + + bp = tp->th_stuff; + strcpy(bp, filename); + bp += strlen(filename); + *bp = 0; + bp++; + size += strlen(filename) + 1; + + strcpy(bp, mode); + bp += strlen(mode); + *bp = 0; + bp++; + size += strlen(mode) + 1; + + if (options_rfc_enabled) { + options[OPT_TSIZE].o_request = strdup("0"); + size += make_options(peer, bp, sizeof(buf) - size); + } + + n = sendto(peer, buf, size, 0, + (struct sockaddr *)&peer_sock, peer_sock.ss_len); + if (n != size) { + tftp_log(LOG_ERR, "send_rrq: %s", n, strerror(errno)); + return (1); + } + return (0); +} + +/* + * Send an OACK packet (option acknowledgement). + */ +int +send_oack(int peer) +{ + struct tftphdr *tp; + int size, i, n; + char *bp; + char buf[MAXPKTSIZE]; + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, "Sending OACK"); + + DROPPACKETn("send_oack", 0); + + /* + * Send back an options acknowledgement (only the ones with + * a reply for) + */ + tp = (struct tftphdr *)buf; + bp = buf + 2; + size = sizeof(buf) - 2; + tp->th_opcode = htons((u_short)OACK); + for (i = 0; options[i].o_type != NULL; i++) { + if (options[i].o_reply != NULL) { + n = snprintf(bp, size, "%s%c%s", options[i].o_type, + 0, options[i].o_reply); + bp += n+1; + size -= n+1; + if (size < 0) { + tftp_log(LOG_ERR, "oack: buffer overflow"); + exit(1); + } + } + } + size = bp - buf; + + if (sendto(peer, buf, size, 0, + (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) { + tftp_log(LOG_INFO, "send_oack: %s", strerror(errno)); + return (1); + } + + return (0); +} + +/* + * Send an ACK packet (acknowledgement). + */ +int +send_ack(int fp, uint16_t block) +{ + struct tftphdr *tp; + int size; + char *bp; + char buf[MAXPKTSIZE]; + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, "Sending ACK for block %d", block); + + DROPPACKETn("send_ack", 0); + + tp = (struct tftphdr *)buf; + bp = buf + 2; + size = sizeof(buf) - 2; + tp->th_opcode = htons((u_short)ACK); + tp->th_block = htons((u_short)block); + size = 4; + + if (sendto(fp, buf, size, 0, + (struct sockaddr *)&peer_sock, peer_sock.ss_len) != size) { + tftp_log(LOG_INFO, "send_ack: %s", strerror(errno)); + return (1); + } + + return (0); +} + +/* + * Send a DATA packet + */ +int +send_data(int peer, uint16_t block, char *data, int size) +{ + char buf[MAXPKTSIZE]; + struct tftphdr *pkt; + int n; + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, "Sending DATA packet %d of %d bytes", + block, size); + + DROPPACKETn("send_data", 0); + + pkt = (struct tftphdr *)buf; + + pkt->th_opcode = htons((u_short)DATA); + pkt->th_block = htons((u_short)block); + memcpy(pkt->th_data, data, size); + + n = send_packet(peer, block, (char *)pkt, size + 4); + return (n); +} + + +/* + * Receive a packet + */ +jmp_buf timeoutbuf; + +static void +timeout(int sig __unused) +{ + + /* tftp_log(LOG_DEBUG, "Timeout\n"); Inside a signal handler... */ + longjmp(timeoutbuf, 1); +} + +int +receive_packet(int peer, char *data, int size, struct sockaddr_storage *from, + int thistimeout) +{ + struct tftphdr *pkt; + struct sockaddr_storage from_local; + struct sockaddr_storage *pfrom; + socklen_t fromlen; + int n; + static int waiting; + + pfrom = (from == NULL) ? &from_local : from; + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, + "Waiting %d seconds for packet", timeoutpacket); + + pkt = (struct tftphdr *)data; + + waiting = 0; + signal(SIGALRM, timeout); + setjmp(timeoutbuf); + alarm(thistimeout); + + if (waiting > 0) { + alarm(0); + return (RP_TIMEOUT); + } + + if (waiting > 0) { + tftp_log(LOG_ERR, "receive_packet: timeout"); + alarm(0); + return (RP_TIMEOUT); + } + + waiting++; + fromlen = sizeof(*pfrom); + n = recvfrom(peer, data, size, 0, (struct sockaddr *)pfrom, &fromlen); + + alarm(0); + + DROPPACKETn("receive_packet", RP_TIMEOUT); + + if (n < 0) { + tftp_log(LOG_ERR, "receive_packet: timeout"); + return (RP_TIMEOUT); + } + + alarm(0); + + if (n < 0) { + /* No idea what could have happened if it isn't a timeout */ + tftp_log(LOG_ERR, "receive_packet: %s", strerror(errno)); + return (RP_RECVFROM); + } + if (n < 4) { + tftp_log(LOG_ERR, + "receive_packet: packet too small (%d bytes)", n); + return (RP_TOOSMALL); + } + + pkt->th_opcode = ntohs((u_short)pkt->th_opcode); + if (pkt->th_opcode == DATA || + pkt->th_opcode == ACK) + pkt->th_block = ntohs((u_short)pkt->th_block); + + if (pkt->th_opcode == DATA && n > pktsize) { + tftp_log(LOG_ERR, "receive_packet: packet too big"); + return (RP_TOOBIG); + } + + if (((struct sockaddr_in *)(pfrom))->sin_addr.s_addr != + ((struct sockaddr_in *)(&peer_sock))->sin_addr.s_addr) { + tftp_log(LOG_ERR, + "receive_packet: received packet from wrong source"); + return (RP_WRONGSOURCE); + } + + if (pkt->th_opcode == ERROR) { + tftp_log(LOG_ERR, "Got ERROR packet: %s", pkt->th_msg); + return (RP_ERROR); + } + + if (debug&DEBUG_PACKETS) + tftp_log(LOG_DEBUG, "Received %d bytes in a %s packet", + n, packettype(pkt->th_opcode)); + + return n - 4; +} diff --git a/libexec/tftpd/tftp-io.h b/libexec/tftpd/tftp-io.h new file mode 100644 index 0000000..70558bc --- /dev/null +++ b/libexec/tftpd/tftp-io.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#define RP_NONE 0 +#define RP_RECVFROM -1 +#define RP_TOOSMALL -2 +#define RP_ERROR -3 +#define RP_WRONGSOURCE -4 +#define RP_TIMEOUT -5 +#define RP_TOOBIG -6 + +const char *errtomsg(int); +void send_error(int peer, int); +int send_wrq(int peer, char *, char *); +int send_rrq(int peer, char *, char *); +int send_oack(int peer); +int send_ack(int peer, unsigned short); +int send_data(int peer, uint16_t, char *, int); +int receive_packet(int peer, char *, int, struct sockaddr_storage *, int); + +extern struct sockaddr_storage peer_sock; +extern struct sockaddr_storage me_sock; diff --git a/libexec/tftpd/tftp-options.c b/libexec/tftpd/tftp-options.c new file mode 100644 index 0000000..0b97aaf --- /dev/null +++ b/libexec/tftpd/tftp-options.c @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "tftp-utils.h" +#include "tftp-io.h" +#include "tftp-options.h" + +/* + * Option handlers + */ + +struct options options[] = { + { "tsize", NULL, NULL, NULL /* option_tsize */, 1 }, + { "timeout", NULL, NULL, option_timeout, 1 }, + { "blksize", NULL, NULL, option_blksize, 1 }, + { "blksize2", NULL, NULL, option_blksize2, 0 }, + { "rollover", NULL, NULL, option_rollover, 0 }, + { NULL, NULL, NULL, NULL, 0 } +}; + +/* By default allow them */ +int options_rfc_enabled = 1; +int options_extra_enabled = 1; + +/* + * Rules for the option handlers: + * - If there is no o_request, there will be no processing. + * + * For servers + * - Logging is done as warnings. + * - The handler exit()s if there is a serious problem with the + * values submitted in the option. + * + * For clients + * - Logging is done as errors. After all, the server shouldn't + * return rubbish. + * - The handler returns if there is a serious problem with the + * values submitted in the option. + * - Sending the EBADOP packets is done by the handler. + */ + +int +option_tsize(int peer, struct tftphdr *tp, int mode, struct stat *stbuf) +{ + + if (options[OPT_TSIZE].o_request == NULL) + return (0); + + if (mode == RRQ) + asprintf(&options[OPT_TSIZE].o_reply, + "%ju", stbuf->st_size); + else + /* XXX Allows writes of all sizes. */ + options[OPT_TSIZE].o_reply = + strdup(options[OPT_TSIZE].o_request); + return (0); +} + +int +option_timeout(int peer) +{ + + if (options[OPT_TIMEOUT].o_request == NULL) + return (0); + + int to = atoi(options[OPT_TIMEOUT].o_request); + if (to < TIMEOUT_MIN || to > TIMEOUT_MAX) { + tftp_log(acting_as_client ? LOG_ERR : LOG_WARNING, + "Received bad value for timeout. " + "Should be between %d and %d, received %s", + TIMEOUT_MIN, TIMEOUT_MAX); + send_error(peer, EBADOP); + if (acting_as_client) + return (1); + exit(1); + } else { + timeoutpacket = to; + options[OPT_TIMEOUT].o_reply = + strdup(options[OPT_TIMEOUT].o_request); + } + settimeouts(timeoutpacket, timeoutnetwork, maxtimeouts); + + if (debug&DEBUG_OPTIONS) + tftp_log(LOG_DEBUG, "Setting timeout to '%s'", + options[OPT_TIMEOUT].o_reply); + + return (0); +} + +int +option_rollover(int peer) +{ + + if (options[OPT_ROLLOVER].o_request == NULL) + return (0); + + if (strcmp(options[OPT_ROLLOVER].o_request, "0") != 0 + && strcmp(options[OPT_ROLLOVER].o_request, "1") != 0) { + tftp_log(acting_as_client ? LOG_ERR : LOG_WARNING, + "Bad value for rollover, " + "should be either 0 or 1, received '%s', " + "ignoring request", + options[OPT_ROLLOVER].o_request); + if (acting_as_client) { + send_error(peer, EBADOP); + return (1); + } + return (0); + } + options[OPT_ROLLOVER].o_reply = + strdup(options[OPT_ROLLOVER].o_request); + + if (debug&DEBUG_OPTIONS) + tftp_log(LOG_DEBUG, "Setting rollover to '%s'", + options[OPT_ROLLOVER].o_reply); + + return (0); +} + +int +option_blksize(int peer) +{ + int *maxdgram; + char maxbuffer[100]; + size_t len; + + if (options[OPT_BLKSIZE].o_request == NULL) + return (0); + + /* maximum size of an UDP packet according to the system */ + len = sizeof(maxbuffer); + if (sysctlbyname("net.inet.udp.maxdgram", + maxbuffer, &len, NULL, 0) < 0) { + tftp_log(LOG_ERR, "sysctl: net.inet.udp.maxdgram"); + return (acting_as_client ? 1 : 0); + } + maxdgram = (int *)maxbuffer; + + int size = atoi(options[OPT_BLKSIZE].o_request); + if (size < BLKSIZE_MIN || size > BLKSIZE_MAX) { + if (acting_as_client) { + tftp_log(LOG_ERR, + "Invalid blocksize (%d bytes), aborting", + size); + send_error(peer, EBADOP); + return (1); + } else { + tftp_log(LOG_WARNING, + "Invalid blocksize (%d bytes), ignoring request", + size); + return (0); + } + } + + if (size > *maxdgram) { + if (acting_as_client) { + tftp_log(LOG_ERR, + "Invalid blocksize (%d bytes), " + "net.inet.udp.maxdgram sysctl limits it to " + "%d bytes.\n", size, *maxdgram); + send_error(peer, EBADOP); + return (1); + } else { + tftp_log(LOG_WARNING, + "Invalid blocksize (%d bytes), " + "net.inet.udp.maxdgram sysctl limits it to " + "%d bytes.\n", size, *maxdgram); + size = *maxdgram; + /* No reason to return */ + } + } + + asprintf(&options[OPT_BLKSIZE].o_reply, "%d", size); + segsize = size; + pktsize = size + 4; + if (debug&DEBUG_OPTIONS) + tftp_log(LOG_DEBUG, "Setting blksize to '%s'", + options[OPT_BLKSIZE].o_reply); + + return (0); +} + +int +option_blksize2(int peer) +{ + int *maxdgram; + char maxbuffer[100]; + int size, i; + size_t len; + + int sizes[] = { + 8, 16, 32, 64, 128, 256, 512, 1024, + 2048, 4096, 8192, 16384, 32768, 0 + }; + + if (options[OPT_BLKSIZE2].o_request == NULL) + return (0); + + /* maximum size of an UDP packet according to the system */ + len = sizeof(maxbuffer); + if (sysctlbyname("net.inet.udp.maxdgram", + maxbuffer, &len, NULL, 0) < 0) { + tftp_log(LOG_ERR, "sysctl: net.inet.udp.maxdgram"); + return (acting_as_client ? 1 : 0); + } + maxdgram = (int *)maxbuffer; + + size = atoi(options[OPT_BLKSIZE2].o_request); + for (i = 0; sizes[i] != 0; i++) { + if (size == sizes[i]) break; + } + if (sizes[i] == 0) { + tftp_log(LOG_INFO, + "Invalid blocksize2 (%d bytes), ignoring request", size); + return (acting_as_client ? 1 : 0); + } + + if (size > *maxdgram) { + for (i = 0; sizes[i+1] != 0; i++) { + if (*maxdgram < sizes[i+1]) break; + } + tftp_log(LOG_INFO, + "Invalid blocksize2 (%d bytes), net.inet.udp.maxdgram " + "sysctl limits it to %d bytes.\n", size, *maxdgram); + size = sizes[i]; + /* No need to return */ + } + + asprintf(&options[OPT_BLKSIZE2].o_reply, "%d", size); + segsize = size; + pktsize = size + 4; + if (debug&DEBUG_OPTIONS) + tftp_log(LOG_DEBUG, "Setting blksize2 to '%s'", + options[OPT_BLKSIZE2].o_reply); + + return (0); +} + +/* + * Append the available options to the header + */ +uint16_t +make_options(int peer, char *buffer, uint16_t size) { + int i; + char *value; + const char *option; + uint16_t length; + uint16_t returnsize = 0; + + if (!options_rfc_enabled) return (0); + + for (i = 0; options[i].o_type != NULL; i++) { + if (options[i].rfc == 0 && !options_extra_enabled) + continue; + + option = options[i].o_type; + if (acting_as_client) + value = options[i].o_request; + else + value = options[i].o_reply; + if (value == NULL) + continue; + + length = strlen(value) + strlen(option) + 2; + if (size <= length) { + tftp_log(LOG_ERR, + "Running out of option space for " + "option '%s' with value '%s': " + "needed %d bytes, got %d bytes", + option, value, size, length); + continue; + } + + sprintf(buffer, "%s%c%s%c", option, '\000', value, '\000'); + size -= length; + buffer += length; + returnsize += length; + } + + return (returnsize); +} + +/* + * Parse the received options in the header + */ +int +parse_options(int peer, char *buffer, uint16_t size) +{ + int i, options_failed; + char *c, *cp, *option, *value; + + if (!options_rfc_enabled) return (0); + + /* Parse the options */ + cp = buffer; + options_failed = 0; + while (size > 0) { + option = cp; + i = get_field(peer, cp, size); + cp += i; + + value = cp; + i = get_field(peer, cp, size); + cp += i; + + /* We are at the end */ + if (*option == '\0') break; + + if (debug&DEBUG_OPTIONS) + tftp_log(LOG_DEBUG, + "option: '%s' value: '%s'", option, value); + + for (c = option; *c; c++) + if (isupper(*c)) + *c = tolower(*c); + for (i = 0; options[i].o_type != NULL; i++) { + if (strcmp(option, options[i].o_type) == 0) { + if (!acting_as_client) + options[i].o_request = value; + if (!options_extra_enabled && !options[i].rfc) { + tftp_log(LOG_INFO, + "Option '%s' with value '%s' found " + "but it is not an RFC option", + option, value); + continue; + } + if (options[i].o_handler) + options_failed += + (options[i].o_handler)(peer); + break; + } + } + if (options[i].o_type == NULL) + tftp_log(LOG_WARNING, + "Unknown option: '%s'", option); + + size -= strlen(option) + strlen(value) + 2; + } + + return (options_failed); +} + +/* + * Set some default values in the options + */ +void +init_options(void) +{ + + options[OPT_ROLLOVER].o_request = strdup("0"); +} diff --git a/libexec/tftpd/tftp-options.h b/libexec/tftpd/tftp-options.h new file mode 100644 index 0000000..d8bd2fc --- /dev/null +++ b/libexec/tftpd/tftp-options.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Options + */ + +void init_options(void); +uint16_t make_options(int peer, char *buffer, uint16_t size); +int parse_options(int peer, char *buffer, uint16_t size); + +/* Call back functions */ +int option_tsize(int peer, struct tftphdr *, int, struct stat *); +int option_timeout(int peer); +int option_blksize(int peer); +int option_blksize2(int peer); +int option_rollover(int peer); + +extern int options_extra_enabled; +extern int options_rfc_enabled; + +struct options { + const char *o_type; + char *o_request; + char *o_reply; + int (*o_handler)(int peer); + int rfc; +}; + +extern struct options options[]; +enum opt_enum { + OPT_TSIZE = 0, + OPT_TIMEOUT, + OPT_BLKSIZE, + OPT_BLKSIZE2, + OPT_ROLLOVER, +}; diff --git a/libexec/tftpd/tftp-transfer.c b/libexec/tftpd/tftp-transfer.c new file mode 100644 index 0000000..fd0e00d --- /dev/null +++ b/libexec/tftpd/tftp-transfer.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "tftp-file.h" +#include "tftp-io.h" +#include "tftp-utils.h" +#include "tftp-options.h" +#include "tftp-transfer.h" + +/* + * Send a file via the TFTP data session. + */ +void +tftp_send(int peer, uint16_t *block, struct tftp_stats *ts) +{ + struct tftphdr *rp; + int size, n_data, n_ack, try; + uint16_t oldblock; + char sendbuffer[MAXPKTSIZE]; + char recvbuffer[MAXPKTSIZE]; + + rp = (struct tftphdr *)recvbuffer; + *block = 1; + ts->amount = 0; + do { + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_DEBUG, "Sending block %d", *block); + + size = read_file(sendbuffer, segsize); + if (size < 0) { + tftp_log(LOG_ERR, "read_file returned %d", size); + send_error(peer, errno + 100); + goto abort; + } + + for (try = 0; ; try++) { + n_data = send_data(peer, *block, sendbuffer, size); + if (n_data > 0) { + if (try == maxtimeouts) { + tftp_log(LOG_ERR, + "Cannot send DATA packet #%d, " + "giving up", *block); + return; + } + tftp_log(LOG_ERR, + "Cannot send DATA packet #%d, trying again", + *block); + continue; + } + + n_ack = receive_packet(peer, recvbuffer, + MAXPKTSIZE, NULL, timeoutpacket); + if (n_ack < 0) { + if (n_ack == RP_TIMEOUT) { + if (try == maxtimeouts) { + tftp_log(LOG_ERR, + "Timeout #%d send ACK %d " + "giving up", try, *block); + return; + } + tftp_log(LOG_WARNING, + "Timeout #%d on ACK %d", + try, *block); + continue; + } + + /* Either read failure or ERROR packet */ + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_ERR, "Aborting: %s", + rp_strerror(n_ack)); + goto abort; + } + if (rp->th_opcode == ACK) { + ts->blocks++; + if (rp->th_block == *block) { + ts->amount += size; + break; + } + + /* Re-synchronize with the other side */ + (void) synchnet(peer); + if (rp->th_block == (*block - 1)) { + ts->retries++; + continue; + } + } + + } + oldblock = *block; + (*block)++; + if (oldblock > *block) { + if (options[OPT_ROLLOVER].o_request == NULL) { + tftp_log(LOG_ERR, + "Block rollover but not allowed."); + send_error(peer, EBADOP); + gettimeofday(&(ts->tstop), NULL); + return; + } + + *block = atoi(options[OPT_ROLLOVER].o_request); + ts->rollovers++; + } + gettimeofday(&(ts->tstop), NULL); + } while (size == segsize); +abort: + return; +} + +/* + * Receive a file via the TFTP data session. + * + * - It could be that the first block has already arrived while + * trying to figure out if we were receiving options or not. In + * that case it is passed to this function. + */ +void +tftp_receive(int peer, uint16_t *block, struct tftp_stats *ts, + struct tftphdr *firstblock, size_t fb_size) +{ + struct tftphdr *rp; + uint16_t oldblock; + int n_data, n_ack, writesize, i, retry; + char recvbuffer[MAXPKTSIZE]; + + ts->amount = 0; + + if (firstblock != NULL) { + writesize = write_file(firstblock->th_data, fb_size); + ts->amount += writesize; + for (i = 0; ; i++) { + n_ack = send_ack(peer, *block); + if (n_ack > 0) { + if (i == maxtimeouts) { + tftp_log(LOG_ERR, + "Cannot send ACK packet #%d, " + "giving up", *block); + return; + } + tftp_log(LOG_ERR, + "Cannot send ACK packet #%d, trying again", + *block); + continue; + } + + break; + } + + if (fb_size != segsize) { + gettimeofday(&(ts->tstop), NULL); + return; + } + } + + rp = (struct tftphdr *)recvbuffer; + do { + oldblock = *block; + (*block)++; + if (oldblock > *block) { + if (options[OPT_ROLLOVER].o_request == NULL) { + tftp_log(LOG_ERR, + "Block rollover but not allowed."); + send_error(peer, EBADOP); + gettimeofday(&(ts->tstop), NULL); + return; + } + + *block = atoi(options[OPT_ROLLOVER].o_request); + ts->rollovers++; + } + + for (retry = 0; ; retry++) { + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_DEBUG, + "Receiving DATA block %d", *block); + + n_data = receive_packet(peer, recvbuffer, + MAXPKTSIZE, NULL, timeoutpacket); + if (n_data < 0) { + if (retry == maxtimeouts) { + tftp_log(LOG_ERR, + "Timeout #%d on DATA block %d, " + "giving up", retry, *block); + return; + } + if (n_data == RP_TIMEOUT) { + tftp_log(LOG_WARNING, + "Timeout #%d on DATA block %d", + retry, *block); + send_ack(peer, oldblock); + continue; + } + + /* Either read failure or ERROR packet */ + if (debug&DEBUG_SIMPLE) + tftp_log(LOG_DEBUG, "Aborting: %s", + rp_strerror(n_data)); + goto abort; + } + if (rp->th_opcode == DATA) { + ts->blocks++; + + if (rp->th_block == *block) + break; + + tftp_log(LOG_WARNING, + "Expected DATA block %d, got block %d", + *block, rp->th_block); + + /* Re-synchronize with the other side */ + (void) synchnet(peer); + if (rp->th_block == (*block-1)) { + tftp_log(LOG_INFO, "Trying to sync"); + *block = oldblock; + ts->retries++; + goto send_ack; /* rexmit */ + } + + } else { + tftp_log(LOG_WARNING, + "Expected DATA block, got %s block", + packettype(rp->th_opcode)); + } + } + + if (n_data > 0) { + writesize = write_file(rp->th_data, n_data); + ts->amount += writesize; + if (writesize <= 0) { + tftp_log(LOG_ERR, + "write_file returned %d", writesize); + if (writesize < 0) + send_error(peer, errno + 100); + else + send_error(peer, ENOSPACE); + goto abort; + } + } + +send_ack: + for (i = 0; ; i++) { + n_ack = send_ack(peer, *block); + if (n_ack > 0) { + + if (i == maxtimeouts) { + tftp_log(LOG_ERR, + "Cannot send ACK packet #%d, " + "giving up", *block); + return; + } + + tftp_log(LOG_ERR, + "Cannot send ACK packet #%d, trying again", + *block); + continue; + } + + break; + } + gettimeofday(&(ts->tstop), NULL); + } while (n_data == segsize); + + /* Don't do late packet management for the client implementation */ + if (acting_as_client) + return; + + for (i = 0; ; i++) { + n_data = receive_packet(peer, (char *)rp, pktsize, + NULL, timeoutpacket); + if (n_data <= 0) + break; + if (n_data > 0 && + rp->th_opcode == DATA && /* and got a data block */ + *block == rp->th_block) /* then my last ack was lost */ + send_ack(peer, *block); /* resend final ack */ + } + +abort: + return; +} diff --git a/libexec/tftpd/tftp-transfer.h b/libexec/tftpd/tftp-transfer.h new file mode 100644 index 0000000..2cfa2df --- /dev/null +++ b/libexec/tftpd/tftp-transfer.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +void tftp_send(int peer, uint16_t *block, struct tftp_stats *tp); +void tftp_receive(int peer, uint16_t *block, struct tftp_stats *tp, + struct tftphdr *firstblock, size_t fb_size); diff --git a/libexec/tftpd/tftp-utils.c b/libexec/tftpd/tftp-utils.c new file mode 100644 index 0000000..da58064 --- /dev/null +++ b/libexec/tftpd/tftp-utils.c @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "tftp-utils.h" +#include "tftp-io.h" + +/* + * Default values, can be changed later via the TFTP Options + */ +int timeoutpacket = TIMEOUT; +int timeoutnetwork = MAX_TIMEOUTS * TIMEOUT; +int maxtimeouts = MAX_TIMEOUTS; +uint16_t segsize = SEGSIZE; +uint16_t pktsize = SEGSIZE + 4; + +int acting_as_client; + + +/* + * Set timeout values for packet reception. The idea is that you + * get 'maxtimeouts' of 5 seconds between 'timeoutpacket' (i.e. the + * first timeout) to 'timeoutnetwork' (i.e. the last timeout) + */ +int +settimeouts(int _timeoutpacket, int _timeoutnetwork, int _maxtimeouts) +{ + int i; + + /* We cannot do impossible things */ + if (_timeoutpacket >= _timeoutnetwork) + return (0); + + maxtimeouts = 0; + i = _timeoutpacket; + while (i < _timeoutnetwork || maxtimeouts < MIN_TIMEOUTS) { + maxtimeouts++; + i += 5; + } + + timeoutpacket = _timeoutpacket; + timeoutnetwork = i; + return (1); +} + +/* translate IPv4 mapped IPv6 address to IPv4 address */ +void +unmappedaddr(struct sockaddr_in6 *sin6) +{ + struct sockaddr_in *sin4; + u_int32_t addr; + int port; + + if (sin6->sin6_family != AF_INET6 || + !IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) + return; + sin4 = (struct sockaddr_in *)sin6; + addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12]; + port = sin6->sin6_port; + memset(sin4, 0, sizeof(struct sockaddr_in)); + sin4->sin_addr.s_addr = addr; + sin4->sin_port = port; + sin4->sin_family = AF_INET; + sin4->sin_len = sizeof(struct sockaddr_in); +} + +/* Get a field from a \0 seperated string */ +ssize_t +get_field(int peer, char *buffer, ssize_t size) +{ + char *cp = buffer; + + while (cp < buffer + size) { + if (*cp == '\0') break; + cp++; + } + if (*cp != '\0') { + tftp_log(LOG_ERR, "Bad option - no trailing \\0 found"); + send_error(peer, EBADOP); + exit(1); + } + return (cp - buffer + 1); +} + +/* + * Logging functions + */ +int _tftp_logtostdout = 1; + +void +tftp_openlog(const char *ident, int logopt, int facility) +{ + + _tftp_logtostdout = (ident == NULL); + if (_tftp_logtostdout == 0) + openlog(ident, logopt, facility); +} + +void +tftp_closelog(void) +{ + + if (_tftp_logtostdout == 0) + closelog(); +} + +void +tftp_log(int priority, const char *message, ...) +{ + va_list ap; + char *s; + + va_start(ap, message); + if (_tftp_logtostdout == 0) { + vasprintf(&s, message, ap); + syslog(priority, "%s", s); + } else { + vprintf(message, ap); + printf("\n"); + } + va_end(ap); +} + +/* + * Packet types + */ +struct packettypes packettypes[] = { + { RRQ, "RRQ" }, + { WRQ, "WRQ" }, + { DATA, "DATA" }, + { ACK, "ACK" }, + { ERROR, "ERROR" }, + { OACK, "OACK" }, + { 0, NULL }, +}; + +char * +packettype(int type) +{ + static char failed[100]; + int i = 0; + + while (packettypes[i].name != NULL) { + if (packettypes[i].value == type) + break; + i++; + } + if (packettypes[i].name != NULL) + return packettypes[i].name; + sprintf(failed, "unknown (type: %d)", type); + return (failed); +} + +/* + * Debugs + */ +int debug = DEBUG_NONE; +struct debugs debugs[] = { + { DEBUG_PACKETS, "packet", "Packet debugging" }, + { DEBUG_SIMPLE, "simple", "Simple debugging" }, + { DEBUG_OPTIONS, "options", "Options debugging" }, + { DEBUG_ACCESS, "access", "TCPd access debugging" }, + { DEBUG_NONE, NULL, "No debugging" }, +}; +int packetdroppercentage = 0; + +int +debug_find(char *s) +{ + int i = 0; + + while (debugs[i].name != NULL) { + if (strcasecmp(debugs[i].name, s) == 0) + break; + i++; + } + return (debugs[i].value); +} + +int +debug_finds(char *s) +{ + int i = 0; + char *ps = s; + + while (s != NULL) { + ps = strchr(s, ' '); + if (ps != NULL) + *ps = '\0'; + i += debug_find(s); + if (ps != NULL) + *ps = ' '; + s = ps; + } + return (i); +} + +char * +debug_show(int d) +{ + static char s[100]; + int i = 0; + + s[0] = '\0'; + while (debugs[i].name != NULL) { + if (d&debugs[i].value) { + if (s[0] != '\0') + strcat(s, " "); + strcat(s, debugs[i].name); + } + i++; + } + if (s[0] != '\0') + return (s); + return ("none"); +} + +/* + * RP_ + */ +struct rp_errors rp_errors[] = { + { RP_TIMEOUT, "Network timeout" }, + { RP_TOOSMALL, "Not enough data bytes" }, + { RP_WRONGSOURCE, "Invalid IP address of UDP port" }, + { RP_ERROR, "Error packet" }, + { RP_RECVFROM, "recvfrom() complained" }, + { RP_TOOBIG, "Too many data bytes" }, + { RP_NONE, NULL } +}; + +char * +rp_strerror(int error) +{ + static char s[100]; + int i = 0; + + while (rp_errors[i].desc != NULL) { + if (rp_errors[i].error == error) { + strcpy(s, rp_errors[i].desc); + } + i++; + } + if (s[0] == '\0') + sprintf(s, "unknown (error=%d)", error); + return (s); +} + +/* + * Performance figures + */ + +void +stats_init(struct tftp_stats *ts) +{ + + ts->amount = 0; + ts->rollovers = 0; + ts->retries = 0; + ts->blocks = 0; + ts->amount = 0; + gettimeofday(&(ts->tstart), NULL); +} + +void +printstats(const char *direction, int verbose, struct tftp_stats *ts) +{ + double delta; /* compute delta in 1/10's second units */ + + delta = ((ts->tstop.tv_sec*10.)+(ts->tstop.tv_usec/100000)) - + ((ts->tstart.tv_sec*10.)+(ts->tstart.tv_usec/100000)); + delta = delta/10.; /* back to seconds */ + + printf("%s %zu bytes during %.1f seconds in %u blocks", + direction, ts->amount, delta, ts->blocks); + + if (ts->rollovers != 0) + printf(" with %d rollover%s", + ts->rollovers, ts->rollovers != 1 ? "s" : ""); + + if (verbose) + printf(" [%.0f bits/sec]", (ts->amount*8.)/delta); + putchar('\n'); +} + diff --git a/libexec/tftpd/tftp-utils.h b/libexec/tftpd/tftp-utils.h new file mode 100644 index 0000000..d072479 --- /dev/null +++ b/libexec/tftpd/tftp-utils.h @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2008 Edwin Groothuis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + */ +#define TIMEOUT 5 +#define MAX_TIMEOUTS 5 + +/* Generic values */ +#define MAXSEGSIZE 65464 /* Maximum size of the data segment */ +#define MAXPKTSIZE (MAXSEGSIZE + 4) /* Maximum size of the packet */ + +/* For the blksize option */ +#define BLKSIZE_MIN 8 /* Minumum size of the data segment */ +#define BLKSIZE_MAX MAXSEGSIZE /* Maximum size of the data segment */ + +/* For the timeout option */ +#define TIMEOUT_MIN 0 /* Minumum timeout value */ +#define TIMEOUT_MAX 255 /* Maximum timeout value */ +#define MIN_TIMEOUTS 3 + +extern int timeoutpacket; +extern int timeoutnetwork; +extern int maxtimeouts; +int settimeouts(int timeoutpacket, int timeoutnetwork, int maxtimeouts); + +extern uint16_t segsize; +extern uint16_t pktsize; + +extern int acting_as_client; + +/* + */ +void unmappedaddr(struct sockaddr_in6 *sin6); +ssize_t get_field(int peer, char *buffer, ssize_t size); + +/* + * Packet types + */ +struct packettypes { + int value; + char *name; +}; +extern struct packettypes packettypes[]; +char *packettype(int); + +/* + * RP_ + */ +struct rp_errors { + int error; + char *desc; +}; +extern struct rp_errors rp_errors[]; +char *rp_strerror(int error); + +/* + * Debug features + */ +#define DEBUG_NONE 0x0000 +#define DEBUG_PACKETS 0x0001 +#define DEBUG_SIMPLE 0x0002 +#define DEBUG_OPTIONS 0x0004 +#define DEBUG_ACCESS 0x0008 +struct debugs { + int value; + char *name; + char *desc; +}; +extern int debug; +extern struct debugs debugs[]; +extern int packetdroppercentage; +int debug_find(char *s); +int debug_finds(char *s); +char *debug_show(int d); + +/* + * Log routines + */ +#define DEBUG(s) tftp_log(LOG_DEBUG, "%s", s) +extern int tftp_logtostdout; +void tftp_openlog(const char *ident, int logopt, int facility); +void tftp_closelog(void); +void tftp_log(int priority, const char *message, ...); + +/* + * Performance figures + */ +struct tftp_stats { + size_t amount; + int rollovers; + uint32_t blocks; + int retries; + struct timeval tstart; + struct timeval tstop; +}; + +void stats_init(struct tftp_stats *ts); +void printstats(const char *direction, int verbose, struct tftp_stats *ts); -- cgit v1.1 From fbfe456f9697050cf749467e9b47e3aad49f09bb Mon Sep 17 00:00:00 2001 From: csjp Date: Tue, 4 May 2010 15:29:07 +0000 Subject: Add a case to make sure that internal audit records get converted to BSM format for lpathconf(2) events. MFC after: 2 weeks --- sys/security/audit/audit_bsm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c index faa4583..b4713cc 100644 --- a/sys/security/audit/audit_bsm.c +++ b/sys/security/audit/audit_bsm.c @@ -740,6 +740,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau) case AUE_LUTIMES: case AUE_NFS_GETFH: case AUE_LSTAT: + case AUE_LPATHCONF: case AUE_PATHCONF: case AUE_READLINK: case AUE_REVOKE: -- cgit v1.1 From c9aaa1e2a21afcea58a3bec5e8cffd6652fbaa25 Mon Sep 17 00:00:00 2001 From: alc Date: Tue, 4 May 2010 15:55:41 +0000 Subject: Add page locking to the vm_page_cow* functions. Push down the acquisition and release of the page queues lock into vm_page_wire(). Reviewed by: kib --- sys/dev/drm/via_dmablit.c | 2 -- sys/kern/uipc_cow.c | 3 --- sys/kern/vfs_bio.c | 2 -- sys/net/bpf_zerocopy.c | 2 -- sys/vm/vm_fault.c | 6 ------ sys/vm/vm_page.c | 20 +++++++++++++------- 6 files changed, 13 insertions(+), 22 deletions(-) diff --git a/sys/dev/drm/via_dmablit.c b/sys/dev/drm/via_dmablit.c index 72d914e..81d438a 100644 --- a/sys/dev/drm/via_dmablit.c +++ b/sys/dev/drm/via_dmablit.c @@ -251,10 +251,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) if (m == NULL) break; vm_page_lock(m); - vm_page_lock_queues(); vm_page_wire(m); vm_page_unhold(m); - vm_page_unlock_queues(); vm_page_unlock(m); vsg->pages[i] = m; } diff --git a/sys/kern/uipc_cow.c b/sys/kern/uipc_cow.c index 88a5625..bc9a56a 100644 --- a/sys/kern/uipc_cow.c +++ b/sys/kern/uipc_cow.c @@ -131,10 +131,8 @@ socow_setup(struct mbuf *m0, struct uio *uio) * set up COW */ vm_page_lock(pp); - vm_page_lock_queues(); if (vm_page_cowsetup(pp) != 0) { vm_page_unhold(pp); - vm_page_unlock_queues(); vm_page_unlock(pp); return (0); } @@ -144,7 +142,6 @@ socow_setup(struct mbuf *m0, struct uio *uio) */ vm_page_wire(pp); vm_page_unhold(pp); - vm_page_unlock_queues(); vm_page_unlock(pp); /* * Allocate an sf buf diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 5db2d9e..589bdbd 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -3043,9 +3043,7 @@ allocbuf(struct buf *bp, int size) * We have a good page. */ vm_page_lock(m); - vm_page_lock_queues(); vm_page_wire(m); - vm_page_unlock_queues(); vm_page_unlock(m); bp->b_pages[bp->b_npages] = m; ++bp->b_npages; diff --git a/sys/net/bpf_zerocopy.c b/sys/net/bpf_zerocopy.c index 5ca6978..5629093 100644 --- a/sys/net/bpf_zerocopy.c +++ b/sys/net/bpf_zerocopy.c @@ -171,10 +171,8 @@ zbuf_sfbuf_get(struct vm_map *map, vm_offset_t uaddr) if (pp == NULL) return (NULL); vm_page_lock(pp); - vm_page_lock_queues(); vm_page_wire(pp); vm_page_unhold(pp); - vm_page_unlock_queues(); vm_page_unlock(pp); sf = sf_buf_alloc(pp, SFB_NOWAIT); if (sf == NULL) { diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index f925594..142a9ef 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -315,8 +315,6 @@ RetryFault:; (fault_type & VM_PROT_WRITE) && (fs.object == fs.first_object)) { vm_page_cowfault(fs.m); - vm_page_unlock_queues(); - vm_page_unlock(fs.m); unlock_and_deallocate(&fs); goto RetryFault; } @@ -797,9 +795,7 @@ vnode_locked: if (wired && (fault_flags & VM_FAULT_CHANGE_WIRING) == 0) { vm_page_lock(fs.first_m); - vm_page_lock_queues(); vm_page_wire(fs.first_m); - vm_page_unlock_queues(); vm_page_unlock(fs.first_m); vm_page_lock(fs.m); @@ -1285,9 +1281,7 @@ vm_fault_copy_entry(vm_map_t dst_map, vm_map_t src_map, vm_page_unlock(src_m); vm_page_lock(dst_m); - vm_page_lock_queues(); vm_page_wire(dst_m); - vm_page_unlock_queues(); vm_page_unlock(dst_m); } else { vm_page_lock(dst_m); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index d9288d9..957bf82 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1544,13 +1544,15 @@ vm_page_wire(vm_page_t m) * and only unqueue the page if it is on some queue (if it is unmanaged * it is already off the queues). */ - mtx_assert(&vm_page_queue_mtx, MA_OWNED); vm_page_lock_assert(m, MA_OWNED); if (m->flags & PG_FICTITIOUS) return; if (m->wire_count == 0) { - if ((m->flags & PG_UNMANAGED) == 0) + if ((m->flags & PG_UNMANAGED) == 0) { + vm_page_lock_queues(); vm_pageq_remove(m); + vm_page_unlock_queues(); + } atomic_add_int(&cnt.v_wire_count, 1); } m->wire_count++; @@ -1922,9 +1924,7 @@ retrylookup: } else { if ((allocflags & VM_ALLOC_WIRED) != 0) { vm_page_lock(m); - vm_page_lock_queues(); vm_page_wire(m); - vm_page_unlock_queues(); vm_page_unlock(m); } if ((allocflags & VM_ALLOC_NOBUSY) == 0) @@ -2224,6 +2224,7 @@ vm_page_cowfault(vm_page_t m) vm_object_t object; vm_pindex_t pindex; + vm_page_lock_assert(m, MA_OWNED); object = m->object; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); KASSERT(object->paging_in_progress != 0, @@ -2238,17 +2239,18 @@ vm_page_cowfault(vm_page_t m) if (mnew == NULL) { vm_page_insert(m, object, pindex); vm_page_unlock_queues(); + vm_page_unlock(m); VM_OBJECT_UNLOCK(object); VM_WAIT; VM_OBJECT_LOCK(object); if (m == vm_page_lookup(object, pindex)) { + vm_page_lock(m); vm_page_lock_queues(); goto retry_alloc; } else { /* * Page disappeared during the wait. */ - vm_page_lock_queues(); return; } } @@ -2269,13 +2271,15 @@ vm_page_cowfault(vm_page_t m) mnew->wire_count = m->wire_count - m->cow; m->wire_count = m->cow; } + vm_page_unlock_queues(); + vm_page_unlock(m); } void vm_page_cowclear(vm_page_t m) { - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); if (m->cow) { m->cow--; /* @@ -2291,11 +2295,13 @@ int vm_page_cowsetup(vm_page_t m) { - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); if (m->cow == USHRT_MAX - 1) return (EBUSY); m->cow++; + vm_page_lock_queues(); pmap_remove_write(m); + vm_page_unlock_queues(); return (0); } -- cgit v1.1 From c0e2f5f6a173f33b55cc1240eb50b7afe9f617b8 Mon Sep 17 00:00:00 2001 From: jkim Date: Tue, 4 May 2010 16:56:59 +0000 Subject: - Remove more dead code[1]. Since r207330, we only need to check division by zero of the second argument 'from'. - Prefer u_int32_t over unsigned int to make its intention more clearer. - Move the function to a header file and make it a static inline function. Pointed out by: Andrew Reilly (areilly at bigpond dot net dot au)[1] MFC after: 3 days --- sys/dev/sound/pcm/buffer.c | 13 ------------- sys/dev/sound/pcm/buffer.h | 12 +++++++++++- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c index a9053d7..687542e 100644 --- a/sys/dev/sound/pcm/buffer.c +++ b/sys/dev/sound/pcm/buffer.c @@ -566,19 +566,6 @@ sndbuf_updateprevtotal(struct snd_dbuf *b) } unsigned int -snd_xbytes(unsigned int v, unsigned int from, unsigned int to) -{ - - if (from == to) - return v; - - if (from == 0 || to == 0 || v == 0) - return 0; - - return (unsigned int)(((u_int64_t)v * to) / from); -} - -unsigned int sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to) { if (from == NULL || to == NULL || v == 0) diff --git a/sys/dev/sound/pcm/buffer.h b/sys/dev/sound/pcm/buffer.h index 91a63af..d079cdb 100644 --- a/sys/dev/sound/pcm/buffer.h +++ b/sys/dev/sound/pcm/buffer.h @@ -111,7 +111,6 @@ u_int64_t sndbuf_getblocks(struct snd_dbuf *b); u_int64_t sndbuf_getprevblocks(struct snd_dbuf *b); u_int64_t sndbuf_gettotal(struct snd_dbuf *b); u_int64_t sndbuf_getprevtotal(struct snd_dbuf *b); -unsigned int snd_xbytes(unsigned int v, unsigned int from, unsigned int to); unsigned int sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to); u_int8_t sndbuf_zerodata(u_int32_t fmt); void sndbuf_updateprevtotal(struct snd_dbuf *b); @@ -132,3 +131,14 @@ void sndbuf_dmabounce(struct snd_dbuf *b); #ifdef OSSV4_EXPERIMENT void sndbuf_getpeaks(struct snd_dbuf *b, int *lp, int *rp); #endif + +static inline u_int32_t +snd_xbytes(u_int32_t v, u_int32_t from, u_int32_t to) +{ + + if (from == to) + return (v); + if (from == 0) + return (0); + return ((u_int64_t)v * to / from); +} -- cgit v1.1 From 3f06f24240ae799188fea0c4e72ae871c5527597 Mon Sep 17 00:00:00 2001 From: imp Date: Tue, 4 May 2010 17:00:18 +0000 Subject: Doh! Add another new file forgotten by the importer of edwin@'s tftp improvements. MFC after: 1 week Pointy Hat: imp-o-rama... --- usr.bin/tftp/tftp.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 usr.bin/tftp/tftp.h diff --git a/usr.bin/tftp/tftp.h b/usr.bin/tftp/tftp.h new file mode 100644 index 0000000..5928dea --- /dev/null +++ b/usr.bin/tftp/tftp.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/6/93 + * $FreeBSD$ + */ + +void recvfile(int peer, char *port, int fd, char *name, char *mode); +void xmitfile(int peer, char *port, int fd, char *name, char *mode); + +extern int verbose; +extern int maxtimeout; +extern volatile int txrx_error; -- cgit v1.1 From 9c1accad5ee5f0c2a36c06f921ac77ec31cd246a Mon Sep 17 00:00:00 2001 From: yongari Date: Tue, 4 May 2010 17:02:34 +0000 Subject: Drop driver lock before exiting from interrupt handler. Submitted by: jhb MFC after: 3 days --- sys/dev/msk/if_msk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c index e15ccfe..1c871a8 100644 --- a/sys/dev/msk/if_msk.c +++ b/sys/dev/msk/if_msk.c @@ -3594,6 +3594,7 @@ msk_intr(void *xsc) (sc->msk_pflags & MSK_FLAG_SUSPEND) != 0 || (status & sc->msk_intrmask) == 0) { CSR_WRITE_4(sc, B0_Y2_SP_ICR, 2); + MSK_UNLOCK(sc); return; } -- cgit v1.1 From 44093d908838f41371b4160ac664abdab7dd5f97 Mon Sep 17 00:00:00 2001 From: yongari Date: Tue, 4 May 2010 17:12:36 +0000 Subject: Make sure to check whether driver is running before processing received frames. Also check driver has valid ifp pointer before calling msk_stop() in device_shutdown handler. While I'm here remove unnecessary accesses to interrupt mask registers in device_shutdown handler because driver puts the controller into reset state. With these changes, msk(4) now survive from heavy RX traffic(1byte UDP frame) while reboot is in progress. Reported by: Mark Atkinson < atkin901 <> gmail dot com > --- sys/dev/msk/if_msk.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c index 1c871a8..af977bf 100644 --- a/sys/dev/msk/if_msk.c +++ b/sys/dev/msk/if_msk.c @@ -2904,20 +2904,15 @@ mskc_shutdown(device_t dev) sc = device_get_softc(dev); MSK_LOCK(sc); for (i = 0; i < sc->msk_num_port; i++) { - if (sc->msk_if[i] != NULL) + if (sc->msk_if[i] != NULL && sc->msk_if[i]->msk_ifp != NULL && + ((sc->msk_if[i]->msk_ifp->if_drv_flags & + IFF_DRV_RUNNING) != 0)) msk_stop(sc->msk_if[i]); } - - /* Disable all interrupts. */ - CSR_WRITE_4(sc, B0_IMSK, 0); - CSR_READ_4(sc, B0_IMSK); - CSR_WRITE_4(sc, B0_HWE_IMSK, 0); - CSR_READ_4(sc, B0_HWE_IMSK); + MSK_UNLOCK(sc); /* Put hardware reset. */ CSR_WRITE_2(sc, B0_CTST, CS_RST_SET); - - MSK_UNLOCK(sc); return (0); } @@ -3525,6 +3520,8 @@ msk_handle_events(struct msk_softc *sc) sc_if->msk_csum = status; break; case OP_RXSTAT: + if (!(sc_if->msk_ifp->if_drv_flags & IFF_DRV_RUNNING)) + break; if (sc_if->msk_framesize > (MCLBYTES - MSK_RX_BUF_ALIGN)) msk_jumbo_rxeof(sc_if, status, control, len); -- cgit v1.1 From a0d55d935c4651b24a66107dc58763618df5172a Mon Sep 17 00:00:00 2001 From: mm Date: Tue, 4 May 2010 17:30:07 +0000 Subject: Fix deadlock during zfs receive. OpenSolaris onnv revision: 9299:8809e849f63e PR: kern/146296 Submitted by: myself Approved by: pjd, delphij (mentor) Obtained from: OpenSolaris (Bug ID 6783818, 6826836) MFC after: 1 week --- .../contrib/opensolaris/uts/common/fs/zfs/dbuf.c | 6 ++--- .../opensolaris/uts/common/fs/zfs/dmu_object.c | 28 ++++++++++++---------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c index 3bf0939..053c1e1 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c @@ -464,15 +464,15 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) ASSERT(db->db_buf == NULL); if (db->db_blkid == DB_BONUS_BLKID) { - int bonuslen = dn->dn_bonuslen; + int bonuslen = MIN(dn->dn_bonuslen, dn->dn_phys->dn_bonuslen); ASSERT3U(bonuslen, <=, db->db.db_size); db->db.db_data = zio_buf_alloc(DN_MAX_BONUSLEN); arc_space_consume(DN_MAX_BONUSLEN); if (bonuslen < DN_MAX_BONUSLEN) bzero(db->db.db_data, DN_MAX_BONUSLEN); - bcopy(DN_BONUS(dn->dn_phys), db->db.db_data, - bonuslen); + if (bonuslen) + bcopy(DN_BONUS(dn->dn_phys), db->db.db_data, bonuslen); dbuf_update_data(db); db->db_state = DB_CACHED; mutex_exit(&db->db_mtx); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c index 25dfafd..1f91fc1 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c @@ -128,15 +128,6 @@ dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot, return (0); } - tx = dmu_tx_create(os); - dmu_tx_hold_bonus(tx, object); - err = dmu_tx_assign(tx, TXG_WAIT); - if (err) { - dmu_tx_abort(tx); - dnode_rele(dn, FTAG); - return (err); - } - nblkptr = 1 + ((DN_MAX_BONUSLEN - bonuslen) >> SPA_BLKPTRSHIFT); /* @@ -144,16 +135,27 @@ dmu_object_reclaim(objset_t *os, uint64_t object, dmu_object_type_t ot, * be a new file instance. We must clear out the previous file * contents before we can change this type of metadata in the dnode. */ - if (dn->dn_nblkptr > nblkptr || dn->dn_datablksz != blocksize) - dmu_free_long_range(os, object, 0, DMU_OBJECT_END); + if (dn->dn_nblkptr > nblkptr || dn->dn_datablksz != blocksize) { + err = dmu_free_long_range(os, object, 0, DMU_OBJECT_END); + if (err) + goto out; + } + + tx = dmu_tx_create(os); + dmu_tx_hold_bonus(tx, object); + err = dmu_tx_assign(tx, TXG_WAIT); + if (err) { + dmu_tx_abort(tx); + goto out; + } dnode_reallocate(dn, ot, blocksize, bonustype, bonuslen, tx); dmu_tx_commit(tx); - +out: dnode_rele(dn, FTAG); - return (0); + return (err); } int -- cgit v1.1 From 551564c95b96239d355e9b3bd713d815204ace7a Mon Sep 17 00:00:00 2001 From: yongari Date: Tue, 4 May 2010 17:34:00 +0000 Subject: Remove clearing RxHashTable2 register. The register is reprogrammed in sge_rxfilter(). --- sys/dev/sge/if_sge.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index 43b7022..753c6de 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -1577,7 +1577,6 @@ sge_init_locked(struct sge_softc *sc) CSR_WRITE_4(sc, RX_DESC, SGE_ADDR_LO(sc->sge_ldata.sge_rx_paddr)); CSR_WRITE_4(sc, TxMacControl, 0x60); - CSR_WRITE_4(sc, 0x6c, 0); CSR_WRITE_4(sc, RxWakeOnLan, 0); CSR_WRITE_4(sc, RxWakeOnLanData, 0); /* Allow receiving VLAN frames. */ -- cgit v1.1 From 6dc3ed99a0862fafbe76f87b5b84a42d0a23f622 Mon Sep 17 00:00:00 2001 From: mm Date: Tue, 4 May 2010 17:40:24 +0000 Subject: Speed up ZFS list operation with objset prefetching. Partial import of OpenSolaris onnv revisions: 8415:8809e849f63e, 10474:0e96dd3b905a PR: kern/146297 Submitted by: myself Approved by: pjd, delphij (mentor) Obtained from: OpenSolaris (Bug ID 6386929, 6755389, 6847118) MFC after: 2 weeks --- .../opensolaris/uts/common/fs/zfs/dmu_objset.c | 33 ++++++++++++++++++++++ .../opensolaris/uts/common/fs/zfs/sys/dmu_objset.h | 3 +- .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 11 ++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c index 7981e06..c9e00d5 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c @@ -1213,6 +1213,39 @@ dmu_objset_find_spa(spa_t *spa, const char *name, return (err); } +/* ARGSUSED */ +int +dmu_objset_prefetch(char *name, void *arg) +{ + dsl_dataset_t *ds; + + if (dsl_dataset_hold(name, FTAG, &ds)) + return (0); + + if (!BP_IS_HOLE(&ds->ds_phys->ds_bp)) { + mutex_enter(&ds->ds_opening_lock); + if (!dsl_dataset_get_user_ptr(ds)) { + uint32_t aflags = ARC_NOWAIT | ARC_PREFETCH; + zbookmark_t zb; + + zb.zb_objset = ds->ds_object; + zb.zb_object = 0; + zb.zb_level = -1; + zb.zb_blkid = 0; + + (void) arc_read_nolock(NULL, dsl_dataset_get_spa(ds), + &ds->ds_phys->ds_bp, NULL, NULL, + ZIO_PRIORITY_ASYNC_READ, + ZIO_FLAG_CANFAIL | ZIO_FLAG_SPECULATIVE, + &aflags, &zb); + } + mutex_exit(&ds->ds_opening_lock); + } + + dsl_dataset_rele(ds, FTAG); + return (0); +} + void dmu_objset_set_user(objset_t *os, void *user_ptr) { diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h index 15df29a..1d65727 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu_objset.h @@ -26,8 +26,6 @@ #ifndef _SYS_DMU_OBJSET_H #define _SYS_DMU_OBJSET_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include #include @@ -118,6 +116,7 @@ int dmu_objset_find(char *name, int func(char *, void *), void *arg, int flags); int dmu_objset_find_spa(spa_t *spa, const char *name, int func(spa_t *, uint64_t, const char *, void *), void *arg, int flags); +int dmu_objset_prefetch(char *name, void *arg); void dmu_objset_byteswap(void *buf, size_t size); int dmu_objset_evict_dbufs(objset_t *os); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 00e446b..1536e0b 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -1349,6 +1349,14 @@ zfs_ioc_dataset_list_next(zfs_cmd_t *zc) (void) strlcat(zc->zc_name, "/", sizeof (zc->zc_name)); p = zc->zc_name + strlen(zc->zc_name); + if (zc->zc_cookie == 0) { + uint64_t cookie = 0; + int len = sizeof (zc->zc_name) - (p - zc->zc_name); + + while (dmu_dir_list_next(os, len, p, NULL, &cookie) == 0) + dmu_objset_prefetch(p, NULL); + } + do { error = dmu_dir_list_next(os, sizeof (zc->zc_name) - (p - zc->zc_name), p, @@ -1387,6 +1395,9 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc) objset_t *os; int error; + if (zc->zc_cookie == 0) + dmu_objset_find(zc->zc_name, dmu_objset_prefetch, + NULL, DS_FIND_SNAPSHOTS); error = dmu_objset_open(zc->zc_name, DMU_OST_ANY, DS_MODE_USER | DS_MODE_READONLY, &os); if (error) -- cgit v1.1 From 0722e342299d977bdcb7da373b668bdb3da0022d Mon Sep 17 00:00:00 2001 From: mm Date: Tue, 4 May 2010 17:44:40 +0000 Subject: Enable "zfs list" to list explicitly requested snapshots. Partial import of OpenSolaris onnv revision: 8415:8809e849f63e PR: kern/146297 Submitted by: myself Approved by: pjd, delphij (mentor) Obtained from: OpenSolaris (Bug ID 6758338) MFC after: 2 weeks --- cddl/contrib/opensolaris/cmd/zfs/zfs_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c index 79428f7..a9d3c01 100644 --- a/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c +++ b/cddl/contrib/opensolaris/cmd/zfs/zfs_main.c @@ -1790,7 +1790,7 @@ zfs_do_list(int argc, char **argv) boolean_t scripted = B_FALSE; static char default_fields[] = "name,used,available,referenced,mountpoint"; - int types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME; + int types = ZFS_TYPE_DATASET; boolean_t types_specified = B_FALSE; char *fields = NULL; list_cbdata_t cb = { 0 }; -- cgit v1.1 From f6cb7b4ffbe9d4afd5ed91935c2bc1906549eb57 Mon Sep 17 00:00:00 2001 From: yongari Date: Tue, 4 May 2010 19:04:51 +0000 Subject: Enable multi-descriptor transmisstion for fragmented mbufs. There is no more need to defragment mbufs. After transmitting the multi-fragmented frame, the controller updates only the first descriptor of multi-descriptor transmission so it's driver's responsibility to clear OWN bits of remaining descriptor of multi-descriptor transmission. It seems the controller behaves much like jme(4) controllers in descriptor handling. Tested by: xclin cs dot nctu dot edu dot tw > --- sys/dev/sge/if_sge.c | 232 ++++++++++++++++++++++++++++-------------------- sys/dev/sge/if_sgereg.h | 19 ++-- 2 files changed, 148 insertions(+), 103 deletions(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index 753c6de..c384983 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -756,6 +756,8 @@ sge_dma_alloc(struct sge_softc *sc) { struct sge_chain_data *cd; struct sge_list_data *ld; + struct sge_rxdesc *rxd; + struct sge_txdesc *txd; int error, i; cd = &sc->sge_cdata; @@ -869,8 +871,12 @@ sge_dma_alloc(struct sge_softc *sc) /* Create DMA maps for Tx buffers. */ for (i = 0; i < SGE_TX_RING_CNT; i++) { + txd = &cd->sge_txdesc[i]; + txd->tx_m = NULL; + txd->tx_dmamap = NULL; + txd->tx_ndesc = 0; error = bus_dmamap_create(cd->sge_txmbuf_tag, 0, - &cd->sge_tx_map[i]); + &txd->tx_dmamap); if (error != 0) { device_printf(sc->sge_dev, "could not create Tx DMA map.\n"); @@ -886,8 +892,11 @@ sge_dma_alloc(struct sge_softc *sc) } /* Create DMA maps for Rx buffers. */ for (i = 0; i < SGE_RX_RING_CNT; i++) { + rxd = &cd->sge_rxdesc[i]; + rxd->rx_m = NULL; + rxd->rx_dmamap = NULL; error = bus_dmamap_create(cd->sge_rxmbuf_tag, 0, - &cd->sge_rx_map[i]); + &rxd->rx_dmamap); if (error) { device_printf(sc->sge_dev, "could not create Rx DMA map.\n"); @@ -903,6 +912,8 @@ sge_dma_free(struct sge_softc *sc) { struct sge_chain_data *cd; struct sge_list_data *ld; + struct sge_rxdesc *rxd; + struct sge_txdesc *txd; int i; cd = &sc->sge_cdata; @@ -934,10 +945,11 @@ sge_dma_free(struct sge_softc *sc) /* Rx buffers. */ if (cd->sge_rxmbuf_tag != NULL) { for (i = 0; i < SGE_RX_RING_CNT; i++) { - if (cd->sge_rx_map[i] != NULL) { + rxd = &cd->sge_rxdesc[i]; + if (rxd->rx_dmamap != NULL) { bus_dmamap_destroy(cd->sge_rxmbuf_tag, - cd->sge_rx_map[i]); - cd->sge_rx_map[i] = NULL; + rxd->rx_dmamap); + rxd->rx_dmamap = NULL; } } if (cd->sge_rx_spare_map != NULL) { @@ -951,10 +963,11 @@ sge_dma_free(struct sge_softc *sc) /* Tx buffers. */ if (cd->sge_txmbuf_tag != NULL) { for (i = 0; i < SGE_TX_RING_CNT; i++) { - if (cd->sge_tx_map[i] != NULL) { + txd = &cd->sge_txdesc[i]; + if (txd->tx_dmamap != NULL) { bus_dmamap_destroy(cd->sge_txmbuf_tag, - cd->sge_tx_map[i]); - cd->sge_tx_map[i] = NULL; + txd->tx_dmamap); + txd->tx_dmamap = NULL; } } bus_dma_tag_destroy(cd->sge_txmbuf_tag); @@ -991,18 +1004,20 @@ static int sge_list_tx_free(struct sge_softc *sc) { struct sge_chain_data *cd; + struct sge_txdesc *txd; int i; SGE_LOCK_ASSERT(sc); cd = &sc->sge_cdata; for (i = 0; i < SGE_TX_RING_CNT; i++) { - if (cd->sge_tx_mbuf[i] != NULL) { - bus_dmamap_sync(cd->sge_txmbuf_tag, - cd->sge_tx_map[i], BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(cd->sge_txmbuf_tag, - cd->sge_tx_map[i]); - m_free(cd->sge_tx_mbuf[i]); - cd->sge_tx_mbuf[i] = NULL; + txd = &cd->sge_txdesc[i]; + if (txd->tx_m != NULL) { + bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); + m_free(txd->tx_m); + txd->tx_m = NULL; + txd->tx_ndesc = 0; } } @@ -1037,18 +1052,20 @@ static int sge_list_rx_free(struct sge_softc *sc) { struct sge_chain_data *cd; + struct sge_rxdesc *rxd; int i; SGE_LOCK_ASSERT(sc); cd = &sc->sge_cdata; for (i = 0; i < SGE_RX_RING_CNT; i++) { - if (cd->sge_rx_mbuf[i] != NULL) { - bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[i], + rxd = &cd->sge_rxdesc[i]; + if (rxd->rx_m != NULL) { + bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(cd->sge_rxmbuf_tag, - cd->sge_rx_map[i]); - m_free(cd->sge_rx_mbuf[i]); - cd->sge_rx_mbuf[i] = NULL; + rxd->rx_dmamap); + m_free(rxd->rx_m); + rxd->rx_m = NULL; } } return (0); @@ -1063,6 +1080,7 @@ sge_newbuf(struct sge_softc *sc, int prod) struct mbuf *m; struct sge_desc *desc; struct sge_chain_data *cd; + struct sge_rxdesc *rxd; bus_dma_segment_t segs[1]; bus_dmamap_t map; int error, nsegs; @@ -1082,17 +1100,18 @@ sge_newbuf(struct sge_softc *sc, int prod) return (error); } KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); - if (cd->sge_rx_mbuf[prod] != NULL) { - bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod], + rxd = &cd->sge_rxdesc[prod]; + if (rxd->rx_m != NULL) { + bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod]); + bus_dmamap_unload(cd->sge_rxmbuf_tag, rxd->rx_dmamap); } - map = cd->sge_rx_map[prod]; - cd->sge_rx_map[prod] = cd->sge_rx_spare_map; + map = rxd->rx_dmamap; + rxd->rx_dmamap = cd->sge_rx_spare_map; cd->sge_rx_spare_map = map; - bus_dmamap_sync(cd->sge_rxmbuf_tag, cd->sge_rx_map[prod], + bus_dmamap_sync(cd->sge_rxmbuf_tag, rxd->rx_dmamap, BUS_DMASYNC_PREREAD); - cd->sge_rx_mbuf[prod] = m; + rxd->rx_m = m; desc = &sc->sge_ldata.sge_rx_ring[prod]; desc->sge_sts_size = 0; @@ -1178,7 +1197,7 @@ sge_rxeof(struct sge_softc *sc) ifp->if_ierrors++; continue; } - m = cd->sge_rx_mbuf[cons]; + m = cd->sge_rxdesc[cons].rx_m; if (sge_newbuf(sc, cons) != 0) { sge_discard_rxbuf(sc, cons); ifp->if_iqdrops++; @@ -1245,8 +1264,9 @@ sge_txeof(struct sge_softc *sc) struct ifnet *ifp; struct sge_list_data *ld; struct sge_chain_data *cd; + struct sge_txdesc *txd; uint32_t txstat; - int cons, prod; + int cons, nsegs, prod; SGE_LOCK_ASSERT(sc); @@ -1260,33 +1280,47 @@ sge_txeof(struct sge_softc *sc) BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); cons = cd->sge_tx_cons; prod = cd->sge_tx_prod; - for (; cons != prod; SGE_INC(cons, SGE_TX_RING_CNT)) { + for (; cons != prod;) { txstat = le32toh(ld->sge_tx_ring[cons].sge_cmdsts); if ((txstat & TDC_OWN) != 0) break; - cd->sge_tx_cnt--; - ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - if (cd->sge_tx_mbuf[cons] != NULL) { - bus_dmamap_sync(cd->sge_txmbuf_tag, - cd->sge_tx_map[cons], BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(cd->sge_txmbuf_tag, - cd->sge_tx_map[cons]); - m_freem(cd->sge_tx_mbuf[cons]); - cd->sge_tx_mbuf[cons] = NULL; - if (SGE_TX_ERROR(txstat) != 0) { + /* + * Only the first descriptor of multi-descriptor transmission + * is updated by controller. Driver should skip entire + * chained buffers for the transmitted frame. In other words + * TDC_OWN bit is valid only at the first descriptor of a + * multi-descriptor transmission. + */ + if (SGE_TX_ERROR(txstat) != 0) { #ifdef SGE_SHOW_ERRORS - device_printf(sc->sge_dev, "Tx error : 0x%b\n", - txstat, TX_ERR_BITS); + device_printf(sc->sge_dev, "Tx error : 0x%b\n", + txstat, TX_ERR_BITS); #endif - ifp->if_oerrors++; - } else { + ifp->if_oerrors++; + } else { #ifdef notyet - ifp->if_collisions += (txstat & 0xFFFF) - 1; + ifp->if_collisions += (txstat & 0xFFFF) - 1; #endif - ifp->if_opackets++; - } + ifp->if_opackets++; } - + txd = &cd->sge_txdesc[cons]; + for (nsegs = 0; nsegs < txd->tx_ndesc; nsegs++) { + ld->sge_tx_ring[cons].sge_cmdsts = 0; + SGE_INC(cons, SGE_TX_RING_CNT); + } + /* Reclaim transmitted mbuf. */ + KASSERT(txd->tx_m != NULL, + ("%s: freeing NULL mbuf\n", __func__)); + bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); + m_freem(txd->tx_m); + txd->tx_m = NULL; + cd->sge_tx_cnt -= txd->tx_ndesc; + KASSERT(cd->sge_tx_cnt >= 0, + ("%s: Active Tx desc counter was garbled\n", __func__)); + txd->tx_ndesc = 0; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } cd->sge_tx_cons = cons; if (cd->sge_tx_cnt == 0) @@ -1388,73 +1422,78 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head) { struct mbuf *m; struct sge_desc *desc; + struct sge_txdesc *txd; bus_dma_segment_t txsegs[SGE_MAXTXSEGS]; - bus_dmamap_t map; uint32_t cflags; - int error, nsegs, prod; + int error, i, nsegs, prod, si; SGE_LOCK_ASSERT(sc); - prod = sc->sge_cdata.sge_tx_prod; - map = sc->sge_cdata.sge_tx_map[prod]; - /* - * Reading Windows inf file indicates SiS controller supports - * TSO, VLAN hardware tag insertion/stripping, interrupt - * moderation and Tx/Rx checksum offloading. Unfortunately - * vendor didn't release these information so we're guessing - * descriptor usage with trial and errors. - * - * Controller seems to support multi-fragmented buffers but - * don't know how to enable that feature so limit number of - * fragmented Tx buffers to single buffer until we understand - * the controller internals. - * I assume the controller can pad zero bytes if frame length - * is less than 60 bytes and I also think the controller has - * no Tx buffer alignment limitation. - Need testing! - */ - if ((*m_head)->m_next != NULL) { - m = m_defrag(*m_head, M_DONTWAIT); + si = prod = sc->sge_cdata.sge_tx_prod; + txd = &sc->sge_cdata.sge_txdesc[prod]; + error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, + txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); + if (error == EFBIG) { + m = m_collapse(*m_head, M_DONTWAIT, SGE_MAXTXSEGS); if (m == NULL) { m_freem(*m_head); *m_head = NULL; return (ENOBUFS); } *m_head = m; - } - error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, map, - *m_head, txsegs, &nsegs, 0); - if (error != 0) { - m_freem(*m_head); - *m_head = NULL; + error = bus_dmamap_load_mbuf_sg(sc->sge_cdata.sge_txmbuf_tag, + txd->tx_dmamap, *m_head, txsegs, &nsegs, 0); + if (error != 0) { + m_freem(*m_head); + *m_head = NULL; + return (error); + } + } else if (error != 0) return (error); - } + + KASSERT(nsegs != 0, ("zero segment returned")); /* Check descriptor overrun. */ if (sc->sge_cdata.sge_tx_cnt + nsegs >= SGE_TX_RING_CNT) { - bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, map); + bus_dmamap_unload(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap); return (ENOBUFS); } - bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, map, + bus_dmamap_sync(sc->sge_cdata.sge_txmbuf_tag, txd->tx_dmamap, BUS_DMASYNC_PREWRITE); + m = *m_head; cflags = 0; - if ((*m_head)->m_pkthdr.csum_flags & CSUM_IP) + if (m->m_pkthdr.csum_flags & CSUM_IP) cflags |= TDC_IP_CSUM; - if ((*m_head)->m_pkthdr.csum_flags & CSUM_TCP) + if (m->m_pkthdr.csum_flags & CSUM_TCP) cflags |= TDC_TCP_CSUM; - if ((*m_head)->m_pkthdr.csum_flags & CSUM_UDP) + if (m->m_pkthdr.csum_flags & CSUM_UDP) cflags |= TDC_UDP_CSUM; - desc = &sc->sge_ldata.sge_tx_ring[prod]; - desc->sge_sts_size = htole32((*m_head)->m_pkthdr.len); - desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[0].ds_addr)); - desc->sge_flags = htole32(txsegs[0].ds_len); - if (prod == SGE_TX_RING_CNT - 1) - desc->sge_flags |= htole32(RING_END); + for (i = 0; i < nsegs; i++) { + desc = &sc->sge_ldata.sge_tx_ring[prod]; + if (i == 0) { + desc->sge_sts_size = htole32(m->m_pkthdr.len); + desc->sge_cmdsts = 0; + } else { + desc->sge_sts_size = 0; + desc->sge_cmdsts = htole32(TDC_OWN); + } + desc->sge_ptr = htole32(SGE_ADDR_LO(txsegs[i].ds_addr)); + desc->sge_flags = htole32(txsegs[i].ds_len); + if (prod == SGE_TX_RING_CNT - 1) + desc->sge_flags |= htole32(RING_END); + sc->sge_cdata.sge_tx_cnt++; + SGE_INC(prod, SGE_TX_RING_CNT); + } + /* Update producer index. */ + sc->sge_cdata.sge_tx_prod = prod; + + desc = &sc->sge_ldata.sge_tx_ring[si]; /* Configure VLAN. */ - if(((*m_head)->m_flags & M_VLANTAG) != 0) { - cflags |= (*m_head)->m_pkthdr.ether_vtag; + if((m->m_flags & M_VLANTAG) != 0) { + cflags |= m->m_pkthdr.ether_vtag; desc->sge_sts_size |= htole32(TDS_INS_VLAN); } - desc->sge_cmdsts = htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags); + desc->sge_cmdsts |= htole32(TDC_DEF | TDC_CRC | TDC_PAD | cflags); #if 1 if ((sc->sge_flags & SGE_FLAG_SPEED_1000) != 0) desc->sge_cmdsts |= htole32(TDC_BST); @@ -1466,13 +1505,9 @@ sge_encap(struct sge_softc *sc, struct mbuf **m_head) } #endif /* Request interrupt and give ownership to controller. */ - if ((prod % SGE_TX_INTR_FRAMES) == 0) - desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR); - else - desc->sge_cmdsts |= htole32(TDC_OWN); - sc->sge_cdata.sge_tx_mbuf[prod] = *m_head; - sc->sge_cdata.sge_tx_cnt++; - SGE_INC(sc->sge_cdata.sge_tx_prod, SGE_TX_RING_CNT); + desc->sge_cmdsts |= htole32(TDC_OWN | TDC_INTR); + txd->tx_m = m; + txd->tx_ndesc = nsegs; return (0); } @@ -1503,7 +1538,8 @@ sge_start_locked(struct ifnet *ifp) return; for (queued = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { - if (sc->sge_cdata.sge_tx_cnt == SGE_TX_RING_CNT - 1) { + if (sc->sge_cdata.sge_tx_cnt > (SGE_TX_RING_CNT - + SGE_MAXTXSEGS)) { ifp->if_drv_flags |= IFF_DRV_OACTIVE; break; } diff --git a/sys/dev/sge/if_sgereg.h b/sys/dev/sge/if_sgereg.h index 722dd3c..c06072c 100644 --- a/sys/dev/sge/if_sgereg.h +++ b/sys/dev/sge/if_sgereg.h @@ -283,7 +283,7 @@ struct sge_desc { #define SGE_RX_RING_CNT 256 /* [8, 1024] */ #define SGE_TX_RING_CNT 256 /* [8, 8192] */ #define SGE_DESC_ALIGN 16 -#define SGE_MAXTXSEGS 1 +#define SGE_MAXTXSEGS 16 #define SGE_RX_BUF_ALIGN sizeof(uint64_t) #define SGE_RX_RING_SZ (SGE_RX_RING_CNT * sizeof(struct sge_desc)) @@ -298,6 +298,17 @@ struct sge_list_data { bus_addr_t sge_tx_paddr; }; +struct sge_txdesc { + struct mbuf *tx_m; + bus_dmamap_t tx_dmamap; + int tx_ndesc; +}; + +struct sge_rxdesc { + struct mbuf *rx_m; + bus_dmamap_t rx_dmamap; +}; + struct sge_chain_data { bus_dma_tag_t sge_tag; bus_dma_tag_t sge_rx_tag; @@ -306,11 +317,9 @@ struct sge_chain_data { bus_dmamap_t sge_tx_dmamap; bus_dma_tag_t sge_txmbuf_tag; bus_dma_tag_t sge_rxmbuf_tag; - struct mbuf *sge_rx_mbuf[SGE_RX_RING_CNT]; - struct mbuf *sge_tx_mbuf[SGE_TX_RING_CNT]; - bus_dmamap_t sge_rx_map[SGE_RX_RING_CNT]; + struct sge_txdesc sge_txdesc[SGE_TX_RING_CNT]; + struct sge_rxdesc sge_rxdesc[SGE_RX_RING_CNT]; bus_dmamap_t sge_rx_spare_map; - bus_dmamap_t sge_tx_map[SGE_TX_RING_CNT]; int sge_rx_cons; int sge_tx_prod; int sge_tx_cons; -- cgit v1.1 From b1f2a2d1bf5b405cd7fdc2686ebba8457803af24 Mon Sep 17 00:00:00 2001 From: delphij Date: Tue, 4 May 2010 19:58:55 +0000 Subject: Remove if_ar, if_ray, if_sr, if_ppp, if_sl to reflect the current modules available, they were removed due to NEEDSGIANT. While I'm there, add if_et which was missed quite a while ago. MFC after: 2 weeks --- sys/boot/forth/loader.conf | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf index e0e4409..d48d8c4 100644 --- a/sys/boot/forth/loader.conf +++ b/sys/boot/forth/loader.conf @@ -197,8 +197,6 @@ if_epair_load="NO" # Virtual b-t-b Ethernet-like interface pair if_faith_load="NO" # IPv6-to-IPv4 TCP relay capturing interface if_gif_load="NO" # generic tunnel interface if_gre_load="NO" # encapsulating network device -if_ppp_load="NO" # Kernel ppp -if_sl_load="NO" # SLIP if_stf_load="NO" # 6to4 tunnel interface if_tap_load="NO" # Ethernet tunnel software network interface if_tun_load="NO" # Tunnel driver (user process ppp) @@ -217,7 +215,6 @@ if_age_load="NO" # Attansic/Atheros L1 Gigabit Ethernet if_alc_load="NO" # Atheros AR8131/AR8132 Ethernet if_ale_load="NO" # Atheros AR8121/AR8113/AR8114 Ethernet if_an_load="NO" # Aironet 4500/4800 802.11 wireless NICs -if_ar_load="NO" # Digi SYNC/570i if_ath_load="NO" # Atheros IEEE 802.11 wireless NICs if_aue_load="NO" # ADMtek AN986 Pegasus USB Ethernet if_awi_load="NO" # AMD PCnetMobile IEEE 802.11 wireless NICs @@ -237,6 +234,7 @@ if_ed_load="NO" # National Semiconductor DS8390/WD83C690 if_em_load="NO" # Intel(R) PRO/1000 Gigabit Ethernet if_en_load="NO" # Midway-based ATM interfaces if_ep_load="NO" # 3Com Etherlink III (3c5x9) +if_et_load="NO" # Agere ET1310 10/100/Gigabit Ethernet if_ex_load="NO" # Intel EtherExpress Pro/10 Ethernet if_fe_load="NO" # Fujitsu MB86960A/MB86965A based Ethernet # adapters @@ -265,17 +263,15 @@ if_nve_load="NO" # NVIDIA nForce MCP Networking Adapter if_nxge_load="NO" # Neterion Xframe 10Gb Ethernet if_pcn_load="NO" # AMD PCnet PCI if_ral_load="NO" # Ralink Technology wireless -if_ray_load="NO" # Raytheon Raylink/Webgear Aviator PCCard if_re_load="NO" # RealTek 8139C+/8169/8169S/8110S if_rl_load="NO" # RealTek 8129/8139 if_rue_load="NO" # RealTek RTL8150 USB to Fast Ethernet if_sbni_load="NO" # Granch SBNI12 leased line adapters if_sf_load="NO" # Adaptec Duralink PCI (AIC-6915 "starfire") -if_sge_load="NO" # Silicon Integrated Systems SiS190/191 +if_sge_load="NO" # Silicon Integrated Systems SiS 190/191 if_sis_load="NO" # Silicon Integrated Systems SiS 900/7016 if_sk_load="NO" # SysKonnect SK-984x series PCI Gigabit Ethernet if_sn_load="NO" # SMC 91Cxx -if_sr_load="NO" # synchronous RISCom/N2 / WANic 400/405 if_ste_load="NO" # Sundance Technologies ST201 Fast Ethernet if_stge_load="NO" # Sundance/Tamarack TC9021 Gigabit Ethernet if_ti_load="NO" # Alteon Networks Tigon 1 and Tigon 2 -- cgit v1.1 From d606e39dd9fd9e3347aeb03267df253fa31b4f1a Mon Sep 17 00:00:00 2001 From: yongari Date: Tue, 4 May 2010 21:23:59 +0000 Subject: Free entire mbuf chain instead of the first mbuf. --- sys/dev/sge/if_sge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/dev/sge/if_sge.c b/sys/dev/sge/if_sge.c index c384983..ee88cb6 100644 --- a/sys/dev/sge/if_sge.c +++ b/sys/dev/sge/if_sge.c @@ -1015,7 +1015,7 @@ sge_list_tx_free(struct sge_softc *sc) bus_dmamap_sync(cd->sge_txmbuf_tag, txd->tx_dmamap, BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(cd->sge_txmbuf_tag, txd->tx_dmamap); - m_free(txd->tx_m); + m_freem(txd->tx_m); txd->tx_m = NULL; txd->tx_ndesc = 0; } @@ -1064,7 +1064,7 @@ sge_list_rx_free(struct sge_softc *sc) BUS_DMASYNC_POSTREAD); bus_dmamap_unload(cd->sge_rxmbuf_tag, rxd->rx_dmamap); - m_free(rxd->rx_m); + m_freem(rxd->rx_m); rxd->rx_m = NULL; } } -- cgit v1.1 From ebcbeb8a91a1c239c7945d6fbb3a918e91757506 Mon Sep 17 00:00:00 2001 From: yongari Date: Tue, 4 May 2010 22:24:19 +0000 Subject: When VLAN hardware tagging is disabled, make sure to disable VLAN checksum offloading as well as TSO over VLAN. Reported by: jhb --- sys/dev/msk/if_msk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c index af977bf..3f97c3a 100644 --- a/sys/dev/msk/if_msk.c +++ b/sys/dev/msk/if_msk.c @@ -1101,7 +1101,8 @@ msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data) (IFCAP_VLAN_HWTAGGING & ifp->if_capabilities) != 0) { ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; if ((IFCAP_VLAN_HWTAGGING & ifp->if_capenable) == 0) - ifp->if_capenable &= ~IFCAP_VLAN_HWTSO; + ifp->if_capenable &= + ~(IFCAP_VLAN_HWTSO | IFCAP_VLAN_HWCSUM); msk_setvlan(sc_if, ifp); } if (ifp->if_mtu > ETHERMTU && -- cgit v1.1 From 4045471dea00b4adc8b2213b9418074861e3c4c3 Mon Sep 17 00:00:00 2001 From: np Date: Tue, 4 May 2010 23:55:08 +0000 Subject: Add IFCAP_LINKSTATE to cxgb's capabilities. MFC after: 3 days --- sys/dev/cxgb/cxgb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c index a805b5d..01095c4 100644 --- a/sys/dev/cxgb/cxgb_main.c +++ b/sys/dev/cxgb/cxgb_main.c @@ -981,7 +981,7 @@ cxgb_makedev(struct port_info *pi) #define CXGB_CAP (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | \ IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO | \ - IFCAP_VLAN_HWTSO) + IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE) #define CXGB_CAP_ENABLE (CXGB_CAP & ~IFCAP_TSO6) static int -- cgit v1.1 From 30b63b91fa4784d0199bd0f95c61f2b6acaf8603 Mon Sep 17 00:00:00 2001 From: np Date: Wed, 5 May 2010 00:41:40 +0000 Subject: Add support for hardware filters to cxgb(4). The T3 chip can inspect L2/3/4 headers and can drop or steer packets as instructed. Filtering based on src ip, dst ip, src port, dst port, 802.1q, udp/tcp, and mac addr is possible. Add support in cxgbtool to program these filters. Some simple examples: Drop all tcp/80 traffic coming from the subnet specified. # cxgbtool cxgb2 filter 0 sip 192.168.1.0/24 dport 80 type tcp action drop Steer all incoming UDP traffic to qset 0. # cxgbtool cxgb2 filter 1 type udp queue 0 action pass Steer all tcp traffic from 192.168.1.1 to qset 1. # cxgbtool cxgb2 filter 2 sip 192.168.1.1 type tcp queue 1 action pass Drop fragments. # cxgbtool cxgb2 filter 3 type frag action drop List all filters. # cxgbtool cxgb2 filter list index SIP DIP sport dport VLAN PRI P/MAC type Q 0 192.168.1.0/24 0.0.0.0 * 80 0 0/1 */* tcp - 1 0.0.0.0/0 0.0.0.0 * * 0 0/1 */* udp 0 2 192.168.1.1/32 0.0.0.0 * * 0 0/1 */* tcp 1 3 0.0.0.0/0 0.0.0.0 * * 0 0/1 */* frag - 16367 0.0.0.0/0 0.0.0.0 * * 0 0/1 */* * * MFC after: 2 weeks --- sys/dev/cxgb/cxgb_ioctl.h | 29 +++++ sys/dev/cxgb/cxgb_main.c | 273 +++++++++++++++++++++++++++++++++++++++++++ usr.sbin/cxgbtool/cxgbtool.c | 186 ++++++++++++++++++++++++++++- 3 files changed, 482 insertions(+), 6 deletions(-) diff --git a/sys/dev/cxgb/cxgb_ioctl.h b/sys/dev/cxgb/cxgb_ioctl.h index e4b4875..3f3ac5a 100644 --- a/sys/dev/cxgb/cxgb_ioctl.h +++ b/sys/dev/cxgb/cxgb_ioctl.h @@ -59,6 +59,9 @@ enum { CH_CLEAR_STATS, CH_GET_UP_LA, CH_GET_UP_IOQS, + CH_SET_FILTER, + CH_DEL_FILTER, + CH_GET_FILTER, }; /* statistics categories */ @@ -215,6 +218,29 @@ struct ch_up_ioqs { struct t3_ioq_entry *data; }; +struct ch_filter_tuple { + uint32_t sip; + uint32_t dip; + uint16_t sport; + uint16_t dport; + uint16_t vlan:12; + uint16_t vlan_prio:3; +}; + +struct ch_filter { + uint32_t filter_id; + struct ch_filter_tuple val; + struct ch_filter_tuple mask; + uint16_t mac_addr_idx; + uint8_t mac_hit:1; + uint8_t proto:2; + + uint8_t want_filter_id:1; + uint8_t pass:1; + uint8_t rss:1; + uint8_t qset; +}; + #define CHELSIO_SETREG _IOW('f', CH_SETREG, struct ch_reg) #define CHELSIO_GETREG _IOWR('f', CH_GETREG, struct ch_reg) #define CHELSIO_GETMTUTAB _IOR('f', CH_GETMTUTAB, struct ch_mtus) @@ -239,4 +265,7 @@ struct ch_up_ioqs { #define CHELSIO_GET_EEPROM _IOWR('f', CH_GET_EEPROM, struct ch_eeprom) #define CHELSIO_GET_UP_LA _IOWR('f', CH_GET_UP_LA, struct ch_up_la) #define CHELSIO_GET_UP_IOQS _IOWR('f', CH_GET_UP_IOQS, struct ch_up_ioqs) +#define CHELSIO_SET_FILTER _IOW('f', CH_SET_FILTER, struct ch_filter) +#define CHELSIO_DEL_FILTER _IOW('f', CH_DEL_FILTER, struct ch_filter) +#define CHELSIO_GET_FILTER _IOWR('f', CH_GET_FILTER, struct ch_filter) #endif diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c index 01095c4..ad2caed 100644 --- a/sys/dev/cxgb/cxgb_main.c +++ b/sys/dev/cxgb/cxgb_main.c @@ -99,6 +99,13 @@ static void cxgb_ext_intr_handler(void *, int); static void cxgb_tick_handler(void *, int); static void cxgb_tick(void *); static void setup_rss(adapter_t *sc); +static int alloc_filters(struct adapter *); +static int setup_hw_filters(struct adapter *); +static int set_filter(struct adapter *, int, const struct filter_info *); +static inline void mk_set_tcb_field(struct cpl_set_tcb_field *, unsigned int, + unsigned int, u64, u64); +static inline void set_tcb_field_ulp(struct cpl_set_tcb_field *, unsigned int, + unsigned int, u64, u64); /* Attachment glue for the PCI controller end of the device. Each port of * the device is attached separately, as defined later. @@ -1661,6 +1668,13 @@ cxgb_up(struct adapter *sc) if ((err = update_tpsram(sc))) goto out; + if (is_offload(sc)) { + sc->params.mc5.nservers = 0; + sc->params.mc5.nroutes = 0; + sc->params.mc5.nfilters = t3_mc5_size(&sc->mc5) - + MC5_MIN_TIDS; + } + err = t3_init_hw(sc, 0); if (err) goto out; @@ -1672,6 +1686,7 @@ cxgb_up(struct adapter *sc) if (err) goto out; + alloc_filters(sc); setup_rss(sc); t3_intr_clear(sc); @@ -1698,6 +1713,7 @@ cxgb_up(struct adapter *sc) if (!(sc->flags & QUEUES_BOUND)) { bind_qsets(sc); + setup_hw_filters(sc); sc->flags |= QUEUES_BOUND; } @@ -3076,6 +3092,139 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, free(buf, M_DEVBUF); break; } + case CHELSIO_SET_FILTER: { + struct ch_filter *f = (struct ch_filter *)data;; + struct filter_info *p; + unsigned int nfilters = sc->params.mc5.nfilters; + + if (!is_offload(sc)) + return (EOPNOTSUPP); /* No TCAM */ + if (!(sc->flags & FULL_INIT_DONE)) + return (EAGAIN); /* mc5 not setup yet */ + if (nfilters == 0) + return (EBUSY); /* TOE will use TCAM */ + + /* sanity checks */ + if (f->filter_id >= nfilters || + (f->val.dip && f->mask.dip != 0xffffffff) || + (f->val.sport && f->mask.sport != 0xffff) || + (f->val.dport && f->mask.dport != 0xffff) || + (f->val.vlan && f->mask.vlan != 0xfff) || + (f->val.vlan_prio && + f->mask.vlan_prio != FILTER_NO_VLAN_PRI) || + (f->mac_addr_idx != 0xffff && f->mac_addr_idx > 15) || + f->qset >= SGE_QSETS || + sc->rrss_map[f->qset] >= RSS_TABLE_SIZE) + return (EINVAL); + + /* Was allocated with M_WAITOK */ + KASSERT(sc->filters, ("filter table NULL\n")); + + p = &sc->filters[f->filter_id]; + if (p->locked) + return (EPERM); + + bzero(p, sizeof(*p)); + p->sip = f->val.sip; + p->sip_mask = f->mask.sip; + p->dip = f->val.dip; + p->sport = f->val.sport; + p->dport = f->val.dport; + p->vlan = f->mask.vlan ? f->val.vlan : 0xfff; + p->vlan_prio = f->mask.vlan_prio ? (f->val.vlan_prio & 6) : + FILTER_NO_VLAN_PRI; + p->mac_hit = f->mac_hit; + p->mac_vld = f->mac_addr_idx != 0xffff; + p->mac_idx = f->mac_addr_idx; + p->pkt_type = f->proto; + p->report_filter_id = f->want_filter_id; + p->pass = f->pass; + p->rss = f->rss; + p->qset = f->qset; + + error = set_filter(sc, f->filter_id, p); + if (error == 0) + p->valid = 1; + break; + } + case CHELSIO_DEL_FILTER: { + struct ch_filter *f = (struct ch_filter *)data; + struct filter_info *p; + unsigned int nfilters = sc->params.mc5.nfilters; + + if (!is_offload(sc)) + return (EOPNOTSUPP); + if (!(sc->flags & FULL_INIT_DONE)) + return (EAGAIN); + if (nfilters == 0 || sc->filters == NULL) + return (EINVAL); + if (f->filter_id >= nfilters) + return (EINVAL); + + p = &sc->filters[f->filter_id]; + if (p->locked) + return (EPERM); + if (!p->valid) + return (EFAULT); /* Read "Bad address" as "Bad index" */ + + bzero(p, sizeof(*p)); + p->sip = p->sip_mask = 0xffffffff; + p->vlan = 0xfff; + p->vlan_prio = FILTER_NO_VLAN_PRI; + p->pkt_type = 1; + error = set_filter(sc, f->filter_id, p); + break; + } + case CHELSIO_GET_FILTER: { + struct ch_filter *f = (struct ch_filter *)data; + struct filter_info *p; + unsigned int i, nfilters = sc->params.mc5.nfilters; + + if (!is_offload(sc)) + return (EOPNOTSUPP); + if (!(sc->flags & FULL_INIT_DONE)) + return (EAGAIN); + if (nfilters == 0 || sc->filters == NULL) + return (EINVAL); + + i = f->filter_id == 0xffffffff ? 0 : f->filter_id + 1; + for (; i < nfilters; i++) { + p = &sc->filters[i]; + if (!p->valid) + continue; + + bzero(f, sizeof(*f)); + + f->filter_id = i; + f->val.sip = p->sip; + f->mask.sip = p->sip_mask; + f->val.dip = p->dip; + f->mask.dip = p->dip ? 0xffffffff : 0; + f->val.sport = p->sport; + f->mask.sport = p->sport ? 0xffff : 0; + f->val.dport = p->dport; + f->mask.dport = p->dport ? 0xffff : 0; + f->val.vlan = p->vlan == 0xfff ? 0 : p->vlan; + f->mask.vlan = p->vlan == 0xfff ? 0 : 0xfff; + f->val.vlan_prio = p->vlan_prio == FILTER_NO_VLAN_PRI ? + 0 : p->vlan_prio; + f->mask.vlan_prio = p->vlan_prio == FILTER_NO_VLAN_PRI ? + 0 : FILTER_NO_VLAN_PRI; + f->mac_hit = p->mac_hit; + f->mac_addr_idx = p->mac_vld ? p->mac_idx : 0xffff; + f->proto = p->pkt_type; + f->want_filter_id = p->report_filter_id; + f->pass = p->pass; + f->rss = p->rss; + f->qset = p->qset; + + break; + } + + if (i == nfilters) + f->filter_id = 0xffffffff; + break; + } default: return (EOPNOTSUPP); break; @@ -3130,5 +3279,129 @@ cxgb_get_regs(adapter_t *sc, struct ch_ifconf_regs *regs, uint8_t *buf) XGM_REG(A_XGM_RX_SPI4_SOP_EOP_CNT, 1)); } +static int +alloc_filters(struct adapter *sc) +{ + struct filter_info *p; + unsigned int nfilters = sc->params.mc5.nfilters; + + if (nfilters == 0) + return (0); + + p = malloc(sizeof(*p) * nfilters, M_DEVBUF, M_WAITOK | M_ZERO); + sc->filters = p; + + p = &sc->filters[nfilters - 1]; + p->vlan = 0xfff; + p->vlan_prio = FILTER_NO_VLAN_PRI; + p->pass = p->rss = p->valid = p->locked = 1; + + return (0); +} + +static int +setup_hw_filters(struct adapter *sc) +{ + int i, rc; + unsigned int nfilters = sc->params.mc5.nfilters; + + if (!sc->filters) + return (0); + + t3_enable_filters(sc); + + for (i = rc = 0; i < nfilters && !rc; i++) { + if (sc->filters[i].locked) + rc = set_filter(sc, i, &sc->filters[i]); + } + + return (rc); +} + +static int +set_filter(struct adapter *sc, int id, const struct filter_info *f) +{ + int len; + struct mbuf *m; + struct ulp_txpkt *txpkt; + struct work_request_hdr *wr; + struct cpl_pass_open_req *oreq; + struct cpl_set_tcb_field *sreq; + + len = sizeof(*wr) + sizeof(*oreq) + 2 * sizeof(*sreq); + KASSERT(len <= MHLEN, ("filter request too big for an mbuf")); + + id += t3_mc5_size(&sc->mc5) - sc->params.mc5.nroutes - + sc->params.mc5.nfilters; + + m = m_gethdr(M_WAITOK, MT_DATA); + m->m_len = m->m_pkthdr.len = len; + bzero(mtod(m, char *), len); + + wr = mtod(m, struct work_request_hdr *); + wr->wrh_hi = htonl(V_WR_OP(FW_WROPCODE_BYPASS) | F_WR_ATOMIC); + + oreq = (struct cpl_pass_open_req *)(wr + 1); + txpkt = (struct ulp_txpkt *)oreq; + txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT)); + txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*oreq) / 8)); + OPCODE_TID(oreq) = htonl(MK_OPCODE_TID(CPL_PASS_OPEN_REQ, id)); + oreq->local_port = htons(f->dport); + oreq->peer_port = htons(f->sport); + oreq->local_ip = htonl(f->dip); + oreq->peer_ip = htonl(f->sip); + oreq->peer_netmask = htonl(f->sip_mask); + oreq->opt0h = 0; + oreq->opt0l = htonl(F_NO_OFFLOAD); + oreq->opt1 = htonl(V_MAC_MATCH_VALID(f->mac_vld) | + V_CONN_POLICY(CPL_CONN_POLICY_FILTER) | + V_VLAN_PRI(f->vlan_prio >> 1) | + V_VLAN_PRI_VALID(f->vlan_prio != FILTER_NO_VLAN_PRI) | + V_PKT_TYPE(f->pkt_type) | V_OPT1_VLAN(f->vlan) | + V_MAC_MATCH(f->mac_idx | (f->mac_hit << 4))); + + sreq = (struct cpl_set_tcb_field *)(oreq + 1); + set_tcb_field_ulp(sreq, id, 1, 0x1800808000ULL, + (f->report_filter_id << 15) | (1 << 23) | + ((u64)f->pass << 35) | ((u64)!f->rss << 36)); + set_tcb_field_ulp(sreq + 1, id, 0, 0xffffffff, (2 << 19) | 1); + t3_mgmt_tx(sc, m); + + if (f->pass && !f->rss) { + len = sizeof(*sreq); + m = m_gethdr(M_WAITOK, MT_DATA); + m->m_len = m->m_pkthdr.len = len; + bzero(mtod(m, char *), len); + sreq = mtod(m, struct cpl_set_tcb_field *); + sreq->wr.wrh_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD)); + mk_set_tcb_field(sreq, id, 25, 0x3f80000, + (u64)sc->rrss_map[f->qset] << 19); + t3_mgmt_tx(sc, m); + } + return 0; +} + +static inline void +mk_set_tcb_field(struct cpl_set_tcb_field *req, unsigned int tid, + unsigned int word, u64 mask, u64 val) +{ + OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid)); + req->reply = V_NO_REPLY(1); + req->cpu_idx = 0; + req->word = htons(word); + req->mask = htobe64(mask); + req->val = htobe64(val); +} + +static inline void +set_tcb_field_ulp(struct cpl_set_tcb_field *req, unsigned int tid, + unsigned int word, u64 mask, u64 val) +{ + struct ulp_txpkt *txpkt = (struct ulp_txpkt *)req; + + txpkt->cmd_dest = htonl(V_ULPTX_CMD(ULP_TXPKT)); + txpkt->len = htonl(V_ULPTX_NFLITS(sizeof(*req) / 8)); + mk_set_tcb_field(req, tid, word, mask, val); +} MODULE_DEPEND(if_cxgb, cxgb_t3fw, 1, 1, 1); diff --git a/usr.sbin/cxgbtool/cxgbtool.c b/usr.sbin/cxgbtool/cxgbtool.c index 28d91f9..b705ff8 100644 --- a/usr.sbin/cxgbtool/cxgbtool.c +++ b/usr.sbin/cxgbtool/cxgbtool.c @@ -1,6 +1,6 @@ /************************************************************************** -Copyright (c) 2007-2009, Chelsio Inc. +Copyright (c) 2007-2010, Chelsio Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -93,6 +93,9 @@ usage(FILE *fp) "\tclearstats clear MAC statistics\n" "\tcontext show an SGE context\n" "\tdesc [] dump SGE descriptors\n" + "\tfilter [ ] ... set a filter\n" + "\tfilter delete|clear delete a filter\n" + "\tfilter list list all filters\n" "\tioqs dump uP IOQs\n" "\tla dump uP logic analyzer info\n" "\tloadboot download boot image\n" @@ -1177,24 +1180,25 @@ parse_ipaddr(const char *s, uint32_t *addr, uint32_t *mask) * Parse a string containing a value and an optional colon separated mask. */ static int -parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask) +parse_val_mask_param(const char *s, uint32_t *val, uint32_t *mask, + uint32_t default_mask) { char *p; - *mask = 0xffffffffU; + *mask = default_mask; *val = strtoul(s, &p, 0); - if (p == s) + if (p == s || *val > default_mask) return -1; if (*p == ':' && p[1]) *mask = strtoul(p + 1, &p, 0); - return *p ? -1 : 0; + return *p || *mask > default_mask ? -1 : 0; } static int parse_trace_param(const char *s, uint32_t *val, uint32_t *mask) { return strchr(s, '.') ? parse_ipaddr(s, val, mask) : - parse_val_mask_param(s, val, mask); + parse_val_mask_param(s, val, mask, 0xffffffffU); } static int @@ -1273,6 +1277,174 @@ trace_config(int argc, char *argv[], int start_arg, const char *iff_name) return 0; } +static void +show_filters(const char *iff_name) +{ + static const char *pkt_type[] = { "*", "tcp", "udp", "frag" }; + struct ch_filter op; + union { + uint32_t nip; + uint8_t octet[4]; + } nsip, ndip; + char sip[20], dip[20]; + int header = 0; + + bzero(&op, sizeof(op)); + op.filter_id = 0xffffffff; + + do { + if (doit(iff_name, CHELSIO_GET_FILTER, &op) < 0) + err(1, "list filters"); + + if (op.filter_id == 0xffffffff) + break; + + if (!header) { + printf("index SIP DIP sport " + "dport VLAN PRI P/MAC type Q\n"); + header = 1; + } + + nsip.nip = htonl(op.val.sip); + ndip.nip = htonl(op.val.dip); + + sprintf(sip, "%u.%u.%u.%u/%-2u", nsip.octet[0], nsip.octet[1], + nsip.octet[2], nsip.octet[3], + op.mask.sip ? 33 - ffs(op.mask.sip) : 0); + sprintf(dip, "%u.%u.%u.%u", ndip.octet[0], ndip.octet[1], + ndip.octet[2], ndip.octet[3]); + printf("%5zu %18s %15s ", (size_t)op.filter_id, sip, dip); + printf(op.val.sport ? "%5u " : " * ", op.val.sport); + printf(op.val.dport ? "%5u " : " * ", op.val.dport); + printf(op.val.vlan != 0xfff ? "%4u " : " * ", op.val.vlan); + printf(op.val.vlan_prio == 7 ? " * " : + "%1u/%1u ", op.val.vlan_prio, op.val.vlan_prio | 1); + if (op.mac_addr_idx == 0xffff) + printf("*/* "); + else if (op.mac_hit) + printf("%1u/%3u ", (op.mac_addr_idx >> 3) & 0x1, + (op.mac_addr_idx) & 0x7); + else + printf("%1u/ * ", (op.mac_addr_idx >> 3) & 0x1); + printf("%4s ", pkt_type[op.proto]); + if (!op.pass) + printf("-\n"); + else if (op.rss) + printf("*\n"); + else + printf("%1u\n", op.qset); + } while (1); +} + +static int +filter_config(int argc, char *argv[], int start_arg, const char *iff_name) +{ + int ret = 0; + uint32_t val, mask; + struct ch_filter op; + + if (argc < start_arg + 1) + return -1; + + memset(&op, 0, sizeof(op)); + op.mac_addr_idx = 0xffff; + op.rss = 1; + + if (argc == start_arg + 1 && !strcmp(argv[start_arg], "list")) { + show_filters(iff_name); + return 0; + } + + if (get_int_arg(argv[start_arg++], &op.filter_id)) + return -1; + if (argc == start_arg + 1 && (!strcmp(argv[start_arg], "delete") || + !strcmp(argv[start_arg], "clear"))) { + if (doit(iff_name, CHELSIO_DEL_FILTER, &op) < 0) { + if (errno == EBUSY) + err(1, "no filter support when offload in use"); + err(1, "delete filter"); + } + return 0; + } + + while (start_arg + 2 <= argc) { + if (!strcmp(argv[start_arg], "sip")) { + ret = parse_ipaddr(argv[start_arg + 1], &op.val.sip, + &op.mask.sip); + } else if (!strcmp(argv[start_arg], "dip")) { + ret = parse_ipaddr(argv[start_arg + 1], &op.val.dip, + &op.mask.dip); + } else if (!strcmp(argv[start_arg], "sport")) { + ret = parse_val_mask_param(argv[start_arg + 1], + &val, &mask, 0xffff); + op.val.sport = val; + op.mask.sport = mask; + } else if (!strcmp(argv[start_arg], "dport")) { + ret = parse_val_mask_param(argv[start_arg + 1], + &val, &mask, 0xffff); + op.val.dport = val; + op.mask.dport = mask; + } else if (!strcmp(argv[start_arg], "vlan")) { + ret = parse_val_mask_param(argv[start_arg + 1], + &val, &mask, 0xfff); + op.val.vlan = val; + op.mask.vlan = mask; + } else if (!strcmp(argv[start_arg], "prio")) { + ret = parse_val_mask_param(argv[start_arg + 1], + &val, &mask, 7); + op.val.vlan_prio = val; + op.mask.vlan_prio = mask; + } else if (!strcmp(argv[start_arg], "mac")) { + if (!strcmp(argv[start_arg + 1], "none")) + val = -1; + else + ret = get_int_arg(argv[start_arg + 1], &val); + op.mac_hit = val != (uint32_t)-1; + op.mac_addr_idx = op.mac_hit ? val : 0; + } else if (!strcmp(argv[start_arg], "type")) { + if (!strcmp(argv[start_arg + 1], "tcp")) + op.proto = 1; + else if (!strcmp(argv[start_arg + 1], "udp")) + op.proto = 2; + else if (!strcmp(argv[start_arg + 1], "frag")) + op.proto = 3; + else + errx(1, "unknown type \"%s\"; must be one of " + "\"tcp\", \"udp\", or \"frag\"", + argv[start_arg + 1]); + } else if (!strcmp(argv[start_arg], "queue")) { + ret = get_int_arg(argv[start_arg + 1], &val); + op.qset = val; + op.rss = 0; + } else if (!strcmp(argv[start_arg], "action")) { + if (!strcmp(argv[start_arg + 1], "pass")) + op.pass = 1; + else if (strcmp(argv[start_arg + 1], "drop")) + errx(1, "unknown action \"%s\"; must be one of " + "\"pass\" or \"drop\"", + argv[start_arg + 1]); + } else + errx(1, "unknown filter parameter \"%s\"\n" + "known parameters are \"mac\", \"sip\", " + "\"dip\", \"sport\", \"dport\", \"vlan\", " + "\"prio\", \"type\", \"queue\", and \"action\"", + argv[start_arg]); + if (ret < 0) + errx(1, "bad value \"%s\" for parameter \"%s\"", + argv[start_arg + 1], argv[start_arg]); + start_arg += 2; + } + if (start_arg != argc) + errx(1, "no value for \"%s\"", argv[start_arg]); + + if (doit(iff_name, CHELSIO_SET_FILTER, &op) < 0) { + if (errno == EBUSY) + err(1, "no filter support when offload in use"); + err(1, "set filter"); + } + + return 0; +} static int get_sched_param(int argc, char *argv[], int pos, unsigned int *valp) { @@ -1501,6 +1673,8 @@ run_cmd(int argc, char *argv[], const char *iff_name) r = pktsched(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "tcb")) r = get_tcb2(argc, argv, 3, iff_name); + else if (!strcmp(argv[2], "filter")) + r = filter_config(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "clearstats")) r = clear_stats(argc, argv, 3, iff_name); else if (!strcmp(argv[2], "la")) -- cgit v1.1 From ea7b6345be41650b664c9b86b93526b79177c75f Mon Sep 17 00:00:00 2001 From: alc Date: Wed, 5 May 2010 03:45:46 +0000 Subject: Push down the acquisition of the page queues lock into vm_page_unwire(). Update the comment describing which lock should be held on entry to vm_page_wire(). Reviewed by: kib --- sys/dev/agp/agp.c | 4 ---- sys/dev/agp/agp_i810.c | 2 -- sys/fs/tmpfs/tmpfs_vnops.c | 2 -- sys/kern/vfs_bio.c | 6 ++---- sys/vm/vm_fault.c | 14 +++++--------- sys/vm/vm_glue.c | 2 -- sys/vm/vm_page.c | 16 ++++++++-------- 7 files changed, 15 insertions(+), 31 deletions(-) diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c index 89b68b0..577a7e9 100644 --- a/sys/dev/agp/agp.c +++ b/sys/dev/agp/agp.c @@ -624,9 +624,7 @@ bad: if (k >= i) vm_page_wakeup(m); vm_page_lock(m); - vm_page_lock_queues(); vm_page_unwire(m, 0); - vm_page_unlock_queues(); vm_page_unlock(m); } VM_OBJECT_UNLOCK(mem->am_obj); @@ -660,9 +658,7 @@ agp_generic_unbind_memory(device_t dev, struct agp_memory *mem) for (i = 0; i < mem->am_size; i += PAGE_SIZE) { m = vm_page_lookup(mem->am_obj, atop(i)); vm_page_lock(m); - vm_page_lock_queues(); vm_page_unwire(m, 0); - vm_page_unlock_queues(); vm_page_unlock(m); } VM_OBJECT_UNLOCK(mem->am_obj); diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c index 44eb50d..ff3ad1c 100644 --- a/sys/dev/agp/agp_i810.c +++ b/sys/dev/agp/agp_i810.c @@ -1011,9 +1011,7 @@ agp_i810_free_memory(device_t dev, struct agp_memory *mem) VM_OBJECT_LOCK(mem->am_obj); m = vm_page_lookup(mem->am_obj, 0); vm_page_lock(m); - vm_page_lock_queues(); vm_page_unwire(m, 0); - vm_page_unlock_queues(); vm_page_unlock(m); VM_OBJECT_UNLOCK(mem->am_obj); } else { diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 2d6005a..85cd23d 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -461,9 +461,7 @@ tmpfs_nocacheread(vm_object_t tobj, vm_pindex_t idx, VM_OBJECT_LOCK(tobj); out: vm_page_lock(m); - vm_page_lock_queues(); vm_page_unwire(m, TRUE); - vm_page_unlock_queues(); vm_page_unlock(m); vm_page_wakeup(m); vm_object_pip_subtract(tobj, 1); diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c index 589bdbd..ec8ad67 100644 --- a/sys/kern/vfs_bio.c +++ b/sys/kern/vfs_bio.c @@ -1571,7 +1571,6 @@ vfs_vmio_release(struct buf *bp) * everything on the inactive queue. */ vm_page_lock(m); - vm_page_lock_queues(); vm_page_unwire(m, 0); /* * We don't mess with busy pages, it is @@ -1580,6 +1579,7 @@ vfs_vmio_release(struct buf *bp) */ if ((m->oflags & VPO_BUSY) == 0 && m->busy == 0 && m->wire_count == 0) { + vm_page_lock_queues(); /* * Might as well free the page if we can and it has * no valid data. We also free the page if the @@ -1593,8 +1593,8 @@ vfs_vmio_release(struct buf *bp) } else if (buf_vm_page_count_severe()) { vm_page_try_to_cache(m); } + vm_page_unlock_queues(); } - vm_page_unlock_queues(); vm_page_unlock(m); } VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object); @@ -2957,9 +2957,7 @@ allocbuf(struct buf *bp, int size) bp->b_pages[i] = NULL; vm_page_lock(m); - vm_page_lock_queues(); vm_page_unwire(m, 0); - vm_page_unlock_queues(); vm_page_unlock(m); } VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object); diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 142a9ef..373433f 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -799,9 +799,7 @@ vnode_locked: vm_page_unlock(fs.first_m); vm_page_lock(fs.m); - vm_page_lock_queues(); vm_page_unwire(fs.m, FALSE); - vm_page_unlock_queues(); vm_page_unlock(fs.m); } /* @@ -1112,6 +1110,7 @@ vm_fault_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, { vm_paddr_t pa; vm_offset_t va; + vm_page_t m; pmap_t pmap; pmap = vm_map_pmap(map); @@ -1125,11 +1124,10 @@ vm_fault_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end, if (pa != 0) { pmap_change_wiring(pmap, va, FALSE); if (!fictitious) { - vm_page_lock(PHYS_TO_VM_PAGE(pa)); - vm_page_lock_queues(); - vm_page_unwire(PHYS_TO_VM_PAGE(pa), 1); - vm_page_unlock_queues(); - vm_page_unlock(PHYS_TO_VM_PAGE(pa)); + m = PHYS_TO_VM_PAGE(pa); + vm_page_lock(m); + vm_page_unwire(m, TRUE); + vm_page_unlock(m); } } } @@ -1275,9 +1273,7 @@ vm_fault_copy_entry(vm_map_t dst_map, vm_map_t src_map, if (upgrade) { vm_page_lock(src_m); - vm_page_lock_queues(); vm_page_unwire(src_m, 0); - vm_page_unlock_queues(); vm_page_unlock(src_m); vm_page_lock(dst_m); diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index 288c5d7..f86212f 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -529,9 +529,7 @@ vm_thread_swapout(struct thread *td) panic("vm_thread_swapout: kstack already missing?"); vm_page_dirty(m); vm_page_lock(m); - vm_page_lock_queues(); vm_page_unwire(m, 0); - vm_page_unlock_queues(); vm_page_unlock(m); } VM_OBJECT_UNLOCK(ksobj); diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 957bf82..a77dc13 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1532,7 +1532,7 @@ vm_page_free_toq(vm_page_t m) * another map, removing it from paging queues * as necessary. * - * The page queues must be locked. + * The page must be locked. * This routine may not block. */ void @@ -1584,31 +1584,31 @@ vm_page_wire(vm_page_t m) * be placed in the cache - for example, just after dirtying a page. * dirty pages in the cache are not allowed. * - * The page queues must be locked. + * The page must be locked. * This routine may not block. */ void vm_page_unwire(vm_page_t m, int activate) { - if ((m->flags & PG_UNMANAGED) == 0) { - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + if ((m->flags & PG_UNMANAGED) == 0) vm_page_lock_assert(m, MA_OWNED); - } if (m->flags & PG_FICTITIOUS) return; if (m->wire_count > 0) { m->wire_count--; if (m->wire_count == 0) { atomic_subtract_int(&cnt.v_wire_count, 1); - if (m->flags & PG_UNMANAGED) { - ; - } else if (activate) + if ((m->flags & PG_UNMANAGED) != 0) + return; + vm_page_lock_queues(); + if (activate) vm_page_enqueue(PQ_ACTIVE, m); else { vm_page_flag_clear(m, PG_WINATCFLS); vm_page_enqueue(PQ_INACTIVE, m); } + vm_page_unlock_queues(); } } else { panic("vm_page_unwire: invalid wire count: %d", m->wire_count); -- cgit v1.1 From d0c6c09b639d1f41c118b9b04f87011bf1905cf2 Mon Sep 17 00:00:00 2001 From: neel Date: Wed, 5 May 2010 04:37:45 +0000 Subject: Fix DDB backtrace involving kernel modules. We can no longer assume that all valid program counter values reside within the kernel object file. --- sys/mips/mips/db_trace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/mips/mips/db_trace.c b/sys/mips/mips/db_trace.c index 9417bcc..116470c 100644 --- a/sys/mips/mips/db_trace.c +++ b/sys/mips/mips/db_trace.c @@ -181,7 +181,7 @@ loop: } /* check for bad PC */ /*XXX MIPS64 bad: These hard coded constants are lame */ - if (pc & 3 || pc < (uintptr_t)0x80000000 || pc >= (uintptr_t)edata) { + if (pc & 3 || pc < (uintptr_t)0x80000000) { (*printfn) ("PC 0x%x: not in kernel\n", pc); ra = 0; goto done; -- cgit v1.1 From 4cb5fea559176d4125f76c10ba810c6fdd6bfc07 Mon Sep 17 00:00:00 2001 From: alc Date: Wed, 5 May 2010 07:40:54 +0000 Subject: Push down the acquisition of the page queues lock into vm_page_unwire(). --- sys/dev/drm/via_dmablit.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sys/dev/drm/via_dmablit.c b/sys/dev/drm/via_dmablit.c index 81d438a..9be42ff 100644 --- a/sys/dev/drm/via_dmablit.c +++ b/sys/dev/drm/via_dmablit.c @@ -179,9 +179,7 @@ via_free_sg_info(drm_via_sg_info_t *vsg) for (i=0; i < vsg->num_pages; ++i) { if ( NULL != (page = vsg->pages[i])) { vm_page_lock(page); - vm_page_lock_queues(); vm_page_unwire(page, 0); - vm_page_unlock_queues(); vm_page_unlock(page); } } -- cgit v1.1 From 966cbc602a2e6deb5c02871f57635e0b0bce90ee Mon Sep 17 00:00:00 2001 From: alc Date: Wed, 5 May 2010 07:47:40 +0000 Subject: Use an OBJT_PHYS object and thus PG_UNMANAGED pages to implement the TSB. The TSB is not a pageable structure, so there is no point in using managed pages. Reviewed by: kib --- sys/sparc64/sparc64/pmap.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sys/sparc64/sparc64/pmap.c b/sys/sparc64/sparc64/pmap.c index 4a2853c..daba4b7 100644 --- a/sys/sparc64/sparc64/pmap.c +++ b/sys/sparc64/sparc64/pmap.c @@ -1091,7 +1091,7 @@ pmap_pinit(pmap_t pm) * Allocate an object for it. */ if (pm->pm_tsb_obj == NULL) - pm->pm_tsb_obj = vm_object_allocate(OBJT_DEFAULT, TSB_PAGES); + pm->pm_tsb_obj = vm_object_allocate(OBJT_PHYS, TSB_PAGES); VM_OBJECT_LOCK(pm->pm_tsb_obj); for (i = 0; i < TSB_PAGES; i++) { @@ -1152,16 +1152,10 @@ pmap_release(pmap_t pm) KASSERT(obj->ref_count == 1, ("pmap_release: tsbobj ref count != 1")); while (!TAILQ_EMPTY(&obj->memq)) { m = TAILQ_FIRST(&obj->memq); - vm_page_lock_queues(); - if (vm_page_sleep_if_busy(m, FALSE, "pmaprl")) - continue; - KASSERT(m->hold_count == 0, - ("pmap_release: freeing held tsb page")); m->md.pmap = NULL; m->wire_count--; atomic_subtract_int(&cnt.v_wire_count, 1); vm_page_free_zero(m); - vm_page_unlock_queues(); } VM_OBJECT_UNLOCK(obj); pmap_qremove((vm_offset_t)pm->pm_tsb, TSB_PAGES); -- cgit v1.1 From 17f839086691cb0a04c5a5de0d93f7f8cd674e87 Mon Sep 17 00:00:00 2001 From: danger Date: Wed, 5 May 2010 08:43:47 +0000 Subject: - fix typo --- usr.sbin/jail/jail.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8 index 85fe988..8e49b07 100644 --- a/usr.sbin/jail/jail.8 +++ b/usr.sbin/jail/jail.8 @@ -239,7 +239,7 @@ The .Xr jexec 8 . .It Va ip4.addr A comma-separated list of IPv4 addresses assigned to the prison. -If this is set, the jail is restricted to using only these address. +If this is set, the jail is restricted to using only these addresses. Any attempts to use other addresses fail, and attempts to use wildcard addresses silently use the jailed address instead. For IPv4 the first address given will be kept used as the source address -- cgit v1.1 From 33dc72ec8c82736f5d5c2ab5c7e57aad0f4ba647 Mon Sep 17 00:00:00 2001 From: vanhu Date: Wed, 5 May 2010 08:55:26 +0000 Subject: Update SA's NAT-T stuff before calling key_mature() in key_update(), as SA may be used as soon as key_mature() has been called. Obtained from: NETASQ MFC after: 1 week --- sys/netipsec/key.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index 5219768..7fc199a 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -5156,12 +5156,6 @@ key_update(so, m, mhp) return key_senderror(so, m, error); } - /* check SA values to be mature. */ - if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) { - KEY_FREESAV(&sav); - return key_senderror(so, m, 0); - } - #ifdef IPSEC_NAT_T /* * Handle more NAT-T info if present, @@ -5188,6 +5182,12 @@ key_update(so, m, mhp) #endif #endif + /* check SA values to be mature. */ + if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) { + KEY_FREESAV(&sav); + return key_senderror(so, m, 0); + } + { struct mbuf *n; -- cgit v1.1 From b9358a210eef916d6fd2297113ab434502924bd2 Mon Sep 17 00:00:00 2001 From: vanhu Date: Wed, 5 May 2010 08:58:58 +0000 Subject: Set SA's natt_type before calling key_mature() in key_add(), as the SA may be used as soon as key_mature() has been done. Obtained from: NETASQ MFC after: 1 week --- sys/netipsec/key.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c index 7fc199a..d00489d 100644 --- a/sys/netipsec/key.c +++ b/sys/netipsec/key.c @@ -5422,12 +5422,6 @@ key_add(so, m, mhp) return key_senderror(so, m, error); } - /* check SA values to be mature. */ - if ((error = key_mature(newsav)) != 0) { - KEY_FREESAV(&newsav); - return key_senderror(so, m, error); - } - #ifdef IPSEC_NAT_T /* * Handle more NAT-T info if present, @@ -5447,6 +5441,12 @@ key_add(so, m, mhp) #endif #endif + /* check SA values to be mature. */ + if ((error = key_mature(newsav)) != 0) { + KEY_FREESAV(&newsav); + return key_senderror(so, m, error); + } + /* * don't call key_freesav() here, as we would like to keep the SA * in the database on success. -- cgit v1.1 From a3da7d7e6937462db7db7ba830332b719a5a46fa Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 5 May 2010 16:05:51 +0000 Subject: Fix a mistake in r207603. td_rux.rux_runtime still needs conversion. Reported and tested by: nwhitehorn Pointy hat to: kib MFC after: 6 days --- sys/kern/kern_proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 6c50f1f..055c844 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -901,7 +901,7 @@ fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp, int preferthread) kp->ki_pri.pri_user = td->td_user_pri; if (preferthread) { - kp->ki_runtime = td->td_rux.rux_runtime; + kp->ki_runtime = cputick2usec(td->td_rux.rux_runtime); kp->ki_pctcpu = sched_pctcpu(td); kp->ki_estcpu = td->td_estcpu; } -- cgit v1.1 From 402e3baadee30786a2a2fa508b9b7bec572da072 Mon Sep 17 00:00:00 2001 From: trasz Date: Wed, 5 May 2010 16:44:25 +0000 Subject: Move checking against RLIMIT_FSIZE into one place, vn_rlimit_fsize(). Reviewed by: kib --- sys/fs/ext2fs/ext2_readwrite.c | 14 ++------------ sys/fs/ext2fs/ext2_vnops.c | 3 --- sys/fs/msdosfs/msdosfs_vnops.c | 15 ++------------- sys/fs/nfsclient/nfs_clbio.c | 16 ++-------------- sys/fs/nwfs/nwfs_io.c | 17 ++++------------- sys/fs/smbfs/smbfs_io.c | 18 ++++-------------- sys/fs/tmpfs/tmpfs_vnops.c | 13 ++----------- sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c | 12 ++---------- sys/kern/vfs_vnops.c | 19 +++++++++++++++++++ sys/nfsclient/nfs_bio.c | 15 ++------------- sys/sys/vnode.h | 1 + sys/ufs/ffs/ffs_vnops.c | 17 ++--------------- 12 files changed, 42 insertions(+), 118 deletions(-) diff --git a/sys/fs/ext2fs/ext2_readwrite.c b/sys/fs/ext2fs/ext2_readwrite.c index 9c9749a..1a713ca 100644 --- a/sys/fs/ext2fs/ext2_readwrite.c +++ b/sys/fs/ext2fs/ext2_readwrite.c @@ -168,7 +168,6 @@ WRITE(ap) struct inode *ip; FS *fs; struct buf *bp; - struct thread *td; daddr_t lbn; off_t osize; int blkoffset, error, flags, ioflag, resid, size, seqcount, xfersize; @@ -213,17 +212,8 @@ WRITE(ap) * Maybe this should be above the vnode op call, but so long as * file servers have no limits, I don't think it matters. */ - td = uio->uio_td; - if (vp->v_type == VREG && td != NULL) { - PROC_LOCK(td->td_proc); - if (uio->uio_offset + uio->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { - psignal(td->td_proc, SIGXFSZ); - PROC_UNLOCK(td->td_proc); - return (EFBIG); - } - PROC_UNLOCK(td->td_proc); - } + if (vn_rlimit_fsize(vp, uio, uio->uio_td)) + return (EFBIG); resid = uio->uio_resid; osize = ip->i_size; diff --git a/sys/fs/ext2fs/ext2_vnops.c b/sys/fs/ext2fs/ext2_vnops.c index 2b2f8c5..2d302c5 100644 --- a/sys/fs/ext2fs/ext2_vnops.c +++ b/sys/fs/ext2fs/ext2_vnops.c @@ -46,7 +46,6 @@ #include #include -#include #include #include #include @@ -54,7 +53,6 @@ #include #include #include -#include #include #include #include @@ -71,7 +69,6 @@ #include -#include #include #include diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index e9c593b..f38c72b 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -61,9 +61,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -699,16 +696,8 @@ msdosfs_write(ap) /* * If they've exceeded their filesize limit, tell them about it. */ - if (td != NULL) { - PROC_LOCK(td->td_proc); - if ((uoff_t)uio->uio_offset + uio->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { - psignal(td->td_proc, SIGXFSZ); - PROC_UNLOCK(td->td_proc); - return (EFBIG); - } - PROC_UNLOCK(td->td_proc); - } + if (vn_rlimit_fsize(vp, uio, td)) + return (EFBIG); /* * If the offset we are starting the write at is beyond the end of diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c index e23da72..1413856 100644 --- a/sys/fs/nfsclient/nfs_clbio.c +++ b/sys/fs/nfsclient/nfs_clbio.c @@ -41,9 +41,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include -#include #include #include @@ -880,7 +877,6 @@ ncl_write(struct vop_write_args *ap) daddr_t lbn; int bcount; int n, on, error = 0; - struct proc *p = td?td->td_proc:NULL; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_WRITE) @@ -962,16 +958,8 @@ flush_and_restart: * Maybe this should be above the vnode op call, but so long as * file servers have no limits, i don't think it matters */ - if (p != NULL) { - PROC_LOCK(p); - if (uio->uio_offset + uio->uio_resid > - lim_cur(p, RLIMIT_FSIZE)) { - psignal(p, SIGXFSZ); - PROC_UNLOCK(p); - return (EFBIG); - } - PROC_UNLOCK(p); - } + if (vn_rlimit_fsize(vp, uio, td)) + return (EFBIG); biosize = vp->v_mount->mnt_stat.f_iosize; /* diff --git a/sys/fs/nwfs/nwfs_io.c b/sys/fs/nwfs/nwfs_io.c index ef1c800..83fbe70 100644 --- a/sys/fs/nwfs/nwfs_io.c +++ b/sys/fs/nwfs/nwfs_io.c @@ -28,16 +28,13 @@ */ #include #include -#include /* defines plimit structure in proc struct */ #include #include #include -#include #include #include #include #include -#include #include #include @@ -229,16 +226,10 @@ nwfs_writevnode(vp, uiop, cred, ioflag) } } if (uiop->uio_resid == 0) return 0; - if (td != NULL) { - PROC_LOCK(td->td_proc); - if (uiop->uio_offset + uiop->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { - psignal(td->td_proc, SIGXFSZ); - PROC_UNLOCK(td->td_proc); - return (EFBIG); - } - PROC_UNLOCK(td->td_proc); - } + + if (vn_rlimit_fsize(vp, uiop, td)) + return (EFBIG); + error = ncp_write(NWFSTOCONN(nmp), &np->n_fh, uiop, cred); NCPVNDEBUG("after: ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid); if (!error) { diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c index 6537ed4..7e021c1 100644 --- a/sys/fs/smbfs/smbfs_io.c +++ b/sys/fs/smbfs/smbfs_io.c @@ -28,9 +28,7 @@ */ #include #include -#include /* defines plimit structure in proc struct */ #include -#include #include #include #include @@ -235,7 +233,6 @@ smbfs_writevnode(struct vnode *vp, struct uio *uiop, struct smbmount *smp = VTOSMBFS(vp); struct smbnode *np = VTOSMB(vp); struct smb_cred scred; - struct proc *p; struct thread *td; int error = 0; @@ -249,7 +246,6 @@ smbfs_writevnode(struct vnode *vp, struct uio *uiop, /* if (uiop->uio_offset + uiop->uio_resid > smp->nm_maxfilesize) return (EFBIG);*/ td = uiop->uio_td; - p = td->td_proc; if (ioflag & (IO_APPEND | IO_SYNC)) { if (np->n_flag & NMODIFIED) { smbfs_attr_cacheremove(vp); @@ -271,16 +267,10 @@ smbfs_writevnode(struct vnode *vp, struct uio *uiop, } if (uiop->uio_resid == 0) return 0; - if (p != NULL) { - PROC_LOCK(p); - if (uiop->uio_offset + uiop->uio_resid > - lim_cur(p, RLIMIT_FSIZE)) { - psignal(p, SIGXFSZ); - PROC_UNLOCK(p); - return EFBIG; - } - PROC_UNLOCK(p); - } + + if (vn_rlimit_fsize(vp, uiop, td)) + return (EFBIG); + smb_makescred(&scred, td, cred); error = smb_write(smp->sm_share, np->n_fid, uiop, &scred); SMBVDEBUG("after: ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid); diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index 85cd23d..3ffef6b 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include #include #include #include @@ -748,16 +747,8 @@ tmpfs_write(struct vop_write_args *v) VFS_TO_TMPFS(vp->v_mount)->tm_maxfilesize) return (EFBIG); - if (vp->v_type == VREG && td != NULL) { - PROC_LOCK(td->td_proc); - if (uio->uio_offset + uio->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { - psignal(td->td_proc, SIGXFSZ); - PROC_UNLOCK(td->td_proc); - return (EFBIG); - } - PROC_UNLOCK(td->td_proc); - } + if (vn_rlimit_fsize(vp, uio, td)) + return (EFBIG); extended = uio->uio_offset + uio->uio_resid > node->tn_size; if (extended) { diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c index 20be557..b935b64 100644 --- a/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c +++ b/sys/gnu/fs/xfs/FreeBSD/xfs_vnops.c @@ -598,16 +598,8 @@ xfs_write_file(xfs_inode_t *xip, struct uio *uio, int ioflag) */ #if 0 td = uio->uio_td; - if (vp->v_type == VREG && td != NULL) { - PROC_LOCK(td->td_proc); - if (uio->uio_offset + uio->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { - psignal(td->td_proc, SIGXFSZ); - PROC_UNLOCK(td->td_proc); - return (EFBIG); - } - PROC_UNLOCK(td->td_proc); - } + if (vn_rlimit_fsize(vp, uio, uio->uio_td)) + return (EFBIG); #endif resid = uio->uio_resid; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 838f8f7..edc7ea8 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1338,3 +1339,21 @@ vn_vget_ino(struct vnode *vp, ino_t ino, int lkflags, struct vnode **rvp) } return (error); } + +int +vn_rlimit_fsize(const struct vnode *vp, const struct uio *uio, const struct thread *td) +{ + if (vp->v_type != VREG || td == NULL) + return (0); + + PROC_LOCK(td->td_proc); + if (uio->uio_offset + uio->uio_resid > + lim_cur(td->td_proc, RLIMIT_FSIZE)) { + psignal(td->td_proc, SIGXFSZ); + PROC_UNLOCK(td->td_proc); + return (EFBIG); + } + PROC_UNLOCK(td->td_proc); + + return (0); +} diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index 3a0705e..13effd0 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -45,8 +45,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include #include #include @@ -873,7 +871,6 @@ nfs_write(struct vop_write_args *ap) daddr_t lbn; int bcount; int n, on, error = 0; - struct proc *p = td?td->td_proc:NULL; #ifdef DIAGNOSTIC if (uio->uio_rw != UIO_WRITE) @@ -954,16 +951,8 @@ flush_and_restart: * Maybe this should be above the vnode op call, but so long as * file servers have no limits, i don't think it matters */ - if (p != NULL) { - PROC_LOCK(p); - if (uio->uio_offset + uio->uio_resid > - lim_cur(p, RLIMIT_FSIZE)) { - psignal(p, SIGXFSZ); - PROC_UNLOCK(p); - return (EFBIG); - } - PROC_UNLOCK(p); - } + if (vn_rlimit_fsize(vp, uio, td)) + return (EFBIG); biosize = vp->v_mount->mnt_stat.f_iosize; /* diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index b5784e4..7c4ae32 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -780,6 +780,7 @@ struct dirent; int vfs_read_dirent(struct vop_readdir_args *ap, struct dirent *dp, off_t off); int vfs_unixify_accmode(accmode_t *accmode); +int vn_rlimit_fsize(const struct vnode *vn, const struct uio *uio, const struct thread *td); #endif /* _KERNEL */ diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index e6617cb..85f8ffd 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -75,9 +75,6 @@ __FBSDID("$FreeBSD$"); #include #include #include -#include -#include -#include #include #include #include @@ -652,7 +649,6 @@ ffs_write(ap) struct inode *ip; struct fs *fs; struct buf *bp; - struct thread *td; ufs_lbn_t lbn; off_t osize; int seqcount; @@ -704,17 +700,8 @@ ffs_write(ap) * Maybe this should be above the vnode op call, but so long as * file servers have no limits, I don't think it matters. */ - td = uio->uio_td; - if (vp->v_type == VREG && td != NULL) { - PROC_LOCK(td->td_proc); - if (uio->uio_offset + uio->uio_resid > - lim_cur(td->td_proc, RLIMIT_FSIZE)) { - psignal(td->td_proc, SIGXFSZ); - PROC_UNLOCK(td->td_proc); - return (EFBIG); - } - PROC_UNLOCK(td->td_proc); - } + if (vn_rlimit_fsize(vp, uio, uio->uio_td)) + return (EFBIG); resid = uio->uio_resid; osize = ip->i_size; -- cgit v1.1 From 5c7ca3ee73eb98150c91a44001daf8ac7adb0907 Mon Sep 17 00:00:00 2001 From: alc Date: Wed, 5 May 2010 18:16:06 +0000 Subject: Acquire the page lock around all remaining calls to vm_page_free() on managed pages that didn't already have that lock held. (Freeing an unmanaged page, such as the various pmaps use, doesn't require the page lock.) This allows a change in vm_page_remove()'s locking requirements. It now expects the page lock to be held instead of the page queues lock. Consequently, the page queues lock is no longer required at all by callers to vm_page_rename(). Discussed with: kib --- sys/fs/nfsclient/nfs_clbio.c | 18 ++++++++++++------ sys/fs/nwfs/nwfs_io.c | 9 ++++++--- sys/fs/smbfs/smbfs_io.c | 18 ++++++++++++------ sys/kern/kern_exec.c | 2 ++ sys/kern/subr_uio.c | 2 ++ sys/nfsclient/nfs_bio.c | 18 ++++++++++++------ sys/ufs/ffs/ffs_vnops.c | 6 ++++-- sys/vm/vm_fault.c | 2 -- sys/vm/vm_object.c | 4 ---- sys/vm/vm_page.c | 12 ++++++++---- sys/vm/vm_page.h | 2 +- 11 files changed, 59 insertions(+), 34 deletions(-) diff --git a/sys/fs/nfsclient/nfs_clbio.c b/sys/fs/nfsclient/nfs_clbio.c index 1413856..df027ac 100644 --- a/sys/fs/nfsclient/nfs_clbio.c +++ b/sys/fs/nfsclient/nfs_clbio.c @@ -131,12 +131,15 @@ ncl_getpages(struct vop_getpages_args *ap) */ VM_OBJECT_LOCK(object); if (pages[ap->a_reqpage]->valid != 0) { - vm_page_lock_queues(); for (i = 0; i < npages; ++i) { - if (i != ap->a_reqpage) + if (i != ap->a_reqpage) { + vm_page_lock(pages[i]); + vm_page_lock_queues(); vm_page_free(pages[i]); + vm_page_unlock_queues(); + vm_page_unlock(pages[i]); + } } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return (0); } @@ -171,12 +174,15 @@ ncl_getpages(struct vop_getpages_args *ap) if (error && (uio.uio_resid == count)) { ncl_printf("nfs_getpages: error %d\n", error); VM_OBJECT_LOCK(object); - vm_page_lock_queues(); for (i = 0; i < npages; ++i) { - if (i != ap->a_reqpage) + if (i != ap->a_reqpage) { + vm_page_lock(pages[i]); + vm_page_lock_queues(); vm_page_free(pages[i]); + vm_page_unlock_queues(); + vm_page_unlock(pages[i]); + } } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return (VM_PAGER_ERROR); } diff --git a/sys/fs/nwfs/nwfs_io.c b/sys/fs/nwfs/nwfs_io.c index 83fbe70..0bb996f 100644 --- a/sys/fs/nwfs/nwfs_io.c +++ b/sys/fs/nwfs/nwfs_io.c @@ -428,12 +428,15 @@ nwfs_getpages(ap) VM_OBJECT_LOCK(object); if (error && (uio.uio_resid == count)) { printf("nwfs_getpages: error %d\n",error); - vm_page_lock_queues(); for (i = 0; i < npages; i++) { - if (ap->a_reqpage != i) + if (ap->a_reqpage != i) { + vm_page_lock(pages[i]); + vm_page_lock_queues(); vm_page_free(pages[i]); + vm_page_unlock_queues(); + vm_page_unlock(pages[i]); + } } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return VM_PAGER_ERROR; } diff --git a/sys/fs/smbfs/smbfs_io.c b/sys/fs/smbfs/smbfs_io.c index 7e021c1..c47fb1b 100644 --- a/sys/fs/smbfs/smbfs_io.c +++ b/sys/fs/smbfs/smbfs_io.c @@ -440,12 +440,15 @@ smbfs_getpages(ap) VM_OBJECT_LOCK(object); if (m->valid != 0) { - vm_page_lock_queues(); for (i = 0; i < npages; ++i) { - if (i != reqpage) + if (i != reqpage) { + vm_page_lock(pages[i]); + vm_page_lock_queues(); vm_page_free(pages[i]); + vm_page_unlock_queues(); + vm_page_unlock(pages[i]); + } } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return 0; } @@ -478,12 +481,15 @@ smbfs_getpages(ap) VM_OBJECT_LOCK(object); if (error && (uio.uio_resid == count)) { printf("smbfs_getpages: error %d\n",error); - vm_page_lock_queues(); for (i = 0; i < npages; i++) { - if (reqpage != i) + if (reqpage != i) { + vm_page_lock(pages[i]); + vm_page_lock_queues(); vm_page_free(pages[i]); + vm_page_unlock_queues(); + vm_page_unlock(pages[i]); + } } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return VM_PAGER_ERROR; } diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index bb92972..0ec9817 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -949,9 +949,11 @@ exec_map_first_page(imgp) ma[0] = vm_page_lookup(object, 0); if ((rv != VM_PAGER_OK) || (ma[0] == NULL)) { if (ma[0]) { + vm_page_lock(ma[0]); vm_page_lock_queues(); vm_page_free(ma[0]); vm_page_unlock_queues(); + vm_page_unlock(ma[0]); } VM_OBJECT_UNLOCK(object); return (EIO); diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c index 725b1a8..783a8d6 100644 --- a/sys/kern/subr_uio.c +++ b/sys/kern/subr_uio.c @@ -104,9 +104,11 @@ retry: if ((user_pg = vm_page_lookup(uobject, upindex)) != NULL) { if (vm_page_sleep_if_busy(user_pg, TRUE, "vm_pgmoveco")) goto retry; + vm_page_lock(user_pg); vm_page_lock_queues(); pmap_remove_all(user_pg); vm_page_free(user_pg); + vm_page_unlock(user_pg); } else { /* * Even if a physical page does not exist in the diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index 13effd0..c93d677 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -129,12 +129,15 @@ nfs_getpages(struct vop_getpages_args *ap) */ VM_OBJECT_LOCK(object); if (pages[ap->a_reqpage]->valid != 0) { - vm_page_lock_queues(); for (i = 0; i < npages; ++i) { - if (i != ap->a_reqpage) + if (i != ap->a_reqpage) { + vm_page_lock(pages[i]); + vm_page_lock_queues(); vm_page_free(pages[i]); + vm_page_unlock_queues(); + vm_page_unlock(pages[i]); + } } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return (0); } @@ -169,12 +172,15 @@ nfs_getpages(struct vop_getpages_args *ap) if (error && (uio.uio_resid == count)) { nfs_printf("nfs_getpages: error %d\n", error); VM_OBJECT_LOCK(object); - vm_page_lock_queues(); for (i = 0; i < npages; ++i) { - if (i != ap->a_reqpage) + if (i != ap->a_reqpage) { + vm_page_lock(pages[i]); + vm_page_lock_queues(); vm_page_free(pages[i]); + vm_page_unlock_queues(); + vm_page_unlock(pages[i]); + } } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(object); return (VM_PAGER_ERROR); } diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 85f8ffd..a2fee4e 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -847,13 +847,15 @@ ffs_getpages(ap) if (mreq->valid) { if (mreq->valid != VM_PAGE_BITS_ALL) vm_page_zero_invalid(mreq, TRUE); - vm_page_lock_queues(); for (i = 0; i < pcount; i++) { if (i != ap->a_reqpage) { + vm_page_lock(ap->a_m[i]); + vm_page_lock_queues(); vm_page_free(ap->a_m[i]); + vm_page_unlock_queues(); + vm_page_unlock(ap->a_m[i]); } } - vm_page_unlock_queues(); VM_OBJECT_UNLOCK(mreq->object); return VM_PAGER_OK; } diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 373433f..2978f7f 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -778,9 +778,7 @@ vnode_locked: * automatically made dirty. */ vm_page_lock(fs.m); - vm_page_lock_queues(); vm_page_rename(fs.m, fs.first_object, fs.first_pindex); - vm_page_unlock_queues(); vm_page_unlock(fs.m); vm_page_busy(fs.m); fs.first_m = fs.m; diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index b5f246c..f8c50bc 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1461,9 +1461,7 @@ retry: goto retry; } vm_page_lock(m); - vm_page_lock_queues(); vm_page_rename(m, new_object, idx); - vm_page_unlock_queues(); vm_page_unlock(m); /* page automatically made dirty by rename and cache handled */ vm_page_busy(m); @@ -1691,9 +1689,7 @@ vm_object_backing_scan(vm_object_t object, int op) * mapped through the rename. */ vm_page_lock(p); - vm_page_lock_queues(); vm_page_rename(p, object, new_pindex); - vm_page_unlock_queues(); vm_page_unlock(p); /* page automatically made dirty by rename */ } diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index a77dc13..cc34c1b 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -791,7 +791,7 @@ vm_page_remove(vm_page_t m) vm_page_t root; if ((m->flags & PG_UNMANAGED) == 0) - mtx_assert(&vm_page_queue_mtx, MA_OWNED); + vm_page_lock_assert(m, MA_OWNED); if ((object = m->object) == NULL) return; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); @@ -2234,11 +2234,11 @@ vm_page_cowfault(vm_page_t m) retry_alloc: pmap_remove_all(m); + vm_page_unlock_queues(); vm_page_remove(m); mnew = vm_page_alloc(object, pindex, VM_ALLOC_NORMAL | VM_ALLOC_NOBUSY); if (mnew == NULL) { vm_page_insert(m, object, pindex); - vm_page_unlock_queues(); vm_page_unlock(m); VM_OBJECT_UNLOCK(object); VM_WAIT; @@ -2261,7 +2261,12 @@ vm_page_cowfault(vm_page_t m) * waiting to allocate a page. If so, put things back * the way they were */ + vm_page_unlock(m); + vm_page_lock(mnew); + vm_page_lock_queues(); vm_page_free(mnew); + vm_page_unlock_queues(); + vm_page_unlock(mnew); vm_page_insert(m, object, pindex); } else { /* clear COW & copy page */ if (!so_zerocp_fullpage) @@ -2270,9 +2275,8 @@ vm_page_cowfault(vm_page_t m) vm_page_dirty(mnew); mnew->wire_count = m->wire_count - m->cow; m->wire_count = m->cow; + vm_page_unlock(m); } - vm_page_unlock_queues(); - vm_page_unlock(m); } void diff --git a/sys/vm/vm_page.h b/sys/vm/vm_page.h index 51a896f..da4d42a 100644 --- a/sys/vm/vm_page.h +++ b/sys/vm/vm_page.h @@ -103,7 +103,7 @@ struct vm_page { struct vm_page *left; /* splay tree link (O) */ struct vm_page *right; /* splay tree link (O) */ - vm_object_t object; /* which object am I in (O,Q)*/ + vm_object_t object; /* which object am I in (O,P)*/ vm_pindex_t pindex; /* offset into object (O,Q) */ vm_paddr_t phys_addr; /* physical address of page */ struct md_page md; /* machine dependant stuff */ -- cgit v1.1 From a0a9776a5cd835b11247f9190d1b1005b828c7ed Mon Sep 17 00:00:00 2001 From: mm Date: Wed, 5 May 2010 18:22:29 +0000 Subject: Introduce hardforce export option (-F) for "zpool export". When exporting with this flag, zpool.cache remains untouched. OpenSolaris onnv revision: 8211:32722be6ad3b Approved by: pjd, delphij (mentor) Obtained from: OpenSolaris (Bug ID: 6775357) --- cddl/contrib/opensolaris/cmd/zpool/zpool_main.c | 12 ++++++++++-- cddl/contrib/opensolaris/cmd/ztest/ztest.c | 2 +- cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h | 1 + .../opensolaris/lib/libzfs/common/libzfs_pool.c | 15 ++++++++++++++- .../contrib/opensolaris/uts/common/fs/zfs/spa.c | 21 +++++++++++++-------- .../contrib/opensolaris/uts/common/fs/zfs/sys/spa.h | 3 ++- .../opensolaris/uts/common/fs/zfs/zfs_ioctl.c | 3 ++- 7 files changed, 43 insertions(+), 14 deletions(-) diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c index 2970371..eef60e6 100644 --- a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c +++ b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c @@ -879,17 +879,21 @@ int zpool_do_export(int argc, char **argv) { boolean_t force = B_FALSE; + boolean_t hardforce = B_FALSE; int c; zpool_handle_t *zhp; int ret; int i; /* check options */ - while ((c = getopt(argc, argv, "f")) != -1) { + while ((c = getopt(argc, argv, "fF")) != -1) { switch (c) { case 'f': force = B_TRUE; break; + case 'F': + hardforce = B_TRUE; + break; case '?': (void) fprintf(stderr, gettext("invalid option '%c'\n"), optopt); @@ -919,8 +923,12 @@ zpool_do_export(int argc, char **argv) continue; } - if (zpool_export(zhp, force) != 0) + if (hardforce) { + if (zpool_export_force(zhp) != 0) + ret = 1; + } else if (zpool_export(zhp, force) != 0) { ret = 1; + } zpool_close(zhp); } diff --git a/cddl/contrib/opensolaris/cmd/ztest/ztest.c b/cddl/contrib/opensolaris/cmd/ztest/ztest.c index b7ca302..9744a0a 100644 --- a/cddl/contrib/opensolaris/cmd/ztest/ztest.c +++ b/cddl/contrib/opensolaris/cmd/ztest/ztest.c @@ -3039,7 +3039,7 @@ ztest_spa_import_export(char *oldname, char *newname) /* * Export it. */ - error = spa_export(oldname, &config, B_FALSE); + error = spa_export(oldname, &config, B_FALSE, B_FALSE); if (error) fatal(0, "spa_export('%s') = %d", oldname, error); diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h index a959494..a77317e 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h @@ -289,6 +289,7 @@ extern int zpool_get_errlog(zpool_handle_t *, nvlist_t **); * Import and export functions */ extern int zpool_export(zpool_handle_t *, boolean_t); +extern int zpool_export_force(zpool_handle_t *); extern int zpool_import(libzfs_handle_t *, nvlist_t *, const char *, char *altroot); extern int zpool_import_props(libzfs_handle_t *, nvlist_t *, const char *, diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c index c3cb547..0369062 100644 --- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c +++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c @@ -1096,7 +1096,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) * mounted datasets in the pool. */ int -zpool_export(zpool_handle_t *zhp, boolean_t force) +zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce) { zfs_cmd_t zc = { 0 }; char msg[1024]; @@ -1109,6 +1109,7 @@ zpool_export(zpool_handle_t *zhp, boolean_t force) (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); zc.zc_cookie = force; + zc.zc_guid = hardforce; if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) { switch (errno) { @@ -1129,6 +1130,18 @@ zpool_export(zpool_handle_t *zhp, boolean_t force) return (0); } +int +zpool_export(zpool_handle_t *zhp, boolean_t force) +{ + return (zpool_export_common(zhp, force, B_FALSE)); +} + +int +zpool_export_force(zpool_handle_t *zhp) +{ + return (zpool_export_common(zhp, B_TRUE, B_TRUE)); +} + /* * zpool_import() is a contracted interface. Should be kept the same * if possible. diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c index 90861ba..888b882 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c @@ -2564,11 +2564,12 @@ spa_tryimport(nvlist_t *tryconfig) * The act of destroying or exporting a pool is very simple. We make sure there * is no more pending I/O and any references to the pool are gone. Then, we * update the pool state and sync all the labels to disk, removing the - * configuration from the cache afterwards. + * configuration from the cache afterwards. If the 'hardforce' flag is set, then + * we don't sync the labels or remove the configuration cache. */ static int spa_export_common(char *pool, int new_state, nvlist_t **oldconfig, - boolean_t force) + boolean_t force, boolean_t hardforce) { spa_t *spa; @@ -2636,7 +2637,7 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig, * so mark them all dirty. spa_unload() will do the * final sync that pushes these changes out. */ - if (new_state != POOL_STATE_UNINITIALIZED) { + if (new_state != POOL_STATE_UNINITIALIZED && !hardforce) { spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER); spa->spa_state = new_state; spa->spa_final_txg = spa_last_synced_txg(spa) + 1; @@ -2656,7 +2657,8 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig, VERIFY(nvlist_dup(spa->spa_config, oldconfig, 0) == 0); if (new_state != POOL_STATE_UNINITIALIZED) { - spa_config_sync(spa, B_TRUE, B_TRUE); + if (!hardforce) + spa_config_sync(spa, B_TRUE, B_TRUE); spa_remove(spa); } mutex_exit(&spa_namespace_lock); @@ -2670,16 +2672,19 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig, int spa_destroy(char *pool) { - return (spa_export_common(pool, POOL_STATE_DESTROYED, NULL, B_FALSE)); + return (spa_export_common(pool, POOL_STATE_DESTROYED, NULL, + B_FALSE, B_FALSE)); } /* * Export a storage pool. */ int -spa_export(char *pool, nvlist_t **oldconfig, boolean_t force) +spa_export(char *pool, nvlist_t **oldconfig, boolean_t force, + boolean_t hardforce) { - return (spa_export_common(pool, POOL_STATE_EXPORTED, oldconfig, force)); + return (spa_export_common(pool, POOL_STATE_EXPORTED, oldconfig, + force, hardforce)); } /* @@ -2690,7 +2695,7 @@ int spa_reset(char *pool) { return (spa_export_common(pool, POOL_STATE_UNINITIALIZED, NULL, - B_FALSE)); + B_FALSE, B_FALSE)); } /* diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h index 99bcb91..b0b758b 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h @@ -333,7 +333,8 @@ extern int spa_import(const char *pool, nvlist_t *config, nvlist_t *props); extern int spa_import_faulted(const char *, nvlist_t *, nvlist_t *); extern nvlist_t *spa_tryimport(nvlist_t *tryconfig); extern int spa_destroy(char *pool); -extern int spa_export(char *pool, nvlist_t **oldconfig, boolean_t force); +extern int spa_export(char *pool, nvlist_t **oldconfig, boolean_t force, + boolean_t hardforce); extern int spa_reset(char *pool); extern void spa_async_request(spa_t *spa, int flag); extern void spa_async_unrequest(spa_t *spa, int flag); diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c index 1536e0b..c7bd8ad 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c @@ -882,9 +882,10 @@ zfs_ioc_pool_export(zfs_cmd_t *zc) { int error; boolean_t force = (boolean_t)zc->zc_cookie; + boolean_t hardforce = (boolean_t)zc->zc_guid; zfs_log_history(zc); - error = spa_export(zc->zc_name, NULL, force); + error = spa_export(zc->zc_name, NULL, force, hardforce); return (error); } -- cgit v1.1 From 70139e5fa64ec30ed27ed723699c17200d26adcd Mon Sep 17 00:00:00 2001 From: jh Date: Wed, 5 May 2010 18:53:24 +0000 Subject: Fix deadlock between GEOM class unloading and withering. Withering can't proceed while g_unload_class() blocks the event thread. Fix this by not running g_unload_class() as a GEOM event and dropping the topology lock when withering needs to proceed. PR: kern/139847 Silence on: freebsd-geom --- sys/geom/geom.h | 3 ++ sys/geom/geom_subr.c | 98 +++++++++++++++++++++++++++------------------------- 2 files changed, 54 insertions(+), 47 deletions(-) diff --git a/sys/geom/geom.h b/sys/geom/geom.h index 82d0456..fe18a15 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -353,6 +353,9 @@ g_free(void *ptr) sx_assert(&topology_lock, SX_UNLOCKED); \ } while (0) +#define g_topology_sleep(chan, timo) \ + sx_sleep(chan, &topology_lock, 0, "gtopol", timo) + #define DECLARE_GEOM_CLASS(class, name) \ static moduledata_t name##_mod = { \ #name, g_modevent, &class \ diff --git a/sys/geom/geom_subr.c b/sys/geom/geom_subr.c index 772277e..b001c5f 100644 --- a/sys/geom/geom_subr.c +++ b/sys/geom/geom_subr.c @@ -134,65 +134,73 @@ g_load_class(void *arg, int flag) } } -static void -g_unload_class(void *arg, int flag) +static int +g_unload_class(struct g_class *mp) { - struct g_hh00 *hh; - struct g_class *mp; struct g_geom *gp; struct g_provider *pp; struct g_consumer *cp; int error; - g_topology_assert(); - hh = arg; - mp = hh->mp; - G_VALID_CLASS(mp); + g_topology_lock(); g_trace(G_T_TOPOLOGY, "g_unload_class(%s)", mp->name); - - /* - * We allow unloading if we have no geoms, or a class - * method we can use to get rid of them. - */ - if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) { - hh->error = EOPNOTSUPP; - return; - } - - /* We refuse to unload if anything is open */ +retry: + G_VALID_CLASS(mp); LIST_FOREACH(gp, &mp->geom, geom) { + /* We refuse to unload if anything is open */ LIST_FOREACH(pp, &gp->provider, provider) if (pp->acr || pp->acw || pp->ace) { - hh->error = EBUSY; - return; + g_topology_unlock(); + return (EBUSY); } LIST_FOREACH(cp, &gp->consumer, consumer) if (cp->acr || cp->acw || cp->ace) { - hh->error = EBUSY; - return; + g_topology_unlock(); + return (EBUSY); } + /* If the geom is withering, wait for it to finish. */ + if (gp->flags & G_GEOM_WITHER) { + g_topology_sleep(mp, 1); + goto retry; + } + } + + /* + * We allow unloading if we have no geoms, or a class + * method we can use to get rid of them. + */ + if (!LIST_EMPTY(&mp->geom) && mp->destroy_geom == NULL) { + g_topology_unlock(); + return (EOPNOTSUPP); } /* Bar new entries */ mp->taste = NULL; mp->config = NULL; - error = 0; + LIST_FOREACH(gp, &mp->geom, geom) { + error = mp->destroy_geom(NULL, mp, gp); + if (error != 0) { + g_topology_unlock(); + return (error); + } + } + /* Wait for withering to finish. */ for (;;) { gp = LIST_FIRST(&mp->geom); if (gp == NULL) break; - error = mp->destroy_geom(NULL, mp, gp); - if (error != 0) - break; + KASSERT(gp->flags & G_GEOM_WITHER, + ("Non-withering geom in class %s", mp->name)); + g_topology_sleep(mp, 1); } - if (error == 0) { - if (mp->fini != NULL) - mp->fini(mp); - LIST_REMOVE(mp, class); - } - hh->error = error; - return; + G_VALID_CLASS(mp); + if (mp->fini != NULL) + mp->fini(mp); + LIST_REMOVE(mp, class); + g_topology_unlock(); + + return (0); } int @@ -213,12 +221,12 @@ g_modevent(module_t mod, int type, void *data) g_ignition++; g_init(); } - hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); - hh->mp = data; error = EOPNOTSUPP; switch (type) { case MOD_LOAD: - g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", hh->mp->name); + g_trace(G_T_TOPOLOGY, "g_modevent(%s, LOAD)", mp->name); + hh = g_malloc(sizeof *hh, M_WAITOK | M_ZERO); + hh->mp = mp; /* * Once the system is not cold, MOD_LOAD calls will be * from the userland and the g_event thread will be able @@ -236,18 +244,14 @@ g_modevent(module_t mod, int type, void *data) } break; case MOD_UNLOAD: - g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", hh->mp->name); - error = g_waitfor_event(g_unload_class, hh, M_WAITOK, NULL); - if (error == 0) - error = hh->error; + g_trace(G_T_TOPOLOGY, "g_modevent(%s, UNLOAD)", mp->name); + DROP_GIANT(); + error = g_unload_class(mp); + PICKUP_GIANT(); if (error == 0) { - KASSERT(LIST_EMPTY(&hh->mp->geom), - ("Unloaded class (%s) still has geom", hh->mp->name)); + KASSERT(LIST_EMPTY(&mp->geom), + ("Unloaded class (%s) still has geom", mp->name)); } - g_free(hh); - break; - default: - g_free(hh); break; } return (error); -- cgit v1.1 -- cgit v1.1 From c8dfd5c0cb853b1ac3f30e4c150522cd84121361 Mon Sep 17 00:00:00 2001 From: joel Date: Wed, 5 May 2010 20:39:02 +0000 Subject: Switch to our preferred 2-clause BSD license. Approved by: kmacy --- sys/amd64/include/xen/xenfunc.h | 31 ++++++++++++++-------------- sys/amd64/include/xen/xenvar.h | 26 +++++++++++------------- sys/dev/cxgb/sys/mvec.h | 42 ++++++++++++++++++-------------------- sys/dev/cxgb/sys/uipc_mvec.c | 44 ++++++++++++++++++---------------------- sys/dev/xen/netfront/netfront.c | 32 ++++++++++++++++++----------- sys/i386/include/xen/xenfunc.h | 29 ++++++++++++-------------- sys/i386/include/xen/xenvar.h | 27 ++++++++++++------------- sys/kern/subr_bufring.c | 45 +++++++++++++++++++---------------------- sys/sys/buf_ring.h | 42 ++++++++++++++++++-------------------- 9 files changed, 154 insertions(+), 164 deletions(-) diff --git a/sys/amd64/include/xen/xenfunc.h b/sys/amd64/include/xen/xenfunc.h index b3a6672..d03d4f6 100644 --- a/sys/amd64/include/xen/xenfunc.h +++ b/sys/amd64/include/xen/xenfunc.h @@ -1,6 +1,5 @@ -/* - * - * Copyright (c) 2004,2005 Kip Macy +/*- + * Copyright (c) 2004, 2005 Kip Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,22 +10,22 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ */ - #ifndef _XEN_XENFUNC_H_ #define _XEN_XENFUNC_H_ diff --git a/sys/amd64/include/xen/xenvar.h b/sys/amd64/include/xen/xenvar.h index 1433b76..d9dbc5d 100644 --- a/sys/amd64/include/xen/xenvar.h +++ b/sys/amd64/include/xen/xenvar.h @@ -1,29 +1,27 @@ -/* +/*- * Copyright (c) 2008 Kip Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * * $FreeBSD$ */ diff --git a/sys/dev/cxgb/sys/mvec.h b/sys/dev/cxgb/sys/mvec.h index ed38dca..9db27dd 100644 --- a/sys/dev/cxgb/sys/mvec.h +++ b/sys/dev/cxgb/sys/mvec.h @@ -1,33 +1,31 @@ -/************************************************************************** - * - * Copyright (c) 2007,2009 Kip Macy kmacy@freebsd.org +/*- + * Copyright (c) 2007, 2009 Kip Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. The name of Kip Macy nor the names of other - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * * $FreeBSD$ * - ***************************************************************************/ + */ #ifndef _MVEC_H_ #define _MVEC_H_ diff --git a/sys/dev/cxgb/sys/uipc_mvec.c b/sys/dev/cxgb/sys/uipc_mvec.c index 4e494eb..f52daa6 100644 --- a/sys/dev/cxgb/sys/uipc_mvec.c +++ b/sys/dev/cxgb/sys/uipc_mvec.c @@ -1,32 +1,28 @@ -/************************************************************************** - * - * Copyright (c) 2007-2008, Kip Macy kmacy@freebsd.org +/*- + * Copyright (c) 2007-2008 Kip Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. The name of Kip Macy nor the names of other - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - ***************************************************************************/ + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ #include __FBSDID("$FreeBSD$"); diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c index d67d354..15cf455 100644 --- a/sys/dev/xen/netfront/netfront.c +++ b/sys/dev/xen/netfront/netfront.c @@ -1,19 +1,27 @@ -/* - * +/*- * Copyright (c) 2004-2006 Kip Macy * All rights reserved. * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ diff --git a/sys/i386/include/xen/xenfunc.h b/sys/i386/include/xen/xenfunc.h index 2851709..47f0405 100644 --- a/sys/i386/include/xen/xenfunc.h +++ b/sys/i386/include/xen/xenfunc.h @@ -1,6 +1,5 @@ -/* - * - * Copyright (c) 2004,2005 Kip Macy +/*- + * Copyright (c) 2004, 2005 Kip Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -11,24 +10,22 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * * $FreeBSD$ */ - #ifndef _XEN_XENFUNC_H_ #define _XEN_XENFUNC_H_ diff --git a/sys/i386/include/xen/xenvar.h b/sys/i386/include/xen/xenvar.h index cefbb05..1110f85 100644 --- a/sys/i386/include/xen/xenvar.h +++ b/sys/i386/include/xen/xenvar.h @@ -1,32 +1,31 @@ -/* +/*- * Copyright (c) 2008 Kip Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. - * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * * $FreeBSD$ */ + #ifndef XENVAR_H_ #define XENVAR_H_ #define XBOOTUP 0x1 diff --git a/sys/kern/subr_bufring.c b/sys/kern/subr_bufring.c index 63938ea..4cd3929 100644 --- a/sys/kern/subr_bufring.c +++ b/sys/kern/subr_bufring.c @@ -1,32 +1,29 @@ -/************************************************************************** - * - * Copyright (c) 2007,2008 Kip Macy kmacy@freebsd.org +/*- + * Copyright (c) 2007, 2008 Kip Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. The name of Kip Macy nor the names of other - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * - ***************************************************************************/ + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + #include __FBSDID("$FreeBSD$"); diff --git a/sys/sys/buf_ring.h b/sys/sys/buf_ring.h index efa667d..57e42e5 100644 --- a/sys/sys/buf_ring.h +++ b/sys/sys/buf_ring.h @@ -1,33 +1,31 @@ -/************************************************************************** - * - * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org +/*- + * Copyright (c) 2007-2009 Kip Macy * All rights reserved. * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. * - * 2. The name of Kip Macy nor the names of other - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. * * $FreeBSD$ * - ***************************************************************************/ + */ #ifndef _SYS_BUF_RING_H_ #define _SYS_BUF_RING_H_ -- cgit v1.1 From 9e7ca00a7d2a09aaf3de24d5ccf18e1a4d305e75 Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 5 May 2010 21:07:47 +0000 Subject: Add definitions for Intel AESNI CPUID bits and print the capabilities on boot. Hardware provided by: Sentex Communications MFC after: 1 week --- sys/amd64/amd64/identcpu.c | 4 ++-- sys/amd64/include/specialreg.h | 2 ++ sys/i386/i386/identcpu.c | 4 ++-- sys/i386/include/specialreg.h | 2 ++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c index c23102a..52e7568 100644 --- a/sys/amd64/amd64/identcpu.c +++ b/sys/amd64/amd64/identcpu.c @@ -240,7 +240,7 @@ printcpuinfo(void) printf("\n Features2=0x%b", cpu_feature2, "\020" "\001SSE3" /* SSE3 */ - "\002" + "\002PCLMULQDQ" /* Carry-Less Mul Quadword */ "\003DTES64" /* 64-bit Debug Trace */ "\004MON" /* MONITOR/MWAIT Instructions */ "\005DS_CPL" /* CPL Qualified Debug Store */ @@ -264,7 +264,7 @@ printcpuinfo(void) "\027MOVBE" "\030POPCNT" "\031" - "\032" + "\032AESNI" /* AES Crypto*/ "\033XSAVE" "\034OSXSAVE" "\035" diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h index 86a08ce..895619c 100644 --- a/sys/amd64/include/specialreg.h +++ b/sys/amd64/include/specialreg.h @@ -113,6 +113,7 @@ #define CPUID_PBE 0x80000000 #define CPUID2_SSE3 0x00000001 +#define CPUID2_PCLMULQDQ 0x00000002 #define CPUID2_DTES64 0x00000004 #define CPUID2_MON 0x00000008 #define CPUID2_DS_CPL 0x00000010 @@ -131,6 +132,7 @@ #define CPUID2_X2APIC 0x00200000 #define CPUID2_MOVBE 0x00400000 #define CPUID2_POPCNT 0x00800000 +#define CPUID2_AESNI 0x02000000 /* * Important bits in the AMD extended cpuid flags diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c index 931bfaf..6f2e4a4 100644 --- a/sys/i386/i386/identcpu.c +++ b/sys/i386/i386/identcpu.c @@ -727,7 +727,7 @@ printcpuinfo(void) printf("\n Features2=0x%b", cpu_feature2, "\020" "\001SSE3" /* SSE3 */ - "\002" + "\002PCLMULQDQ" /* Carry-Less Mul Quadword */ "\003DTES64" /* 64-bit Debug Trace */ "\004MON" /* MONITOR/MWAIT Instructions */ "\005DS_CPL" /* CPL Qualified Debug Store */ @@ -751,7 +751,7 @@ printcpuinfo(void) "\027MOVBE" "\030POPCNT" "\031" - "\032" + "\032AESNI" /* AES Crypto*/ "\033XSAVE" "\034OSXSAVE" "\035" diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h index d2494c7..efcf924 100644 --- a/sys/i386/include/specialreg.h +++ b/sys/i386/include/specialreg.h @@ -110,6 +110,7 @@ #define CPUID_PBE 0x80000000 #define CPUID2_SSE3 0x00000001 +#define CPUID2_PCLMULQDQ 0x00000002 #define CPUID2_DTES64 0x00000004 #define CPUID2_MON 0x00000008 #define CPUID2_DS_CPL 0x00000010 @@ -128,6 +129,7 @@ #define CPUID2_X2APIC 0x00200000 #define CPUID2_MOVBE 0x00400000 #define CPUID2_POPCNT 0x00800000 +#define CPUID2_AESNI 0x02000000 /* * Important bits in the AMD extended cpuid flags -- cgit v1.1 From a5718881d81033624f276036560f07f69ceac0cc Mon Sep 17 00:00:00 2001 From: delphij Date: Wed, 5 May 2010 21:24:18 +0000 Subject: Move SCCS tags to comments as they were already #if 0'ed. --- usr.bin/find/find.c | 9 ++------- usr.bin/find/function.c | 8 ++------ usr.bin/find/ls.c | 8 ++------ usr.bin/find/main.c | 8 ++------ usr.bin/find/misc.c | 9 ++------- usr.bin/find/operator.c | 8 ++------ usr.bin/find/option.c | 8 ++------ 7 files changed, 14 insertions(+), 44 deletions(-) diff --git a/usr.bin/find/find.c b/usr.bin/find/find.c index cc2d797..35ef5b2 100644 --- a/usr.bin/find/find.c +++ b/usr.bin/find/find.c @@ -32,15 +32,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * @(#)find.c 8.5 (Berkeley) 8/5/94 */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)find.c 8.5 (Berkeley) 8/5/94"; -#else -#endif -#endif /* not lint */ - #include __FBSDID("$FreeBSD$"); diff --git a/usr.bin/find/function.c b/usr.bin/find/function.c index 1714627..4329887 100644 --- a/usr.bin/find/function.c +++ b/usr.bin/find/function.c @@ -32,14 +32,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * @(#)function.c 8.10 (Berkeley) 5/4/95 */ -#ifndef lint -#if 0 -static const char sccsid[] = "@(#)function.c 8.10 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ - #include __FBSDID("$FreeBSD$"); diff --git a/usr.bin/find/ls.c b/usr.bin/find/ls.c index 88e4593..e96994b 100644 --- a/usr.bin/find/ls.c +++ b/usr.bin/find/ls.c @@ -29,14 +29,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * @(#)ls.c 8.1 (Berkeley) 6/6/93 */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)ls.c 8.1 (Berkeley) 6/6/93"; -#endif -#endif /* not lint */ - #include __FBSDID("$FreeBSD$"); diff --git a/usr.bin/find/main.c b/usr.bin/find/main.c index 8e2b42c..7d4c24a 100644 --- a/usr.bin/find/main.c +++ b/usr.bin/find/main.c @@ -32,6 +32,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * @(#)main.c 8.4 (Berkeley) 5/4/95 */ #ifndef lint @@ -40,12 +42,6 @@ char copyright[] = The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 5/4/95"; -#endif -#endif /* not lint */ - #include __FBSDID("$FreeBSD$"); diff --git a/usr.bin/find/misc.c b/usr.bin/find/misc.c index 1532906..3696c13 100644 --- a/usr.bin/find/misc.c +++ b/usr.bin/find/misc.c @@ -32,15 +32,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * @(#)misc.c 8.2 (Berkeley) 4/1/94 */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)misc.c 8.2 (Berkeley) 4/1/94"; -#else -#endif -#endif /* not lint */ - #include __FBSDID("$FreeBSD$"); diff --git a/usr.bin/find/operator.c b/usr.bin/find/operator.c index c774efa..d1a7ea8 100644 --- a/usr.bin/find/operator.c +++ b/usr.bin/find/operator.c @@ -32,14 +32,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * @(#)operator.c 8.1 (Berkeley) 6/6/93 */ -#ifndef lint -#if 0 -static char sccsid[] = "@(#)operator.c 8.1 (Berkeley) 6/6/93"; -#endif -#endif /* not lint */ - #include __FBSDID("$FreeBSD$"); diff --git a/usr.bin/find/option.c b/usr.bin/find/option.c index 7d06c91..6ae3958 100644 --- a/usr.bin/find/option.c +++ b/usr.bin/find/option.c @@ -32,14 +32,10 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * @(#)option.c 8.2 (Berkeley) 4/16/94 */ -#ifndef lint -/* -static char sccsid[] = "@(#)option.c 8.2 (Berkeley) 4/16/94"; -*/ -#endif /* not lint */ - #include __FBSDID("$FreeBSD$"); -- cgit v1.1 From f3856c6cf2fb115757967b7e32bdeb21bd27d1ee Mon Sep 17 00:00:00 2001 From: jilles Date: Wed, 5 May 2010 21:48:40 +0000 Subject: sh: Apply locale vars on builtins, recognize LC_MESSAGES as a locale var. This allows doing things like LC_ALL=C some_builtin to run a builtin under a different locale, just like is possible with external programs. The immediate reason is that this allows making printf(1) a builtin without breaking things like LC_NUMERIC=C printf '%f\n' 1.2 This change also affects special builtins, as even though the assignment is persistent, the export is only to the builtin (unless the variable was already exported). Note: for this to work for builtins that also exist as external programs such as /bin/test, the setlocale() call must be under #ifndef SHELL. The shell will do the setlocale() calls which may not agree with the environment variables. --- bin/sh/eval.c | 4 + bin/sh/var.c | 75 ++++++++++++++-- bin/sh/var.h | 2 + tools/regression/bin/sh/builtins/locale1.0 | 133 +++++++++++++++++++++++++++++ 4 files changed, 207 insertions(+), 7 deletions(-) create mode 100644 tools/regression/bin/sh/builtins/locale1.0 diff --git a/bin/sh/eval.c b/bin/sh/eval.c index e93fb14..c4495d0 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -937,6 +937,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) cmdentry.special = 1; if (cmdentry.special) listsetvar(cmdenviron); + if (argc > 0) + bltinsetlocale(); commandname = argv[0]; argptr = argv + 1; nextopt_optptr = NULL; /* initialize nextopt */ @@ -944,6 +946,8 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); flushall(); cmddone: + if (argc > 0) + bltinunsetlocale(); cmdenviron = NULL; out1 = &output; out2 = &errout; diff --git a/bin/sh/var.c b/bin/sh/var.c index d46e2c3..75de239 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -122,6 +122,14 @@ STATIC const struct varinit varinit[] = { STATIC struct var *vartab[VTABSIZE]; +STATIC const char *const locale_names[7] = { + "LC_COLLATE", "LC_CTYPE", "LC_MONETARY", + "LC_NUMERIC", "LC_TIME", "LC_MESSAGES", NULL +}; +STATIC const int locale_categories[7] = { + LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME, LC_MESSAGES, 0 +}; + STATIC struct var **hashvar(const char *); STATIC int varequal(const char *, const char *); STATIC int localevar(const char *); @@ -258,11 +266,7 @@ setvar(const char *name, const char *val, int flags) STATIC int localevar(const char *s) { - static const char *lnames[7] = { - "ALL", "COLLATE", "CTYPE", "MONETARY", - "NUMERIC", "TIME", NULL - }; - const char **ss; + const char *const *ss; if (*s != 'L') return 0; @@ -270,8 +274,10 @@ localevar(const char *s) return 1; if (strncmp(s + 1, "C_", 2) != 0) return 0; - for (ss = lnames; *ss ; ss++) - if (varequal(s + 3, *ss)) + if (varequal(s + 3, "ALL")) + return 1; + for (ss = locale_names; *ss ; ss++) + if (varequal(s + 3, *ss + 3)) return 1; return 0; } @@ -437,6 +443,61 @@ bltinlookup(const char *name, int doall) } +/* + * Set up locale for a builtin (LANG/LC_* assignments). + */ +void +bltinsetlocale(void) +{ + struct strlist *lp; + int act = 0; + char *loc, *locdef; + int i; + + for (lp = cmdenviron ; lp ; lp = lp->next) { + if (localevar(lp->text)) { + act = 1; + break; + } + } + if (!act) + return; + loc = bltinlookup("LC_ALL", 0); + INTOFF; + if (loc != NULL) { + setlocale(LC_ALL, loc); + INTON; + return; + } + locdef = bltinlookup("LANG", 0); + for (i = 0; locale_names[i] != NULL; i++) { + loc = bltinlookup(locale_names[i], 0); + if (loc == NULL) + loc = locdef; + if (loc != NULL) + setlocale(locale_categories[i], loc); + } + INTON; +} + +/* + * Undo the effect of bltinlocaleset(). + */ +void +bltinunsetlocale(void) +{ + struct strlist *lp; + + INTOFF; + for (lp = cmdenviron ; lp ; lp = lp->next) { + if (localevar(lp->text)) { + setlocale(LC_ALL, ""); + return; + } + } + INTON; +} + /* * Generate a list of exported variables. This routine is used to construct diff --git a/bin/sh/var.h b/bin/sh/var.h index 9c792c8..6a02630 100644 --- a/bin/sh/var.h +++ b/bin/sh/var.h @@ -107,6 +107,8 @@ struct strlist; void listsetvar(struct strlist *); char *lookupvar(const char *); char *bltinlookup(const char *, int); +void bltinsetlocale(void); +void bltinunsetlocale(void); char **environment(void); int showvarscmd(int, char **); int exportcmd(int, char **); diff --git a/tools/regression/bin/sh/builtins/locale1.0 b/tools/regression/bin/sh/builtins/locale1.0 new file mode 100644 index 0000000..93a37df --- /dev/null +++ b/tools/regression/bin/sh/builtins/locale1.0 @@ -0,0 +1,133 @@ +# $FreeBSD$ +# Note: this test depends on strerror() using locale. + +failures=0 + +check() { + if ! eval "[ $1 ]"; then + echo "Failed: $1 at $2" + : $((failures += 1)) + fi +} + +unset LANG LC_ALL LC_COLLATE LC_CTYPE LC_MONETARY LC_NUMERIC LC_TIME LC_MESSAGES + +msgeng="No such file or directory" +msgdut="Bestand of map niet gevonden" + +# Verify C locale error message. +case $(command . /var/empty/foo 2>&1) in + *"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +# Various locale variables that should not affect the message. +case $(LC_ALL=C command . /var/empty/foo 2>&1) in + *"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LC_ALL=C LANG=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in + *"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LC_ALL=C LC_MESSAGES=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in + *"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LC_CTYPE=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in + *"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +# Verify Dutch message. +case $(export LANG=nl_NL.ISO8859-1; command . /var/empty/foo 2>&1) in + *"$msgdut"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(export LC_MESSAGES=nl_NL.ISO8859-1; command . /var/empty/foo 2>&1) in + *"$msgdut"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(export LC_ALL=nl_NL.ISO8859-1; command . /var/empty/foo 2>&1) in + *"$msgdut"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LANG=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in + *"$msgdut"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LC_MESSAGES=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in + *"$msgdut"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LC_ALL=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1) in + *"$msgdut"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +# Verify that command assignments do not set the locale persistently. +case $(command . /var/empty/foo 2>&1) in + *"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LANG=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1; command . /var/empty/foo 2>&1) in + *"$msgdut"*"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LC_MESSAGES=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1; command . /var/empty/foo 2>&1) in + *"$msgdut"*"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(LC_ALL=nl_NL.ISO8859-1 command . /var/empty/foo 2>&1; command . /var/empty/foo 2>&1) in + *"$msgdut"*"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +# Check special builtin; add colon invocation to avoid depending on certain fix. +case $(LC_ALL=nl_NL.ISO8859-1 . /var/empty/foo 2>&1; :) in + *"$msgdut"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +# Assignments on special builtins are exported to that builtin; the export +# is not persistent. +case $(LC_ALL=nl_NL.ISO8859-1 . /dev/null; . /var/empty/foo 2>&1) in + *"$msgeng"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +case $(export LC_ALL; LC_ALL=nl_NL.ISO8859-1 . /dev/null; . /var/empty/foo 2>&1) in + *"$msgdut"*) ok=1 ;; + *) ok=0 ;; +esac +check '$ok -eq 1' $LINENO + +exit $((failures > 0)) -- cgit v1.1