Rewrote the Global lock implementation by stealing code from NetBSD, and fudged around a bug in the IBM Thinkpad A21M ACPI firmware, involving the invocation of the _STA method. I suspect this may be a deeper bug -- I'll look into it later.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@12463 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -187,11 +187,42 @@
|
|||||||
#define ACPI_USE_SYSTEM_CLIBRARY
|
#define ACPI_USE_SYSTEM_CLIBRARY
|
||||||
#define ACPI_USE_NATIVE_DIVIDE
|
#define ACPI_USE_NATIVE_DIVIDE
|
||||||
|
|
||||||
extern int acpi_acquire_global_lock(uint32 *lock);
|
/* The following Global Lock code stolen from NetBSD
|
||||||
extern int acpi_release_global_lock(uint32 *lock);
|
src/sys/arch/i386/include/acpi_func.h which in turn
|
||||||
|
was stolen from Intel's spec document */
|
||||||
|
|
||||||
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) ((Acq) = acpi_acquire_global_lock(GLptr))
|
#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
|
||||||
#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) ((Acq) = acpi_release_global_lock(GLptr))
|
do { \
|
||||||
|
__asm __volatile( \
|
||||||
|
"1: movl %1,%%eax ;" \
|
||||||
|
" movl %%eax,%%edx ;" \
|
||||||
|
" andl %2,%%edx ;" \
|
||||||
|
" btsl $0x1,%%edx ;" \
|
||||||
|
" adcl $0x0,%%edx ;" \
|
||||||
|
" lock ;" \
|
||||||
|
" cmpxchgl %%edx,%1 ;" \
|
||||||
|
" jnz 1b ;" \
|
||||||
|
" andb $0x3,%%dl ;" \
|
||||||
|
" cmpb $0x3,%%dl ;" \
|
||||||
|
" sbbl %%eax,%%eax ;" \
|
||||||
|
: "=&a" (Acq), "+m" (*GLptr) \
|
||||||
|
: "i" (~1L) \
|
||||||
|
: "edx"); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \
|
||||||
|
do { \
|
||||||
|
__asm __volatile( \
|
||||||
|
"1: movl %1,%%eax ;" \
|
||||||
|
" andl %2,%%edx ;" \
|
||||||
|
" lock ;" \
|
||||||
|
" cmpxchgl %%edx,%1 ;" \
|
||||||
|
" jnz 1b ;" \
|
||||||
|
" andl $0x1,%%eax ;" \
|
||||||
|
: "=&a" (Acq), "+m" (*GLptr) \
|
||||||
|
: "i" (~3L) \
|
||||||
|
: "edx"); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
/* Kernel doesn't have strupr, should be fixed. */
|
/* Kernel doesn't have strupr, should be fixed. */
|
||||||
|
|||||||
@@ -583,7 +583,7 @@ AcpiNsGetDeviceCallback (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Run _STA to determine if device is present */
|
/* Run _STA to determine if device is present */
|
||||||
|
#if 0
|
||||||
Status = AcpiUtExecute_STA (Node, &Flags);
|
Status = AcpiUtExecute_STA (Node, &Flags);
|
||||||
if (ACPI_FAILURE (Status))
|
if (ACPI_FAILURE (Status))
|
||||||
{
|
{
|
||||||
@@ -596,7 +596,7 @@ AcpiNsGetDeviceCallback (
|
|||||||
|
|
||||||
return (AE_CTRL_DEPTH);
|
return (AE_CTRL_DEPTH);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* Filter based on device HID & CID */
|
/* Filter based on device HID & CID */
|
||||||
|
|
||||||
if (Info->Hid != NULL)
|
if (Info->Hid != NULL)
|
||||||
|
|||||||
@@ -1279,49 +1279,3 @@ 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);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user