loApicIntr.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:20k
源码类别:
VxWorks
开发平台:
C/C++
- /* loApicIntr.c - Intel Pentium[234] Local APIC/xAPIC driver */
- /* Copyright 1984-2002 Wind River Systems, Inc. */
- #include "copyright_wrs.h"
- /*
- modification history
- --------------------
- 01f,15may02,hdn changed apicId 8 bit to 16 bit, added DBG_MSG.
- added Error Status Register checking
- 01e,08mar02,hdn updated loApicInit() and loApicIpi()
- added loApicEnable() for HTT (spr 73738)
- 01d,29nov01,hdn doc update for 5.5
- 01c,21jun01,hdn added support for Pentium4 Local xAPIC
- moved show routines to loApicIntrShow.c
- 01b,25mar98,hdn re-written.
- 01a,20jun97,sub written.
- */
- /*
- DESCRIPTION
- This module is a driver for the local APIC/xAPIC (Advanced Programmable
- Interrupt Controller) in P6 (PentiumPro, II, III) family processors
- and P7 (Pentium4) family processors. The local APIC/xAPIC is included
- in selected P6 (PentiumPro, II, III) and P7 (Pentium4) family processors.
- Beginning with the P6 family processors, the presence or absence of an
- on-chip local APIC can be detected using the CPUID instruction. When the
- CPUID instruction is executed, bit 9 of the feature flags returned in the
- EDX register indicates the presence (set) or absence (clear) of an on-chip
- local APIC.
- The local APIC performs two main functions for the processor:
- - It processes local external interrupts that the processor receives at its
- interrupt pins and local internal interrupts that software generates.
- - In multiple-processor systems, it communicates with an external IO APIC
- chip. The external IO APIC receives external interrupt events from the
- system and interprocessor interrupts from the processors on the system bus
- and distributes them to the processors on the system bus. The IO APIC is
- part of Intel's system chip set.
- The local APIC controls the dispatching of interrupts (to its associated
- processor) that it receives either locally or from the IO APIC. It provides
- facilities for queuing, nesting and masking of interrupts. It handles the
- interrupt delivery protocol with its local processor and accesses to APIC
- registers, and also manages interprocessor interrupts and remote APIC register
- reads. A timer on the local APIC allows local generation of interrupts, and
- local interrupt pins permit local reception of processor-specific interrupts.
- The local APIC can be disabled and used in conjunction with a standard 8259A
- style interrupt controller. Disabling the local APIC can be done in hardware
- for the Pentium processors or in software for the P6 and P7 (Pentium4) family
- processors.
- The local APIC in the Pentium4 processors (called the xAPIC) is an extension
- of the local APIC found in the P6 family processors. The primary difference
- between the APIC architecture and xAPIC architecture is that with Pentium4
- processors, the local xAPICs and IO xAPIC communicate with one another through
- the processors system bus; whereas, with the P6 family processors, communication
- between the local APICs and the IO APIC is handled through a dedicated 3-wire
- APIC bus. Also, some of the architectural features of the local APIC have been
- extended and/or modified in the local xAPIC.
- The base address of the local APIC and IO APIC is taken from the MP configuration
- table (see Intel MP Specification Version 1.4) or the IA32_APIC_BASE MSR.
- It uses LOAPIC_BASE and IOAPIC_INDEX_BASE defined in the BSP, if it is not able
- to find the addresses. This driver contains three routines for use. They are:
- loApicInit() initializes the Local APIC for the interrupt mode chosen.
- loApicEnable() enables or disables the Local APIC.
- loApicIpi() delivers the inter processor interrupt to the specified local APIC.
- Local APIC is used in the Virtual Wire Mode (define VIRTUAL_WIRE_MODE in the
- BSP) and the Symmetric IO Mode (define SYMMETRIC_IO_MODE in the BSP), but not
- in the PIC Mode which is the default interrupt mode and uses 8259A PIC.
- Virtual Wire Mode is one of three interrupt modes defined by the MP
- specification. In this mode, interrupts are generated by the 8259A equivalent
- PICs, but delivered to the Boot Strap Processor by the local APIC that is
- programmed to act as a "virtual Wire"; that is, the local APIC is logically
- indistinguishable from a hardware connection. This is a uniprocessor
- compatibility mode.
- Symmetric IO Mode is one of three interrupt modes defined by the MP
- specification. In this mode, the local and IO APICs are fully functional,
- and interrupts are generated and delivered to the processors by the APICs.
- Any interrupt can be delivered to any processor. This is the only
- multiprocessor interrupt mode.
- The local and IO APICs support interrupts in the range of 32 to 255.
- Interrupt priority is implied by its vector, according to the following
- relationship: "priority = vector / 16".
- Here the quotient is rounded down to the nearest integer value to determine
- the priority, with 1 being the lowest and 15 is the highest. Because vectors
- 0 through 31 are reserved for exclusive use by the processor, the priority of
- user defined interrupts range from 2 to 15. A value of 15 in the Interrupt
- Class field of the Task Priority Register (TPR) will mask off all interrupts,
- which require interrupt service.
- The P6 family processor's local APIC includes an in-service entry and a holding
- entry for each priority level. To avoid losing interrupts, software should
- allocate no more than 2 interrupt vectors per priority. The Pentium4 processor
- expands this support of all acceptance of two interrupts per vector rather than
- per priority level.
- INCLUDE FILES: loApic.h
- */
- /* includes */
- #include "drv/intrCtl/loApic.h"
- /* defines */
- #define LOAPIC_DBG
- #ifdef LOAPIC_DBG
- # define LOAPIC_DBG_MSG(STR,VALUE) logMsg(STR,VALUE,0,0,0,0,0);
- #else
- # define LOAPIC_DBG_MSG(STR,VALUE)
- #endif /* IPI_DEBUG */
- /* externs */
- IMPORT CPUID sysCpuId; /* CPUID structure */
- IMPORT UINT sysProcessor; /* CPU family */
- IMPORT BOOL sysBp; /* TRUE(default) for BP, FALSE for AP */
- /* globals */
- UINT32 loApicBase = LOAPIC_BASE; /* def Local APIC addr */
- UINT32 ioApicBase = IOAPIC_INDEX_BASE; /* def IO APIC select (index) addr */
- UINT32 ioApicData = IOAPIC_DATA_BASE; /* def IO APIC window (data) addr */
- UINT32 loApicId; /* local APIC Id */
- UINT32 loApicVersion; /* local APIC Version */
- UINT32 loApicMaxLvt; /* local APIC Max LVT */
- UINT32 loApicBusy = 0; /* counter for not sending IPI */
- UINT32 loApicNcpu = 0; /* number of CPUs (MP Table) */
- UINT32 loApicNioApic = 0; /* number of IO APICs (MP Table) */
- BOOL loApicImcr = FALSE; /* TRUE if IMCR exist (MP Table) */
- /* locals */
- LOCAL UINT32 sysIntMaskLocalApic = 0;
- LOCAL UINT32 loApicOldSvr = 0; /* original SVR */
- LOCAL UINT32 loApicOldLint0 = 0; /* original LINT0 */
- LOCAL UINT32 loApicOldLint1 = 0; /* original LINT1 */
- /* forward declarations */
- LOCAL void loApicIntEoi (INT32 irq);
- LOCAL STATUS loApicMpConfigTableInit (void);
- LOCAL INT8 * loApicMpScan (INT8 * start, INT8 * end);
- /*******************************************************************************
- *
- * loApicInit - initialize the Local APIC or xAPIC
- *
- * This routine initializes Local APIC or xAPIC.
- *
- * RETURNS: N/A
- *
- */
- void loApicInit (void)
- {
- UINT32 apicBase[2];
- /* override loApicBase from the MP Config Table */
- (void) loApicMpConfigTableInit ();
- /* override loApicBase, sysBp from MSR if available */
- if (sysCpuId.featuresEdx & CPUID_APIC)
- {
- pentiumMsrGet (IA32_APIC_BASE, (long long int *)&apicBase);
- loApicBase = apicBase[0] & LOAPIC_BASE_MASK; /* override */
- sysBp = apicBase[0] & LOAPIC_BSP ? TRUE : FALSE; /* override */
- /* enable the Local APIC explicitly */
- apicBase[0] |= LOAPIC_GLOBAL_ENABLE; /* set E(nable) bit */
- pentiumMsrSet (IA32_APIC_BASE, (long long int *)&apicBase);
- }
- /* remember the original state : SVR, LINT0, LINT1 for now */
- loApicOldSvr = *(int *)(loApicBase + LOAPIC_SVR);
- loApicOldLint0 = *(int *)(loApicBase + LOAPIC_LINT0);
- loApicOldLint1 = *(int *)(loApicBase + LOAPIC_LINT1);
- /* enable the Local APIC */
- loApicEnable (TRUE);
- *(int *)(loApicBase + LOAPIC_SVR) |= LOAPIC_FOCUS_DISABLE |
- INT_NUM_LOAPIC_SPURIOUS;
- /* get the Local APIC ID from Local APIC ID register */
- loApicId = (*(int *)(loApicBase + LOAPIC_ID) & LOAPIC_ID_MASK) >> 24;
- /* get the Local APIC Version from Local APIC Version register */
- loApicVersion = *(int *)(loApicBase + LOAPIC_VER) & LOAPIC_VERSION_MASK;
- loApicMaxLvt = (*(int *)(loApicBase + LOAPIC_VER) & LOAPIC_MAXLVT_MASK)
- >> 16;
- /* reset the DFR, TPR, TIMER_CONFIG, and TIMER_ICR */
- *(int *)(loApicBase + LOAPIC_DFR) = 0xffffffff;
- *(int *)(loApicBase + LOAPIC_TPR) = 0x0;
- *(int *)(loApicBase + LOAPIC_TIMER_CONFIG) = 0x0;
- *(int *)(loApicBase + LOAPIC_TIMER_ICR) = 0x0;
- #if defined(VIRTUAL_WIRE_MODE)
- /* program Local Vector Table for the Virtual Wire Mode */
- if (sysBp)
- {
- /* set LINT0: extInt, high-polarity, edge-trigger, not-masked */
- *(int *)(loApicBase + LOAPIC_LINT0) =
- (*(int *)(loApicBase + LOAPIC_LINT0) &
- ~(LOAPIC_MODE | LOAPIC_LOW | LOAPIC_LEVEL | LOAPIC_MASK)) |
- (LOAPIC_EXT | LOAPIC_HIGH | LOAPIC_EDGE);
- /* set LINT1: NMI, high-polarity, edge-trigger, not-masked */
- *(int *)(loApicBase + LOAPIC_LINT1) =
- (*(int *)(loApicBase + LOAPIC_LINT1) &
- ~(LOAPIC_MODE | LOAPIC_LOW | LOAPIC_LEVEL | LOAPIC_MASK)) |
- (LOAPIC_NMI | LOAPIC_HIGH | LOAPIC_EDGE);
- }
- else
- {
- *(int *)(loApicBase + LOAPIC_LINT0) = LOAPIC_MASK;
- *(int *)(loApicBase + LOAPIC_LINT1) = LOAPIC_MASK;
- }
- #elif defined(SYMMETRIC_IO_MODE)
- /* program Local Vector Table for the Symmetric IO Mode */
- *(int *)(loApicBase + LOAPIC_LINT0) = LOAPIC_MASK;
- *(int *)(loApicBase + LOAPIC_LINT1) = LOAPIC_MASK;
- #endif /* defined(VIRTUAL_WIRE_MODE) */
- /* lock the Local APIC interrupts */
- *(int *)(loApicBase + LOAPIC_TIMER) = LOAPIC_MASK;
- *(int *)(loApicBase + LOAPIC_ERROR) = LOAPIC_MASK;
- if (loApicMaxLvt >= LOAPIC_LVT_P6)
- *(int *)(loApicBase + LOAPIC_PMC) = LOAPIC_MASK;
- if (loApicMaxLvt >= LOAPIC_LVT_PENTIUM4)
- *(int *)(loApicBase + LOAPIC_THERMAL) = LOAPIC_MASK;
- /* discard a pending interrupt if any */
- *(int *)(loApicBase + LOAPIC_EOI) = 0;
- }
- /*******************************************************************************
- *
- * loApicEnable - enable or disable the Local xAPIC
- *
- * This routine enables or disables the Local xAPIC. If the parameter is TRUE,
- * the Local xAPIC is enabled. If the parameter is FALSE, the Local xAPIC
- * is disabled.
- *
- * RETURNS: N/A
- */
- void loApicEnable
- (
- BOOL enable /* enable the Local xAPIC */
- )
- {
- INT32 oldLevel;
- oldLevel = intLock (); /* LOCK INTERRUPTS */
- /* enable or disable the Local APIC */
- if (enable)
- {
- /* if the original mode is PIC mode, enable the Local APIC */
- if ((loApicOldSvr & LOAPIC_ENABLE) == 0)
- {
- *(int *)(loApicBase + LOAPIC_SVR) |= LOAPIC_ENABLE;
- }
- #if defined (SYMMETRIC_IO_MODE)
- /* switch to SYMMETRIC_IO mode from PIC/VIRTUAL_WIRE mode */
- if (loApicImcr)
- {
- sysOutByte (IMCR_ADRS, IMCR_REG_SEL);
- sysOutByte (IMCR_DATA, IMCR_IOAPIC_ON);
- }
- #endif /* defined (SYMMETRIC_IO_MODE) */
- }
- else
- {
- #if defined (SYMMETRIC_IO_MODE)
- /* switch from SYMMETRIC_IO mode to PIC/VIRTUAL_WIRE mode */
- if (loApicImcr)
- {
- sysOutByte (IMCR_ADRS, IMCR_REG_SEL);
- sysOutByte (IMCR_DATA, IMCR_IOAPIC_OFF);
- }
- #endif /* defined (SYMMETRIC_IO_MODE) */
- /* if the original mode is PIC mode, disable the Local APIC */
- if ((loApicOldSvr & LOAPIC_ENABLE) == 0)
- {
- *(int *)(loApicBase + LOAPIC_SVR) &= ~LOAPIC_ENABLE;
- }
- else
- {
- /* restore the original value */
- *(int *)(loApicBase + LOAPIC_SVR) = loApicOldSvr;
- *(int *)(loApicBase + LOAPIC_LINT0) = loApicOldLint0;
- *(int *)(loApicBase + LOAPIC_LINT1) = loApicOldLint1;
- }
- }
- intUnlock (oldLevel); /* UNLOCK INTERRUPTS */
- }
- /*******************************************************************************
- *
- * loApicIntLock - lock out all Local APIC interrupts
- *
- * This routine locks out all Local APIC interrupts
- * It should be called in the interrupt disable state(IF bit is 0).
- *
- * RETURNS: N/A
- *
- * SEE ALSO: loApicIntUnlock()
- *
- * ARGSUSED0
- */
- LOCAL void loApicIntLock (void)
- {
- if (!(*(int *)(loApicBase + LOAPIC_TIMER) & LOAPIC_MASK))
- {
- sysIntMaskLocalApic |= LOCKED_TIMER;
- *(int *)(loApicBase + LOAPIC_TIMER) |= LOAPIC_MASK;
- }
- if (!(*(int *)(loApicBase + LOAPIC_LINT0) & LOAPIC_MASK))
- {
- sysIntMaskLocalApic |= LOCKED_LINT0;
- *(int *)(loApicBase + LOAPIC_LINT0) |= LOAPIC_MASK;
- }
- if (!(*(int *)(loApicBase + LOAPIC_LINT1) & LOAPIC_MASK))
- {
- sysIntMaskLocalApic |= LOCKED_LINT1;
- *(int *)(loApicBase + LOAPIC_LINT1) |= LOAPIC_MASK;
- }
- if (!(*(int *)(loApicBase + LOAPIC_ERROR) & LOAPIC_MASK))
- {
- sysIntMaskLocalApic |= LOCKED_ERROR;
- *(int *)(loApicBase + LOAPIC_ERROR) |= LOAPIC_MASK;
- }
- if ((loApicMaxLvt >= LOAPIC_LVT_P6) &&
- (!(*(int *)(loApicBase + LOAPIC_PMC) & LOAPIC_MASK)))
- {
- sysIntMaskLocalApic |= LOCKED_PMC;
- *(int *)(loApicBase + LOAPIC_PMC) |= LOAPIC_MASK;
- }
- if ((loApicMaxLvt >= LOAPIC_LVT_PENTIUM4) &&
- (!(*(int *)(loApicBase + LOAPIC_THERMAL) & LOAPIC_MASK)))
- {
- sysIntMaskLocalApic |= LOCKED_THERMAL;
- *(int *)(loApicBase + LOAPIC_THERMAL) |= LOAPIC_MASK;
- }
- }
- /*******************************************************************************
- *
- * loApicIntUnlock - unlock the Local APIC interrupts
- *
- * This routine unlocks the Local APIC interrupts
- * It should be called in the interrupt disable state(IF bit is 0).
- *
- * RETURNS: N/A
- *
- * SEE ALSO: loApicIntLock()
- *
- * ARGSUSED0
- */
- LOCAL void loApicIntUnlock (void)
- {
- if (sysIntMaskLocalApic & LOCKED_TIMER)
- *(int *)(loApicBase + LOAPIC_TIMER) &= ~LOAPIC_MASK;
- if (sysIntMaskLocalApic & LOCKED_LINT0)
- *(int *)(loApicBase + LOAPIC_LINT0) &= ~LOAPIC_MASK;
- if (sysIntMaskLocalApic & LOCKED_LINT1)
- *(int *)(loApicBase + LOAPIC_LINT1) &= ~LOAPIC_MASK;
- if (sysIntMaskLocalApic & LOCKED_ERROR)
- *(int *)(loApicBase + LOAPIC_ERROR) &= ~LOAPIC_MASK;
- if ((loApicMaxLvt >= LOAPIC_LVT_P6) &&
- (sysIntMaskLocalApic & LOCKED_PMC))
- *(int *)(loApicBase + LOAPIC_PMC) &= ~LOAPIC_MASK;
- if ((loApicMaxLvt >= LOAPIC_LVT_PENTIUM4) &&
- (sysIntMaskLocalApic & LOCKED_THERMAL))
- *(int *)(loApicBase + LOAPIC_THERMAL) &= ~LOAPIC_MASK;
- sysIntMaskLocalApic = 0; /* reset the flags */
- }
- /*******************************************************************************
- *
- * loApicIntEoi - send EOI (End Of Interrupt) signal to Local APIC
- *
- * This routine sends an EOI signal to the Local APIC's interrupting source.
- *
- * RETURNS: N/A
- */
- LOCAL void loApicIntEoi
- (
- INT32 irqNo /* INIIN number to send EOI */
- )
- {
- #ifdef SYS_INT_DEBUG
- extern UINT32 sysIntCount [];
- sysIntCount [irqNo]++;
- #endif /* SYS_INT_DEBUG */
- *(int *)(loApicBase + LOAPIC_EOI) = 0;
- }
- /*******************************************************************************
- *
- * loApicMpConfigTableInit - initialize pointers to MP configuration table
- *
- * This routine scans the memory areas specified in MP ver1.4, to find the
- * MP signature and initializes pointers to MP configuration tables. This
- * is not comprehensive and the only data used by VxWorks is the
- * APIC IDs and APIC base addresses.
- *
- * RETURNS: OK, or ERROR if not MP compliant
- *
- */
- LOCAL STATUS loApicMpConfigTableInit (void)
- {
- MP_FPS * pFps = NULL;
- MP_HEADER * mpHdr;
- MP_CPU * mpCpu;
- MP_IOAPIC * mpIOApic;
- INT8 * p;
- INT32 ix;
- /* scan for the MP Floating Point Structure */
- pFps = (MP_FPS *)loApicMpScan ((char *)EBDA_START, (char *)EBDA_END);
- if (pFps == NULL)
- pFps = (MP_FPS *)loApicMpScan ((char *)BIOS_ROM_START,
- (char *)BIOS_ROM_END);
- if (pFps == NULL)
- return (ERROR);
- /*
- * If featurebyte1 (array element 0) is non-zero, then we use
- * standard configuration return ERROR and let the error handle use
- * standard addresses and Local and IO APIC ID's.
- */
- if ((pFps->featureByte[0] != 0) || (pFps->configTableAddr == 0))
- return (ERROR);
- /* check if the IMCR exists or not */
- loApicImcr = (pFps->featureByte[1] & 0x80) ? TRUE : FALSE;
- /* get MP header pointer */
- mpHdr = (MP_HEADER *) pFps->configTableAddr;
- /* get Local APIC Base Address */
- loApicBase = (UINT32)(mpHdr->localApicBaseAddr);
- /* We only need CPU and IO APIC entries, ignore the rest */
- p = (char *)mpHdr + sizeof(MP_HEADER);
- for(ix = 0; ix < mpHdr->entryCount; ix++)
- {
- switch(*p)
- {
- case MP_ENTRY_CPU: /* Processor Configuration Entry */
- mpCpu = (MP_CPU *)p;
- loApicNcpu++; /* increment the CPU counter */
- p += sizeof (MP_CPU);
- break;
- case MP_ENTRY_IOAPIC: /* IO Apic Configuration Entry */
- mpIOApic = (MP_IOAPIC *)p;
- loApicNioApic++; /* increment the IO APIC counter */
- p += sizeof (MP_IOAPIC);
- break;
- default: /* Others..ignore, for now */
- p += 8; /* wild guess */
- }
- }
- return(OK);
- }
- /*******************************************************************************
- *
- * loApicMpScan - scans given memory range for the string "_MP_"
- *
- * This routine scans the memory areas specified in its argument for the
- * Intel MP signature string "_MP_".
- *
- * RETURNS: pointer to "_MP_" in the range , or NULL
- *
- */
- LOCAL INT8 * loApicMpScan
- (
- INT8 * start, /* start address to scan */
- INT8 * end /* end address to scan */
- )
- {
- INT8 * p;
- for (p = start; (p+3) < end; p++)
- {
- if (strncmp (p, "_MP_", 4) == 0)
- return (p);
- }
- return (NULL);
- }
- /******************************************************************************
- *
- * loApicIpi - generate a Inter Processor Interrupt
- *
- * This routine delivers an Inter-Processor interrupt to the specified CPU
- * in the specified mode, with the specified vectorNo. Level should always
- * be 1 except INIT De-assert mode.
- *
- * RETURNS: OK, or ERROR if the delivery status is not idle
- */
- STATUS loApicIpi
- (
- INT32 apicId, /* APIC ID number to send the interrupt */
- INT32 shortHand, /* destination short hand */
- INT32 trigger, /* trigger mode. 0: edge or 1: level */
- INT32 level, /* level. 0: de-assert or 1: assert */
- INT32 destMode, /* destination mode. 0: physical or 1: logical */
- INT32 deliMode, /* delivery mode. 000: fixed ... 110: startup */
- INT32 vectorNo /* vector number */
- )
- {
- UINT32 icrHi = (*(int *)(loApicBase + LOAPIC_ICRHI)) & 0xf0ffffff;
- UINT32 icrLo = (*(int *)(loApicBase + LOAPIC_ICRLO)) & 0xfff33000;
- /* ShortHand, Trigger, Level, DeliveryMode and Vector */
- icrLo |= ((shortHand << 18) & 0xc0000) |
- ((trigger << 15) & 0x8000) |
- ((level << 14) & 0x4000) |
- ((destMode << 11) & 0x800) |
- ((deliMode << 8) & 0x700) |
- (vectorNo & 0xff);
- /* Destination Apic Id */
- icrHi |= (apicId << 24) & 0xff000000;
- /* is the interrupt idle? */
- if (*(int *)(loApicBase + LOAPIC_ICRLO) & STATUS_PEND)
- {
- loApicBusy++;
- LOAPIC_DBG_MSG ("ipi: LOAPIC busy 0x%xn",
- *(int *)(loApicBase + LOAPIC_ESR))
- return (ERROR);
- }
- /* reset the error status register */
- *(int *)(loApicBase + LOAPIC_ESR) = 0;
- *(int *)(loApicBase + LOAPIC_ESR) = 0;
- if (*(int *)(loApicBase + LOAPIC_ESR) != 0)
- {
- LOAPIC_DBG_MSG ("ipi: 0. ESR=0x%xn",
- *(int *)(loApicBase + LOAPIC_ESR))
- return (ERROR);
- }
- /* Send it! */
- *(int *)(loApicBase + LOAPIC_ICRHI) = icrHi;
- *(int *)(loApicBase + LOAPIC_ICRLO) = icrLo;
- /* Wait till interrupt is sent */
- while (*(int *)(loApicBase + LOAPIC_ICRLO) & STATUS_PEND)
- if (*(int *)(loApicBase + LOAPIC_ESR) != 0)
- {
- LOAPIC_DBG_MSG ("ipi: 1. ESR=0x%xn",
- *(int *)(loApicBase + LOAPIC_ESR))
- return (ERROR);
- }
- return(OK);
- }