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:
parent
a8715f0fa5
commit
813830c9f8
@ -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;
|
||||
}
|
||||
|
@ -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 *
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user