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
@@ -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; return (status == AE_OK) ? B_OK : B_ERROR;
} }
void waking_vector(void) {
//--- This should do something ---
}
status_t enter_sleep_state (uint8 state) { status_t enter_sleep_state (uint8 state) {
ACPI_STATUS status; ACPI_STATUS status;
cpu_status cpu; 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); status = AcpiEnterSleepStatePrep(state);
if (status != AE_OK) if (status != AE_OK)
@@ -275,9 +287,9 @@ status_t enter_sleep_state (uint8 state) {
if (status != AE_OK) if (status != AE_OK)
return B_ERROR; return B_ERROR;
status = AcpiLeaveSleepState(state); /*status = AcpiLeaveSleepState(state);
if (status != AE_OK) if (status != AE_OK)
return B_ERROR; return B_ERROR;*/
return B_OK; return B_OK;
} }
@@ -151,8 +151,7 @@
#define ACPI_INTERNAL_VAR_XFACE #define ACPI_INTERNAL_VAR_XFACE
#define ACPI_FLUSH_CPU_CACHE() #define ACPI_FLUSH_CPU_CACHE() __asm __volatile("wbinvd");
/* Implement ACPI_FLUSH_CPU_CACHE to do something! */
#ifdef ACPI_DEBUG #ifdef ACPI_DEBUG
#define ACPI_DEBUG_OUTPUT #define ACPI_DEBUG_OUTPUT
@@ -188,8 +187,12 @@
#define ACPI_USE_SYSTEM_CLIBRARY #define ACPI_USE_SYSTEM_CLIBRARY
#define ACPI_USE_NATIVE_DIVIDE #define ACPI_USE_NATIVE_DIVIDE
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) extern int acpi_acquire_global_lock(uint32 *lock);
#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) 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. */ /* Kernel doesn't have strupr, should be fixed. */
static __inline char * static __inline char *
+55 -1
View File
@@ -684,6 +684,16 @@ AcpiOsSignalSemaphore (
return AE_OK; 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 ACPI_STATUS
AcpiOsCreateLock ( AcpiOsCreateLock (
@@ -726,7 +736,7 @@ AcpiOsAcquireLock (
call is hanging the system? I'm not sure how to detect that call is hanging the system? I'm not sure how to detect that
though. Anyway, this works, even if it's stupid. */ 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); 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);
}