Implemented the global firmware mutex, and fixed our fake spinlock implementation to actually work. The last bit of functionality I'm trying to trying to get from the bus manager, before I move onto drivers, is ACPI poweroff. Which, at least on my SMP machine, is hanging my system in ways I didn't even think possible. I suspect this may have to do with non-S5 wakeup GPEs still being enabled.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12255 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Nathan Whitehorn 2005-04-05 16:36:23 +00:00
parent a8715f0fa5
commit 813830c9f8
3 changed files with 76 additions and 7 deletions

View File

@ -258,9 +258,21 @@ status_t evaluate_method (const char *object, const char *method, acpi_object_ty
return (status == AE_OK) ? B_OK : B_ERROR;
}
void waking_vector(void) {
//--- This should do something ---
}
status_t enter_sleep_state (uint8 state) {
ACPI_STATUS status;
cpu_status cpu;
physical_entry wake_vector;
lock_memory(&waking_vector,sizeof(waking_vector),0);
get_memory_map(&waking_vector,sizeof(waking_vector),&wake_vector,1);
status = AcpiSetFirmwareWakingVector(wake_vector.address);
if (status != AE_OK)
return B_ERROR;
status = AcpiEnterSleepStatePrep(state);
if (status != AE_OK)
@ -275,9 +287,9 @@ status_t enter_sleep_state (uint8 state) {
if (status != AE_OK)
return B_ERROR;
status = AcpiLeaveSleepState(state);
/*status = AcpiLeaveSleepState(state);
if (status != AE_OK)
return B_ERROR;
return B_ERROR;*/
return B_OK;
}

View File

@ -151,8 +151,7 @@
#define ACPI_INTERNAL_VAR_XFACE
#define ACPI_FLUSH_CPU_CACHE()
/* Implement ACPI_FLUSH_CPU_CACHE to do something! */
#define ACPI_FLUSH_CPU_CACHE() __asm __volatile("wbinvd");
#ifdef ACPI_DEBUG
#define ACPI_DEBUG_OUTPUT
@ -188,8 +187,12 @@
#define ACPI_USE_SYSTEM_CLIBRARY
#define ACPI_USE_NATIVE_DIVIDE
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq)
#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq)
extern int acpi_acquire_global_lock(uint32 *lock);
extern int acpi_release_global_lock(uint32 *lock);
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) ((Acq) = acpi_acquire_global_lock(GLptr))
#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) ((Acq) = acpi_release_global_lock(GLptr))
/* Kernel doesn't have strupr, should be fixed. */
static __inline char *

View File

@ -684,6 +684,16 @@ AcpiOsSignalSemaphore (
return AE_OK;
}
/* For R5 compatibility */
inline int32
_atomic_test_and_set(volatile int32 *value, int32 newValue, int32 testAgainst)
{
int32 oldValue;
asm volatile("lock; cmpxchg %%ecx, (%%edx)"
: "=a" (oldValue) : "a" (testAgainst), "c" (newValue), "d" (value));
return oldValue;
}
ACPI_STATUS
AcpiOsCreateLock (
@ -726,7 +736,7 @@ AcpiOsAcquireLock (
call is hanging the system? I'm not sure how to detect that
though. Anyway, this works, even if it's stupid. */
while (atomic_add(((spinlock *)(Handle)),0) <= 0);
while (_atomic_test_and_set(((spinlock *)(Handle)),0,1) <= 0);
}
@ -1270,4 +1280,48 @@ AcpiOsSignal (
return (AE_OK);
}
/* The following stolen from FreeBSD */
/* Section 5.2.9.1: global lock acquire/release functions */
#define GL_ACQUIRED (-1)
#define GL_BUSY 0
#define GL_BIT_PENDING 0x1
#define GL_BIT_OWNED 0x2
#define GL_BIT_MASK (GL_BIT_PENDING | GL_BIT_OWNED)
/*
* Acquire the global lock. If busy, set the pending bit. The caller
* will wait for notification from the BIOS that the lock is available
* and then attempt to acquire it again.
*/
int
acpi_acquire_global_lock(uint32 *lock)
{
uint32 new, old;
do {
old = *lock;
new = ((old & ~GL_BIT_MASK) | GL_BIT_OWNED) |
((old >> 1) & GL_BIT_PENDING);
} while (_atomic_test_and_set(lock, new, old) != old);
return ((new < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY);
}
/*
* Release the global lock, returning whether there is a waiter pending.
* If the BIOS set the pending bit, OSPM must notify the BIOS when it
* releases the lock.
*/
int
acpi_release_global_lock(uint32 *lock)
{
uint32 new, old;
do {
old = *lock;
new = old & ~GL_BIT_MASK;
} while (_atomic_test_and_set(lock, new, old) != old);
return (old & GL_BIT_PENDING);
}