Ticket #4762: acpi_fix_global_locking.patch
File acpi_fix_global_locking.patch, 7.1 KB (added by , 15 years ago) |
---|
-
src/add-ons/kernel/bus_managers/acpi/include/platform/achaiku.h
160 160 161 161 #define ACPI_FLUSH_CPU_CACHE() __asm __volatile("wbinvd"); 162 162 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 */ 164 extern int AcpiOsAcquireGlobalLock(uint32 *lock); 165 extern int AcpiOsReleaseGlobalLock(uint32 *lock); 166 167 #define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) do { \ 168 (Acq) = AcpiOsAcquireGlobalLock(&((GLptr)->GlobalLock)); \ 180 169 } while (0) 181 170 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)); \ 194 173 } while (0) 195 174 196 175 #else /* _KERNEL_MODE */ -
src/add-ons/kernel/bus_managers/acpi/oshaiku.c
157 157 dprintf("acpi[%ld]: %s\n", find_thread(NULL), __PRETTY_FUNCTION__); 158 158 # define DEBUG_FUNCTION_F(x, y...) \ 159 159 dprintf("acpi[%ld]: %s(" x ")\n", find_thread(NULL), __PRETTY_FUNCTION__, y); 160 # if DEBUG_OSHAIKU = 1160 # if DEBUG_OSHAIKU == 1 161 161 // No verbose debugging, do nothing 162 162 # define DEBUG_FUNCTION_V() 163 163 # define DEBUG_FUNCTION_VF(x, y...) … … 243 243 if (status == AE_OK) 244 244 sACPIRoot = address; 245 245 } 246 dprintf("AcpiOsGetRootPointer returning %p\n", (void *)sACPIRoot);247 246 return sACPIRoot; 248 247 #else 249 248 return AeLocalGetRootPointer(); … … 445 444 #ifdef _KERNEL_MODE 446 445 void *there; 447 446 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 449 449 DEBUG_FUNCTION_F("addr: 0x%08lx; length: %lu; mapped: %p; area: %ld", 450 450 (addr_t)where, (size_t)length, there, area); 451 451 if (area < 0) { 452 452 dprintf("ACPI: cannot map memory at 0x%08x, length %d\n", where, length); 453 453 return NULL; 454 454 } 455 456 455 return there; 457 456 #else 458 457 return NULL; … … 611 610 break; 612 611 } 613 612 } 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); 615 615 return result; 616 616 } 617 617 … … 890 890 AcpiOsReadPciConfiguration(ACPI_PCI_ID *pciId, UINT32 reg, void *value, 891 891 UINT32 width) 892 892 { 893 uint32 *val; 894 val = value; 893 895 #ifdef _KERNEL_MODE 894 UINT32 val = gPCIManager->read_pci_config(895 pciId->Bus, pciId->Device, pciId->Function, reg, width / 8);896 896 DEBUG_FUNCTION(); 897 897 898 switch (width) { 898 899 case 8: 899 *(UINT8 *) value = val;900 break;901 900 case 16: 902 *(UINT16 *) value = val;903 break;904 901 case 32: 905 *(UINT32 *) value = val; 902 *val = gPCIManager->read_pci_config( 903 pciId->Bus, pciId->Device, pciId->Function, reg, width / 8); 906 904 break; 907 905 default: 908 dprintf("AcpiOsReadPciConfiguration unhandled width: %u\n", width);909 906 return AE_ERROR; 910 907 } 911 908 return AE_OK; … … 983 980 break; 984 981 985 982 default: 986 dprintf("AcpiOsReadPort: unhandeld width: %u\n", width);987 983 return AE_ERROR; 988 984 } 989 985 … … 1027 1023 break; 1028 1024 1029 1025 default: 1030 dprintf("AcpiOsWritePort: unhandeld width: %u\n", width);1031 1026 return AE_ERROR; 1032 1027 } 1033 1028 … … 1107 1102 * 1108 1103 *****************************************************************************/ 1109 1104 BOOLEAN 1110 AcpiOsReadable(void *pointer, ACPI_SIZE Length)1105 AcpiOsReadable(void *pointer, ACPI_SIZE length) 1111 1106 { 1112 //TODO: Look if this is really ok. 1107 area_id id; 1108 area_info info; 1113 1109 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); 1115 1118 } 1116 1119 1117 1120 … … 1130 1133 BOOLEAN 1131 1134 AcpiOsWritable(void *pointer, ACPI_SIZE length) 1132 1135 { 1133 //TODO: Look if this is really ok. 1136 area_id id; 1137 area_info info; 1134 1138 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); 1136 1147 } 1137 1148 1138 1149 … … 1154 1165 AcpiOsGetThreadId() 1155 1166 { 1156 1167 thread_id thread = find_thread(NULL); 1157 return thread;1158 1168 1159 //TODO: Look if this is needed.1169 //TODO: Handle if thread_id is 0. 1160 1170 // ACPI treats a 0 return as an error, 1161 1171 // but we are thread 0 in early boot 1162 //return thread == 0 ? 1 : thread;1172 return thread == 0 ? 1 : thread; 1163 1173 } 1164 1174 1165 1175 … … 1179 1189 AcpiOsSignal(UINT32 function, void *info) 1180 1190 { 1181 1191 DEBUG_FUNCTION(); 1192 1182 1193 switch (function) { 1183 1194 case ACPI_SIGNAL_FATAL: 1184 1195 #ifdef _KERNEL_MODE … … 1195 1206 1196 1207 return AE_OK; 1197 1208 } 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 */ 1227 int 1228 AcpiOsAcquireGlobalLock(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 */ 1249 int 1250 AcpiOsReleaseGlobalLock(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 }