Subversion Repositories Kolibri OS

Rev

Rev 1498 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1498 Rev 2216
Line 6... Line 6...
6
 
6
 
7
/******************************************************************************
7
/******************************************************************************
8
 *
8
 *
9
 * 1. Copyright Notice
9
 * 1. Copyright Notice
10
 *
10
 *
11
 * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
11
 * Some or all of this work - Copyright (c) 1999 - 2011, Intel Corp.
12
 * All rights reserved.
12
 * All rights reserved.
13
 *
13
 *
14
 * 2. License
14
 * 2. License
15
 *
15
 *
Line 115... Line 115...
115
 
115
 
116
#include "acpi.h"
116
#include "acpi.h"
117
#include "accommon.h"
117
#include "accommon.h"
118
#include "acevents.h"
118
#include "acevents.h"
119
#include "acnamesp.h"
-
 
Line 120... Line 119...
120
#include "acinterp.h"
119
#include "acnamesp.h"
121
 
120
 
Line 127... Line 126...
127
 
126
 
128
static void ACPI_SYSTEM_XFACE
127
static void ACPI_SYSTEM_XFACE
129
AcpiEvNotifyDispatch (
128
AcpiEvNotifyDispatch (
Line 130... Line -...
130
    void                    *Context);
-
 
131
 
-
 
132
static UINT32
-
 
133
AcpiEvGlobalLockHandler (
-
 
134
    void                    *Context);
-
 
135
 
-
 
136
static ACPI_STATUS
-
 
137
AcpiEvRemoveGlobalLockHandler (
-
 
Line 138... Line 129...
138
    void);
129
    void                    *Context);
139
 
130
 
140
 
131
 
141
/*******************************************************************************
132
/*******************************************************************************
Line 370... Line 361...
370
 
361
 
371
    AcpiUtDeleteGenericState (NotifyInfo);
362
    AcpiUtDeleteGenericState (NotifyInfo);
Line 372... Line -...
372
}
-
 
373
 
-
 
374
 
-
 
375
/*******************************************************************************
-
 
376
 *
-
 
377
 * FUNCTION:    AcpiEvGlobalLockHandler
-
 
378
 *
-
 
379
 * PARAMETERS:  Context         - From thread interface, not used
-
 
380
 *
-
 
381
 * RETURN:      ACPI_INTERRUPT_HANDLED
-
 
382
 *
-
 
383
 * DESCRIPTION: Invoked directly from the SCI handler when a global lock
-
 
384
 *              release interrupt occurs. Attempt to acquire the global lock,
-
 
385
 *              if successful, signal the thread waiting for the lock.
-
 
386
 *
-
 
387
 * NOTE: Assumes that the semaphore can be signaled from interrupt level. If
-
 
388
 * this is not possible for some reason, a separate thread will have to be
-
 
389
 * scheduled to do this.
-
 
390
 *
-
 
391
 ******************************************************************************/
-
 
392
 
-
 
393
static UINT32
-
 
394
AcpiEvGlobalLockHandler (
-
 
395
    void                    *Context)
-
 
396
{
-
 
397
    BOOLEAN                 Acquired = FALSE;
-
 
398
    ACPI_STATUS             Status;
-
 
399
 
-
 
400
 
-
 
401
    /*
-
 
402
     * Attempt to get the lock.
-
 
403
     *
-
 
404
     * If we don't get it now, it will be marked pending and we will
-
 
405
     * take another interrupt when it becomes free.
-
 
406
     */
-
 
407
    ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired);
-
 
408
    if (Acquired)
-
 
409
    {
-
 
410
        /* Got the lock, now wake the thread waiting for it */
-
 
411
 
-
 
412
        AcpiGbl_GlobalLockAcquired = TRUE;
-
 
413
 
-
 
414
        /* Send a unit to the semaphore */
-
 
415
 
-
 
416
        Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1);
-
 
417
        if (ACPI_FAILURE (Status))
-
 
418
        {
-
 
419
            ACPI_ERROR ((AE_INFO, "Could not signal Global Lock semaphore"));
-
 
420
        }
-
 
421
    }
-
 
422
 
-
 
423
    return (ACPI_INTERRUPT_HANDLED);
-
 
424
}
-
 
425
 
-
 
426
 
-
 
427
/*******************************************************************************
-
 
428
 *
-
 
429
 * FUNCTION:    AcpiEvInitGlobalLockHandler
-
 
430
 *
-
 
431
 * PARAMETERS:  None
-
 
432
 *
-
 
433
 * RETURN:      Status
-
 
434
 *
-
 
435
 * DESCRIPTION: Install a handler for the global lock release event
-
 
436
 *
-
 
437
 ******************************************************************************/
-
 
438
 
-
 
439
ACPI_STATUS
-
 
440
AcpiEvInitGlobalLockHandler (
-
 
441
    void)
-
 
442
{
-
 
443
    ACPI_STATUS             Status;
-
 
444
 
-
 
445
 
-
 
446
    ACPI_FUNCTION_TRACE (EvInitGlobalLockHandler);
-
 
447
 
-
 
448
 
-
 
449
    /* Attempt installation of the global lock handler */
-
 
450
 
-
 
451
    Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL,
-
 
452
                AcpiEvGlobalLockHandler, NULL);
-
 
453
 
-
 
454
    /*
-
 
455
     * If the global lock does not exist on this platform, the attempt to
-
 
456
     * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick).
-
 
457
     * Map to AE_OK, but mark global lock as not present. Any attempt to
-
 
458
     * actually use the global lock will be flagged with an error.
-
 
459
     */
-
 
460
    if (Status == AE_NO_HARDWARE_RESPONSE)
-
 
461
    {
-
 
462
        ACPI_ERROR ((AE_INFO,
-
 
463
            "No response from Global Lock hardware, disabling lock"));
-
 
464
 
-
 
465
        AcpiGbl_GlobalLockPresent = FALSE;
-
 
466
        return_ACPI_STATUS (AE_OK);
-
 
467
    }
-
 
468
 
-
 
469
    AcpiGbl_GlobalLockPresent = TRUE;
-
 
470
    return_ACPI_STATUS (Status);
-
 
471
}
-
 
472
 
-
 
473
 
-
 
474
/*******************************************************************************
-
 
475
 *
-
 
476
 * FUNCTION:    AcpiEvRemoveGlobalLockHandler
-
 
477
 *
-
 
478
 * PARAMETERS:  None
-
 
479
 *
-
 
480
 * RETURN:      Status
-
 
481
 *
-
 
482
 * DESCRIPTION: Remove the handler for the Global Lock
-
 
483
 *
-
 
484
 ******************************************************************************/
-
 
485
 
-
 
486
static ACPI_STATUS
-
 
487
AcpiEvRemoveGlobalLockHandler (
-
 
488
    void)
-
 
489
{
-
 
490
    ACPI_STATUS             Status;
-
 
491
 
-
 
492
 
-
 
493
    ACPI_FUNCTION_TRACE (EvRemoveGlobalLockHandler);
-
 
494
 
-
 
495
    AcpiGbl_GlobalLockPresent = FALSE;
-
 
496
    Status = AcpiRemoveFixedEventHandler (ACPI_EVENT_GLOBAL,
-
 
497
                AcpiEvGlobalLockHandler);
-
 
498
 
-
 
499
    return_ACPI_STATUS (Status);
-
 
500
}
-
 
501
 
-
 
502
 
-
 
503
/******************************************************************************
-
 
504
 *
-
 
505
 * FUNCTION:    AcpiEvAcquireGlobalLock
-
 
506
 *
-
 
507
 * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec.
-
 
508
 *
-
 
509
 * RETURN:      Status
-
 
510
 *
-
 
511
 * DESCRIPTION: Attempt to gain ownership of the Global Lock.
-
 
512
 *
-
 
513
 * MUTEX:       Interpreter must be locked
-
 
514
 *
-
 
515
 * Note: The original implementation allowed multiple threads to "acquire" the
-
 
516
 * Global Lock, and the OS would hold the lock until the last thread had
-
 
517
 * released it. However, this could potentially starve the BIOS out of the
-
 
518
 * lock, especially in the case where there is a tight handshake between the
-
 
519
 * Embedded Controller driver and the BIOS. Therefore, this implementation
-
 
520
 * allows only one thread to acquire the HW Global Lock at a time, and makes
-
 
521
 * the global lock appear as a standard mutex on the OS side.
-
 
522
 *
-
 
523
 *****************************************************************************/
-
 
524
 
-
 
525
ACPI_STATUS
-
 
526
AcpiEvAcquireGlobalLock (
-
 
527
    UINT16                  Timeout)
-
 
528
{
-
 
529
    ACPI_STATUS             Status = AE_OK;
-
 
530
    BOOLEAN                 Acquired = FALSE;
-
 
531
 
-
 
532
 
-
 
533
    ACPI_FUNCTION_TRACE (EvAcquireGlobalLock);
-
 
534
 
-
 
535
 
-
 
536
    /*
-
 
537
     * Only one thread can acquire the GL at a time, the GlobalLockMutex
-
 
538
     * enforces this. This interface releases the interpreter if we must wait.
-
 
539
     */
-
 
540
    Status = AcpiExSystemWaitMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex,
-
 
541
                Timeout);
-
 
542
    if (ACPI_FAILURE (Status))
-
 
543
    {
-
 
544
        return_ACPI_STATUS (Status);
-
 
545
    }
-
 
546
 
-
 
547
    /*
-
 
548
     * Update the global lock handle and check for wraparound. The handle is
-
 
549
     * only used for the external global lock interfaces, but it is updated
-
 
550
     * here to properly handle the case where a single thread may acquire the
-
 
551
     * lock via both the AML and the AcpiAcquireGlobalLock interfaces. The
-
 
552
     * handle is therefore updated on the first acquire from a given thread
-
 
553
     * regardless of where the acquisition request originated.
-
 
554
     */
-
 
555
    AcpiGbl_GlobalLockHandle++;
-
 
556
    if (AcpiGbl_GlobalLockHandle == 0)
-
 
557
    {
-
 
558
        AcpiGbl_GlobalLockHandle = 1;
-
 
559
    }
-
 
560
 
-
 
561
    /*
-
 
562
     * Make sure that a global lock actually exists. If not, just treat the
-
 
563
     * lock as a standard mutex.
-
 
564
     */
-
 
565
    if (!AcpiGbl_GlobalLockPresent)
-
 
566
    {
-
 
567
        AcpiGbl_GlobalLockAcquired = TRUE;
-
 
568
        return_ACPI_STATUS (AE_OK);
-
 
569
    }
-
 
570
 
-
 
571
    /* Attempt to acquire the actual hardware lock */
-
 
572
 
-
 
573
    ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired);
-
 
574
    if (Acquired)
-
 
575
    {
-
 
576
       /* We got the lock */
-
 
577
 
-
 
578
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired hardware Global Lock\n"));
-
 
579
 
-
 
580
        AcpiGbl_GlobalLockAcquired = TRUE;
-
 
581
        return_ACPI_STATUS (AE_OK);
-
 
582
    }
-
 
583
 
-
 
584
    /*
-
 
585
     * Did not get the lock. The pending bit was set above, and we must now
-
 
586
     * wait until we get the global lock released interrupt.
-
 
587
     */
-
 
588
    ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n"));
-
 
589
 
-
 
590
    /*
-
 
591
     * Wait for handshake with the global lock interrupt handler.
-
 
592
     * This interface releases the interpreter if we must wait.
-
 
593
     */
-
 
594
    Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore,
-
 
595
                ACPI_WAIT_FOREVER);
-
 
596
 
-
 
597
    return_ACPI_STATUS (Status);
-
 
598
}
-
 
599
 
-
 
600
 
-
 
601
/*******************************************************************************
-
 
602
 *
-
 
603
 * FUNCTION:    AcpiEvReleaseGlobalLock
-
 
604
 *
-
 
605
 * PARAMETERS:  None
-
 
606
 *
-
 
607
 * RETURN:      Status
-
 
608
 *
-
 
609
 * DESCRIPTION: Releases ownership of the Global Lock.
-
 
610
 *
-
 
611
 ******************************************************************************/
-
 
612
 
-
 
613
ACPI_STATUS
-
 
614
AcpiEvReleaseGlobalLock (
-
 
615
    void)
-
 
616
{
-
 
617
    BOOLEAN                 Pending = FALSE;
-
 
618
    ACPI_STATUS             Status = AE_OK;
-
 
619
 
-
 
620
 
-
 
621
    ACPI_FUNCTION_TRACE (EvReleaseGlobalLock);
-
 
622
 
-
 
623
 
-
 
624
    /* Lock must be already acquired */
-
 
625
 
-
 
626
    if (!AcpiGbl_GlobalLockAcquired)
-
 
627
    {
-
 
628
        ACPI_WARNING ((AE_INFO,
-
 
629
            "Cannot release the ACPI Global Lock, it has not been acquired"));
-
 
630
        return_ACPI_STATUS (AE_NOT_ACQUIRED);
-
 
631
    }
-
 
632
 
-
 
633
    if (AcpiGbl_GlobalLockPresent)
-
 
634
    {
-
 
635
        /* Allow any thread to release the lock */
-
 
636
 
-
 
637
        ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_FACS, Pending);
-
 
638
 
-
 
639
        /*
-
 
640
         * If the pending bit was set, we must write GBL_RLS to the control
-
 
641
         * register
-
 
642
         */
-
 
643
        if (Pending)
-
 
644
        {
-
 
645
            Status = AcpiWriteBitRegister (
-
 
646
                        ACPI_BITREG_GLOBAL_LOCK_RELEASE, ACPI_ENABLE_EVENT);
-
 
647
        }
-
 
648
 
-
 
649
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Released hardware Global Lock\n"));
-
 
650
    }
-
 
651
 
-
 
652
    AcpiGbl_GlobalLockAcquired = FALSE;
-
 
653
 
-
 
654
    /* Release the local GL mutex */
-
 
655
 
-
 
656
    AcpiOsReleaseMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex);
-
 
657
    return_ACPI_STATUS (Status);
-
 
658
}
363
}
659
 
364
 
660
 
365
 
661
/******************************************************************************
366
/******************************************************************************
662
 *
367
 *
Line 735... Line 440...
735
            ACPI_WARNING ((AE_INFO, "AcpiDisable failed"));
440
            ACPI_WARNING ((AE_INFO, "AcpiDisable failed"));
736
        }
441
        }
737
    }
442
    }
738
    return_VOID;
443
    return_VOID;
739
}
444
}
740
-