Ticket #4762: acpi_fix_global_locking.patch

File acpi_fix_global_locking.patch, 7.1 KB (added by tqh, 12 years ago)

Fixed global locking code, base on FreeBSD's

  • src/add-ons/kernel/bus_managers/acpi/include/platform/achaiku.h

     
    160160
    161161#define ACPI_FLUSH_CPU_CACHE() __asm __volatile("wbinvd");
    162162
    163 #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
    164 do { \
    165     __asm __volatile( \
    166     "1: movl %1,%%eax       ;" \
    167     "   movl %%eax,%%edx    ;" \
    168     "   andl %2,%%edx       ;" \
    169     "   btsl $0x1,%%edx     ;" \
    170     "   adcl $0x0,%%edx     ;" \
    171     "   lock            ;" \
    172     "   cmpxchgl %%edx,%1   ;" \
    173     "   jnz 1b          ;" \
    174     "   andb $0x3,%%dl      ;" \
    175     "   cmpb $0x3,%%dl      ;" \
    176     "   sbbl %%eax,%%eax    ;" \
    177     : "=&a" (Acq), "+m" (*GLptr) \
    178     : "i" (~1L) \
    179     : "edx"); \
     163/* Based on FreeBSD's due to lack of documentation */
     164extern int AcpiOsAcquireGlobalLock(uint32 *lock);
     165extern int AcpiOsReleaseGlobalLock(uint32 *lock);
     166
     167#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq)    do {                    \
     168        (Acq) = AcpiOsAcquireGlobalLock(&((GLptr)->GlobalLock));       \
    180169} while (0)
    181170
    182 #define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \
    183 do { \
    184     __asm __volatile( \
    185     "1: movl %1,%%eax       ;" \
    186     "   andl %2,%%edx       ;" \
    187     "   lock            ;" \
    188     "   cmpxchgl %%edx,%1   ;" \
    189     "   jnz 1b          ;" \
    190     "   andl $0x1,%%eax     ;" \
    191     : "=&a" (Acq), "+m" (*GLptr) \
    192     : "i" (~3L) \
    193     : "edx"); \
     171#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq)    do {                    \
     172        (Acq) = AcpiOsReleaseGlobalLock(&((GLptr)->GlobalLock));       \
    194173} while (0)
    195174
    196175#else /* _KERNEL_MODE */
  • src/add-ons/kernel/bus_managers/acpi/oshaiku.c

     
    157157        dprintf("acpi[%ld]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__);
    158158#   define DEBUG_FUNCTION_F(x, y...) \
    159159        dprintf("acpi[%ld]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y);
    160 #   if DEBUG_OSHAIKU = 1
     160#   if DEBUG_OSHAIKU == 1
    161161// No verbose debugging, do nothing
    162162#       define DEBUG_FUNCTION_V()
    163163#       define DEBUG_FUNCTION_VF(x, y...)
     
    243243        if (status == AE_OK)
    244244            sACPIRoot = address;
    245245    }
    246     dprintf("AcpiOsGetRootPointer returning %p\n", (void *)sACPIRoot);
    247246    return sACPIRoot;
    248247#else
    249248    return AeLocalGetRootPointer();
     
    445444#ifdef _KERNEL_MODE
    446445    void *there;
    447446    area_id area = map_physical_memory("acpi_physical_mem_area", (void *)where,
    448         length, B_ANY_KERNEL_ADDRESS, 0, &there);
     447        length, B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, &there);
     448
    449449    DEBUG_FUNCTION_F("addr: 0x%08lx; length: %lu; mapped: %p; area: %ld",
    450450        (addr_t)where, (size_t)length, there, area);
    451451    if (area < 0) {
    452452        dprintf("ACPI: cannot map memory at 0x%08x, length %d\n", where, length);
    453453        return NULL;
    454454    }
    455 
    456455    return there;
    457456#else
    458457    return NULL;
     
    611610                break;
    612611        }       
    613612    }
    614     DEBUG_FUNCTION_VF("result: %lu", (uint32)result);
     613    DEBUG_FUNCTION_VF("sem: %ld; count: %lu; timeout: %u result: %lu",
     614        handle, units, timeout, (uint32)result);
    615615    return result;
    616616}
    617617
     
    890890AcpiOsReadPciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, void *value,
    891891        UINT32 width)
    892892{
     893    uint32 *val;
     894    val = value;
    893895#ifdef _KERNEL_MODE
    894     UINT32 val = gPCIManager->read_pci_config(
    895         pciId->Bus, pciId->Device, pciId->Function, reg, width / 8);
    896896    DEBUG_FUNCTION();
     897
    897898    switch (width) {
    898899        case 8:
    899             *(UINT8 *) value = val;
    900             break;
    901900        case 16:
    902             *(UINT16 *) value = val;
    903             break;
    904901        case 32:
    905             *(UINT32 *) value = val;
     902            *val = gPCIManager->read_pci_config(
     903                pciId->Bus, pciId->Device, pciId->Function, reg, width / 8);
    906904            break;
    907905        default:
    908             dprintf("AcpiOsReadPciConfiguration unhandled width: %u\n", width);
    909906            return AE_ERROR;
    910907    }
    911908    return AE_OK;
     
    983980            break;
    984981
    985982        default:
    986             dprintf("AcpiOsReadPort: unhandeld width: %u\n", width);
    987983            return AE_ERROR;
    988984    }
    989985
     
    10271023            break;
    10281024
    10291025        default:
    1030             dprintf("AcpiOsWritePort: unhandeld width: %u\n", width);
    10311026            return AE_ERROR;
    10321027    }
    10331028
     
    11071102 *
    11081103 *****************************************************************************/
    11091104BOOLEAN
    1110 AcpiOsReadable(void *pointer, ACPI_SIZE Length)
     1105AcpiOsReadable(void *pointer, ACPI_SIZE length)
    11111106{
    1112     //TODO: Look if this is really ok.
     1107    area_id id;
     1108    area_info info;
    11131109    DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length);
    1114     return TRUE;
     1110   
     1111    id = area_for(pointer);
     1112    if (id == B_ERROR)
     1113        return false;
     1114    if (get_area_info(id, &info) != B_OK)
     1115        return false;
     1116    return info.protection & B_KERNEL_READ_AREA &&
     1117        (pointer + length) <= (info.address + info.ram_size);
    11151118}
    11161119
    11171120
     
    11301133BOOLEAN
    11311134AcpiOsWritable(void *pointer, ACPI_SIZE length)
    11321135{
    1133     //TODO: Look if this is really ok.
     1136    area_id id;
     1137    area_info info;
    11341138    DEBUG_FUNCTION_F("addr: %p; length: %lu", pointer, (size_t)length);
    1135     return TRUE;
     1139
     1140    id = area_for(pointer);
     1141    if (id == B_ERROR)
     1142        return false;
     1143    if (get_area_info(id, &info) != B_OK)
     1144        return false;
     1145    return info.protection & (B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA) &&
     1146        (pointer + length) <= (info.address + info.ram_size);
    11361147}
    11371148
    11381149
     
    11541165AcpiOsGetThreadId()
    11551166{
    11561167    thread_id thread = find_thread(NULL);
    1157     return thread;
    11581168
    1159     //TODO: Look if this is needed.
     1169    //TODO: Handle if thread_id is 0.
    11601170    // ACPI treats a 0 return as an error,
    11611171    // but we are thread 0 in early boot
    1162     //return thread == 0 ? 1 : thread;
     1172    return thread == 0 ? 1 : thread;
    11631173}
    11641174
    11651175
     
    11791189AcpiOsSignal(UINT32 function, void *info)
    11801190{
    11811191    DEBUG_FUNCTION();
     1192
    11821193    switch (function) {
    11831194        case ACPI_SIGNAL_FATAL:
    11841195#ifdef _KERNEL_MODE
     
    11951206
    11961207    return AE_OK;
    11971208}
     1209
     1210/*
     1211 * Adapted from FreeBSD since the documentation of its intended impl
     1212 * is lacking.
     1213 *  Section 5.2.10.1: global lock acquire/release functions */
     1214#define GL_ACQUIRED     (-1)
     1215#define GL_BUSY         0
     1216#define GL_BIT_PENDING  0x01
     1217#define GL_BIT_OWNED    0x02
     1218#define GL_BIT_MASK     (GL_BIT_PENDING | GL_BIT_OWNED)
     1219
     1220/*
     1221 * Adapted from FreeBSD since the documentation of its intended impl
     1222 * is lacking.
     1223 * Acquire the global lock.  If busy, set the pending bit.  The caller
     1224 * will wait for notification from the BIOS that the lock is available
     1225 * and then attempt to acquire it again.
     1226 */
     1227int
     1228AcpiOsAcquireGlobalLock(uint32 *lock)
     1229{
     1230    uint32 new;
     1231    uint32 old;
     1232
     1233    do {
     1234        old = *lock;
     1235        new = ((old & ~GL_BIT_MASK) | GL_BIT_OWNED) |
     1236                ((old >> 1) & GL_BIT_PENDING);
     1237        atomic_test_and_set(lock, new, old);       
     1238    } while (*lock == old);
     1239    return ((new < GL_BIT_MASK) ? GL_ACQUIRED : GL_BUSY);
     1240}
     1241
     1242/*
     1243 * Adapted from FreeBSD since the documentation of its intended impl
     1244 * is lacking.
     1245 * Release the global lock, returning whether there is a waiter pending.
     1246 * If the BIOS set the pending bit, OSPM must notify the BIOS when it
     1247 * releases the lock.
     1248 */
     1249int
     1250AcpiOsReleaseGlobalLock(uint32 *lock)
     1251{
     1252    uint32 new;
     1253    uint32 old;
     1254
     1255    do {
     1256        old = *lock;
     1257        new = old & ~GL_BIT_MASK;
     1258        atomic_test_and_set(lock, new, old);
     1259    } while (*lock == old);
     1260    return (old & GL_BIT_PENDING);
     1261}