// HAL serial output endpoint. This file owns polling COM1 writes and subscribes serial to HAL text streams. #include #include #include #include #define HAL_COM1_DATA_PORT 0x03F8u #define HAL_COM1_STATUS_PORT 0x03FDu #define HAL_COM1_TX_READY 0x20u static volatile long gSerialWriteLock; // Waits until COM1 can accept one byte. static void HalSerialWaitForTransmit(void) { while ((__inbyte(HAL_COM1_STATUS_PORT) & HAL_COM1_TX_READY) == 0) _mm_pause(); } // Writes one byte to COM1. static void HalSerialWriteByte(uint8_t value) { HalSerialWaitForTransmit(); __outbyte(HAL_COM1_DATA_PORT, value); } // Acquires the normal serial writer lock. static void HalSerialAcquireWriteLock(void) { while (_InterlockedCompareExchange(&gSerialWriteLock, 1, 0) != 0) _mm_pause(); } // Releases the normal serial writer lock. static void HalSerialReleaseWriteLock(void) { _InterlockedExchange(&gSerialWriteLock, 0); } // Writes one output record through polling COM1. static void HalSerialWriteRecord(void* context, const HAL_OUTPUT_RECORD* record) { (void)context; if (!record || !record->Buffer) return; bool emergency = (record->Flags & HAL_OUTPUT_WRITE_EMERGENCY) != 0; uintptr_t interruptFlags = 0; if (!emergency) { interruptFlags = HalDisableInterrupts(); HalSerialAcquireWriteLock(); } for (size_t i = 0; i < record->Length; i++) { char c = record->Buffer[i]; if (c == '\n') HalSerialWriteByte('\r'); HalSerialWriteByte((uint8_t)c); } if (!emergency) { HalSerialReleaseWriteLock(); HalRestoreInterrupts(interruptFlags); } } // Registers the polling serial endpoint. void HalSerialInitialize(HAL_OUTPUT_ROUTER* output) { if (!output || !output->RegisterEndpoint) return; HAL_OUTPUT_ENDPOINT endpoint; endpoint.Name = "serial0"; endpoint.StreamMask = HAL_OUTPUT_STREAM_ALL; endpoint.Capabilities = HAL_OUTPUT_ENDPOINT_PANIC_SAFE; endpoint.Write = HalSerialWriteRecord; endpoint.Context = 0; uint32_t endpointId = HAL_OUTPUT_ENDPOINT_INVALID; if (KSUCCESS(output->RegisterEndpoint(&endpoint, &endpointId))) output->SerialEndpointId = endpointId; }