mirror of https://gitlab.com/nakst/essence
				
				
				
			centralised list of io ports
This commit is contained in:
		
							parent
							
								
									411ff15698
								
							
						
					
					
						commit
						e546555787
					
				| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
#include <module.h>
 | 
			
		||||
#include <kernel/x86_64.h>
 | 
			
		||||
 | 
			
		||||
struct BGADisplay : KGraphicsTarget {
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -38,8 +39,8 @@ void BGADeviceAttached(KDevice *_parent) {
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ProcessorOut16(0x01CE, 0 /* version */);
 | 
			
		||||
	uint16_t version = ProcessorIn16(0x01CF);
 | 
			
		||||
	ProcessorOut16(IO_BGA_INDEX, 0 /* version */);
 | 
			
		||||
	uint16_t version = ProcessorIn16(IO_BGA_DATA);
 | 
			
		||||
	KernelLog(LOG_INFO, "BGA", "version", "Detected version %X%X.\n", version >> 8, version);
 | 
			
		||||
 | 
			
		||||
	if (version < 0xB0C0 || version > 0xB0C5) {
 | 
			
		||||
| 
						 | 
				
			
			@ -48,25 +49,25 @@ void BGADeviceAttached(KDevice *_parent) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// Set the mode.
 | 
			
		||||
	ProcessorOut16(0x01CE, 4 /* enable */);
 | 
			
		||||
	ProcessorOut16(0x01CF, 0);
 | 
			
		||||
	ProcessorOut16(0x01CE, 1 /* x resolution */);
 | 
			
		||||
	ProcessorOut16(0x01CF, BGA_RESOLUTION_WIDTH);
 | 
			
		||||
	ProcessorOut16(0x01CE, 2 /* y resolution */);
 | 
			
		||||
	ProcessorOut16(0x01CF, BGA_RESOLUTION_HEIGHT);
 | 
			
		||||
	ProcessorOut16(0x01CE, 3 /* bpp */);
 | 
			
		||||
	ProcessorOut16(0x01CF, 32);
 | 
			
		||||
	ProcessorOut16(0x01CE, 4 /* enable */);
 | 
			
		||||
	ProcessorOut16(0x01CF, 0x41 /* linear frame-buffer */);
 | 
			
		||||
	ProcessorOut16(IO_BGA_INDEX, 4 /* enable */);
 | 
			
		||||
	ProcessorOut16(IO_BGA_DATA, 0);
 | 
			
		||||
	ProcessorOut16(IO_BGA_INDEX, 1 /* x resolution */);
 | 
			
		||||
	ProcessorOut16(IO_BGA_DATA, BGA_RESOLUTION_WIDTH);
 | 
			
		||||
	ProcessorOut16(IO_BGA_INDEX, 2 /* y resolution */);
 | 
			
		||||
	ProcessorOut16(IO_BGA_DATA, BGA_RESOLUTION_HEIGHT);
 | 
			
		||||
	ProcessorOut16(IO_BGA_INDEX, 3 /* bpp */);
 | 
			
		||||
	ProcessorOut16(IO_BGA_DATA, 32);
 | 
			
		||||
	ProcessorOut16(IO_BGA_INDEX, 4 /* enable */);
 | 
			
		||||
	ProcessorOut16(IO_BGA_DATA, 0x41 /* linear frame-buffer */);
 | 
			
		||||
 | 
			
		||||
	// Setup the graphics target.
 | 
			
		||||
	device->updateScreen = BGAUpdateScreen;
 | 
			
		||||
	device->debugPutBlock = BGADebugPutBlock;
 | 
			
		||||
	device->debugClearScreen = BGADebugClearScreen;
 | 
			
		||||
	ProcessorOut16(0x01CE, 1 /* x resolution */);
 | 
			
		||||
	device->screenWidth = ProcessorIn16(0x01CF);
 | 
			
		||||
	ProcessorOut16(0x01CE, 2 /* y resolution */);
 | 
			
		||||
	device->screenHeight = ProcessorIn16(0x01CF);
 | 
			
		||||
	ProcessorOut16(IO_BGA_INDEX, 1 /* x resolution */);
 | 
			
		||||
	device->screenWidth = ProcessorIn16(IO_BGA_DATA);
 | 
			
		||||
	ProcessorOut16(IO_BGA_INDEX, 2 /* y resolution */);
 | 
			
		||||
	device->screenHeight = ProcessorIn16(IO_BGA_DATA);
 | 
			
		||||
 | 
			
		||||
	// Register the display.
 | 
			
		||||
	KernelLog(LOG_INFO, "BGA", "register target", 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@
 | 
			
		|||
// TODO Inserting/removing ATAPI devices.
 | 
			
		||||
 | 
			
		||||
#include <module.h>
 | 
			
		||||
#include <kernel/x86_64.h>
 | 
			
		||||
 | 
			
		||||
#define ATA_BUSES 2
 | 
			
		||||
#define ATA_DRIVES (ATA_BUSES * 2)
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +10,7 @@
 | 
			
		|||
#define ATA_TIMEOUT (10000)
 | 
			
		||||
#define ATAPI_SECTOR_SIZE (2048)
 | 
			
		||||
 | 
			
		||||
#define ATA_REGISTER(_bus, _reg) (_reg != -1 ? ((_bus ? 0x170 : 0x1F0) + _reg) : (_bus ? 0x376 : 0x3F6))
 | 
			
		||||
#define ATA_REGISTER(_bus, _reg) (_reg != -1 ? ((_bus ? IO_ATA_1 : IO_ATA_2) + _reg) : (_bus ? IO_ATA_3 : IO_ATA_4))
 | 
			
		||||
#define ATA_IRQ(_bus) (_bus ? 15 : 14)
 | 
			
		||||
#define ATA_DATA 0
 | 
			
		||||
#define ATA_FEATURES 1
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,13 +2,7 @@
 | 
			
		|||
 | 
			
		||||
#include <module.h>
 | 
			
		||||
 | 
			
		||||
#define PCI_CONFIG	(0xCF8)
 | 
			
		||||
#define PCI_DATA	(0xCFC)
 | 
			
		||||
 | 
			
		||||
struct PCIController : KDevice {
 | 
			
		||||
	inline uint32_t ReadConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, int size = 32);
 | 
			
		||||
	inline void WriteConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value, int size = 32);
 | 
			
		||||
 | 
			
		||||
#define PCI_BUS_DO_NOT_SCAN 0
 | 
			
		||||
#define PCI_BUS_SCAN_NEXT 1
 | 
			
		||||
#define PCI_BUS_SCANNED 2
 | 
			
		||||
| 
						 | 
				
			
			@ -174,65 +168,30 @@ void KPCIDevice::WriteBAR64(uintptr_t index, uintptr_t offset, uint64_t value) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Spinlock since some drivers need to access it in IRQs (e.g. ACPICA).
 | 
			
		||||
// Also can't be part of PCIController since PCI is initialised after ACPICA.
 | 
			
		||||
static KSpinlock configSpaceSpinlock; 
 | 
			
		||||
 | 
			
		||||
static PCIController *pci;
 | 
			
		||||
 | 
			
		||||
uint32_t KPCIReadConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, int size) {
 | 
			
		||||
	return pci->ReadConfig(bus, device, function, offset, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KPCIWriteConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value, int size) {
 | 
			
		||||
	pci->WriteConfig(bus, device, function, offset, value, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t PCIController::ReadConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, int size) {
 | 
			
		||||
	KSpinlockAcquire(&configSpaceSpinlock);
 | 
			
		||||
	EsDefer(KSpinlockRelease(&configSpaceSpinlock));
 | 
			
		||||
	if (offset & 3) KernelPanic("PCIController::ReadConfig - offset is not 4-byte aligned.");
 | 
			
		||||
	ProcessorOut32(PCI_CONFIG, (uint32_t) (0x80000000 | (bus << 16) | (device << 11) | (function << 8) | offset));
 | 
			
		||||
	if (size == 8) return ProcessorIn8(PCI_DATA);
 | 
			
		||||
	if (size == 16) return ProcessorIn16(PCI_DATA);
 | 
			
		||||
	if (size == 32) return ProcessorIn32(PCI_DATA);
 | 
			
		||||
	KernelPanic("PCIController::ReadConfig - Invalid size %d.\n", size);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PCIController::WriteConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value, int size) {
 | 
			
		||||
	KSpinlockAcquire(&configSpaceSpinlock);
 | 
			
		||||
	EsDefer(KSpinlockRelease(&configSpaceSpinlock));
 | 
			
		||||
	if (offset & 3) KernelPanic("PCIController::WriteConfig - offset is not 4-byte aligned.");
 | 
			
		||||
	ProcessorOut32(PCI_CONFIG, (uint32_t) (0x80000000 | (bus << 16) | (device << 11) | (function << 8) | offset));
 | 
			
		||||
	if (size == 8) ProcessorOut8(PCI_DATA, value);
 | 
			
		||||
	else if (size == 16) ProcessorOut16(PCI_DATA, value);
 | 
			
		||||
	else if (size == 32) ProcessorOut32(PCI_DATA, value);
 | 
			
		||||
	else KernelPanic("PCIController::WriteConfig - Invalid size %d.\n", size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KPCIDevice::WriteConfig8(uintptr_t offset, uint8_t value) {
 | 
			
		||||
	pci->WriteConfig(bus, slot, function, offset, value, 8);
 | 
			
		||||
	KPCIWriteConfig(bus, slot, function, offset, value, 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t KPCIDevice::ReadConfig8(uintptr_t offset) {
 | 
			
		||||
	return pci->ReadConfig(bus, slot, function, offset, 8);
 | 
			
		||||
	return KPCIReadConfig(bus, slot, function, offset, 8);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KPCIDevice::WriteConfig16(uintptr_t offset, uint16_t value) {
 | 
			
		||||
	pci->WriteConfig(bus, slot, function, offset, value, 16);
 | 
			
		||||
	KPCIWriteConfig(bus, slot, function, offset, value, 16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint16_t KPCIDevice::ReadConfig16(uintptr_t offset) {
 | 
			
		||||
	return pci->ReadConfig(bus, slot, function, offset, 16);
 | 
			
		||||
	return KPCIReadConfig(bus, slot, function, offset, 16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KPCIDevice::WriteConfig32(uintptr_t offset, uint32_t value) {
 | 
			
		||||
	pci->WriteConfig(bus, slot, function, offset, value, 32);
 | 
			
		||||
	KPCIWriteConfig(bus, slot, function, offset, value, 32);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t KPCIDevice::ReadConfig32(uintptr_t offset) {
 | 
			
		||||
	return pci->ReadConfig(bus, slot, function, offset, 32);
 | 
			
		||||
	return KPCIReadConfig(bus, slot, function, offset, 32);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool KPCIDevice::EnableSingleInterrupt(KIRQHandler irqHandler, void *context, const char *cOwnerName) {
 | 
			
		||||
| 
						 | 
				
			
			@ -440,11 +399,11 @@ bool EnumeratePCIDrivers(KInstalledDriver *driver, KDevice *_device) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void PCIController::EnumerateFunction(int bus, int device, int function, int *busesToScan) {
 | 
			
		||||
	uint32_t deviceID = ReadConfig(bus, device, function, 0x00);
 | 
			
		||||
	uint32_t deviceID = KPCIReadConfig(bus, device, function, 0x00);
 | 
			
		||||
	if ((deviceID & 0xFFFF) == 0xFFFF) return;
 | 
			
		||||
 | 
			
		||||
	uint32_t deviceClass = ReadConfig(bus, device, function, 0x08);
 | 
			
		||||
	uint32_t interruptInformation = ReadConfig(bus, device, function, 0x3C);
 | 
			
		||||
	uint32_t deviceClass = KPCIReadConfig(bus, device, function, 0x08);
 | 
			
		||||
	uint32_t interruptInformation = KPCIReadConfig(bus, device, function, 0x3C);
 | 
			
		||||
 | 
			
		||||
	KPCIDevice *pciDevice = (KPCIDevice *) KDeviceCreate("PCI function", this, sizeof(KPCIDevice));
 | 
			
		||||
	if (!pciDevice) return;
 | 
			
		||||
| 
						 | 
				
			
			@ -460,8 +419,8 @@ void PCIController::EnumerateFunction(int bus, int device, int function, int *bu
 | 
			
		|||
	pciDevice->interruptPin = (interruptInformation >> 8) & 0xFF;
 | 
			
		||||
	pciDevice->interruptLine = (interruptInformation >> 0) & 0xFF;
 | 
			
		||||
 | 
			
		||||
	pciDevice->deviceID = ReadConfig(bus, device, function, 0);
 | 
			
		||||
	pciDevice->subsystemID = ReadConfig(bus, device, function, 0x2C);
 | 
			
		||||
	pciDevice->deviceID = KPCIReadConfig(bus, device, function, 0);
 | 
			
		||||
	pciDevice->subsystemID = KPCIReadConfig(bus, device, function, 0x2C);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < 6; i++) {
 | 
			
		||||
		pciDevice->baseAddresses[i] = pciDevice->ReadConfig32(0x10 + 4 * i);
 | 
			
		||||
| 
						 | 
				
			
			@ -485,7 +444,7 @@ void PCIController::EnumerateFunction(int bus, int device, int function, int *bu
 | 
			
		|||
			pciDevice->interruptPin, pciDevice->interruptLine);
 | 
			
		||||
 | 
			
		||||
	if (pciDevice->classCode == 0x06 && pciDevice->subclassCode == 0x04 /* PCI bridge */) {
 | 
			
		||||
		uint8_t secondaryBus = (ReadConfig(bus, device, function, 0x18) >> 8) & 0xFF; 
 | 
			
		||||
		uint8_t secondaryBus = (KPCIReadConfig(bus, device, function, 0x18) >> 8) & 0xFF; 
 | 
			
		||||
 | 
			
		||||
		if (busScanStates[secondaryBus] == PCI_BUS_DO_NOT_SCAN) {
 | 
			
		||||
			KernelLog(LOG_INFO, "PCI", "PCI bridge", "PCI bridge to bus %d.\n", secondaryBus);
 | 
			
		||||
| 
						 | 
				
			
			@ -504,13 +463,13 @@ void PCIController::EnumerateFunction(int bus, int device, int function, int *bu
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void PCIController::Enumerate() {
 | 
			
		||||
	uint32_t baseHeaderType = ReadConfig(0, 0, 0, 0x0C);
 | 
			
		||||
	uint32_t baseHeaderType = KPCIReadConfig(0, 0, 0, 0x0C);
 | 
			
		||||
	int baseBuses = (baseHeaderType & 0x80) ? 8 : 1;
 | 
			
		||||
 | 
			
		||||
	int busesToScan = 0;
 | 
			
		||||
 | 
			
		||||
	for (int baseBus = 0; baseBus < baseBuses; baseBus++) {
 | 
			
		||||
		uint32_t deviceID = ReadConfig(0, 0, baseBus, 0x00);
 | 
			
		||||
		uint32_t deviceID = KPCIReadConfig(0, 0, baseBus, 0x00);
 | 
			
		||||
		if ((deviceID & 0xFFFF) == 0xFFFF) continue;
 | 
			
		||||
		busScanStates[baseBus] = PCI_BUS_SCAN_NEXT;
 | 
			
		||||
		busesToScan++;
 | 
			
		||||
| 
						 | 
				
			
			@ -530,10 +489,10 @@ void PCIController::Enumerate() {
 | 
			
		|||
			busesToScan--;
 | 
			
		||||
 | 
			
		||||
			for (int device = 0; device < 32; device++) {
 | 
			
		||||
				uint32_t deviceID = ReadConfig(bus, device, 0, 0x00);
 | 
			
		||||
				uint32_t deviceID = KPCIReadConfig(bus, device, 0, 0x00);
 | 
			
		||||
				if ((deviceID & 0xFFFF) == 0xFFFF) continue;
 | 
			
		||||
 | 
			
		||||
				uint32_t headerType = (ReadConfig(bus, device, 0, 0x0C) >> 16) & 0xFF;
 | 
			
		||||
				uint32_t headerType = (KPCIReadConfig(bus, device, 0, 0x0C) >> 16) & 0xFF;
 | 
			
		||||
				int functions = (headerType & 0x80) ? 8 : 1;
 | 
			
		||||
 | 
			
		||||
				for (int function = 0; function < functions; function++) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
// TODO Scrolling.
 | 
			
		||||
 | 
			
		||||
#include <module.h>
 | 
			
		||||
#include <kernel/x86_64.h>
 | 
			
		||||
 | 
			
		||||
struct PS2Update {
 | 
			
		||||
	union {
 | 
			
		||||
| 
						 | 
				
			
			@ -176,11 +177,6 @@ uint16_t scancodeConversionTable2[] = {
 | 
			
		|||
#define PS2_FIRST_IRQ 		(1)
 | 
			
		||||
#define PS2_SECOND_IRQ		(12)
 | 
			
		||||
 | 
			
		||||
// Ports.
 | 
			
		||||
#define PS2_PORT_DATA		(0x60)
 | 
			
		||||
#define PS2_PORT_STATUS		(0x64)
 | 
			
		||||
#define PS2_PORT_COMMAND	(0x64)
 | 
			
		||||
 | 
			
		||||
// Keyboard commands.
 | 
			
		||||
#define PS2_KEYBOARD_RESET	(0xFF)
 | 
			
		||||
#define PS2_KEYBOARD_ENABLE	(0xF4)
 | 
			
		||||
| 
						 | 
				
			
			@ -217,16 +213,16 @@ void PS2KeyboardUpdated(EsGeneric _update) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void PS2::WaitInputBuffer() {
 | 
			
		||||
	while (ProcessorIn8(PS2_PORT_STATUS) & PS2_INPUT_FULL);
 | 
			
		||||
	while (ProcessorIn8(IO_PS2_STATUS) & PS2_INPUT_FULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PS2::PollRead(uint8_t *value, bool forMouse) {
 | 
			
		||||
	uint8_t status = ProcessorIn8(PS2_PORT_STATUS);
 | 
			
		||||
	uint8_t status = ProcessorIn8(IO_PS2_STATUS);
 | 
			
		||||
	if (status & PS2_MOUSE_BYTE && !forMouse) return false;
 | 
			
		||||
	if (!(status & PS2_MOUSE_BYTE) && forMouse) return false;
 | 
			
		||||
 | 
			
		||||
	if (status & PS2_OUTPUT_FULL) {
 | 
			
		||||
		*value = ProcessorIn8(PS2_PORT_DATA);
 | 
			
		||||
		*value = ProcessorIn8(IO_PS2_DATA);
 | 
			
		||||
 | 
			
		||||
		if (*value == 0xE1 && !forMouse) {
 | 
			
		||||
			KDebugKeyPressed();
 | 
			
		||||
| 
						 | 
				
			
			@ -382,60 +378,60 @@ bool PS2IRQHandler(uintptr_t interruptIndex, void *) {
 | 
			
		|||
void PS2::DisableDevices(unsigned which) {
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	// EsPrint("ps2 first write...\n");
 | 
			
		||||
	if (which & 1) ProcessorOut8(PS2_PORT_COMMAND, PS2_DISABLE_FIRST);
 | 
			
		||||
	if (which & 1) ProcessorOut8(IO_PS2_COMMAND, PS2_DISABLE_FIRST);
 | 
			
		||||
	// EsPrint("ps2 first write end\n");
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	if (which & 2) ProcessorOut8(PS2_PORT_COMMAND, PS2_DISABLE_SECOND);
 | 
			
		||||
	if (which & 2) ProcessorOut8(IO_PS2_COMMAND, PS2_DISABLE_SECOND);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PS2::EnableDevices(unsigned which) {
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	if (which & 1) ProcessorOut8(PS2_PORT_COMMAND, PS2_ENABLE_FIRST);
 | 
			
		||||
	if (which & 1) ProcessorOut8(IO_PS2_COMMAND, PS2_ENABLE_FIRST);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	if (which & 2) ProcessorOut8(PS2_PORT_COMMAND, PS2_ENABLE_SECOND);
 | 
			
		||||
	if (which & 2) ProcessorOut8(IO_PS2_COMMAND, PS2_ENABLE_SECOND);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PS2::FlushOutputBuffer() {
 | 
			
		||||
	while (ProcessorIn8(PS2_PORT_STATUS) & PS2_OUTPUT_FULL) {
 | 
			
		||||
		ProcessorIn8(PS2_PORT_DATA);
 | 
			
		||||
	while (ProcessorIn8(IO_PS2_STATUS) & PS2_OUTPUT_FULL) {
 | 
			
		||||
		ProcessorIn8(IO_PS2_DATA);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PS2::SendCommand(uint8_t command) {
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, command);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, command);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t PS2::ReadByte(KTimeout *timeout) {
 | 
			
		||||
	while (!(ProcessorIn8(PS2_PORT_STATUS) & PS2_OUTPUT_FULL) && !timeout->Hit());
 | 
			
		||||
	return ProcessorIn8(PS2_PORT_DATA);
 | 
			
		||||
	while (!(ProcessorIn8(IO_PS2_STATUS) & PS2_OUTPUT_FULL) && !timeout->Hit());
 | 
			
		||||
	return ProcessorIn8(IO_PS2_DATA);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void PS2::WriteByte(KTimeout *timeout, uint8_t value) {
 | 
			
		||||
	while ((ProcessorIn8(PS2_PORT_STATUS) & PS2_INPUT_FULL) && !timeout->Hit());
 | 
			
		||||
	while ((ProcessorIn8(IO_PS2_STATUS) & PS2_INPUT_FULL) && !timeout->Hit());
 | 
			
		||||
	if (timeout->Hit()) return;
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, value);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool PS2::SetupKeyboard(KTimeout *timeout) {
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, PS2_KEYBOARD_ENABLE);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, PS2_KEYBOARD_ENABLE);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, PS2_KEYBOARD_SCANCODE_SET);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, PS2_KEYBOARD_SCANCODE_SET);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, 0);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, 0);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	scancodeSet = ReadByte(timeout) & 3;
 | 
			
		||||
	KernelLog(LOG_INFO, "PS/2", "scancode set", "Keyboard reports it is using scancode set %d.\n", scancodeSet);
 | 
			
		||||
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, PS2_KEYBOARD_REPEAT);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, PS2_KEYBOARD_REPEAT);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, 0);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, 0);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -443,14 +439,14 @@ bool PS2::SetupKeyboard(KTimeout *timeout) {
 | 
			
		|||
 | 
			
		||||
bool PS2::SetMouseRate(KTimeout *timeout, int rate) {
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, PS2_MOUSE_SAMPLE_RATE);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, PS2_MOUSE_SAMPLE_RATE);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, rate);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, rate);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -459,9 +455,9 @@ bool PS2::SetupMouse(KTimeout *timeout) {
 | 
			
		|||
	// TODO Mouse with scroll wheel detection.
 | 
			
		||||
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, PS2_MOUSE_RESET);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, PS2_MOUSE_RESET);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	if (ReadByte(timeout) != 0xAA) return false;
 | 
			
		||||
	if (ReadByte(timeout) != 0x00) return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -469,26 +465,26 @@ bool PS2::SetupMouse(KTimeout *timeout) {
 | 
			
		|||
	if (!SetMouseRate(timeout, 100)) return false;
 | 
			
		||||
	if (!SetMouseRate(timeout, 80)) return false;
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, 0xF2);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, 0xF2);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	mouseType = ReadByte(timeout);
 | 
			
		||||
	if (!SetMouseRate(timeout, 100)) return false;
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, PS2_MOUSE_RESOLUTION);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, PS2_MOUSE_RESOLUTION);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, 3);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, 3);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_SECOND);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_DATA, PS2_MOUSE_ENABLE);
 | 
			
		||||
	ProcessorOut8(IO_PS2_DATA, PS2_MOUSE_ENABLE);
 | 
			
		||||
	if (ReadByte(timeout) != 0xFA) return false;
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -515,10 +511,10 @@ void PS2::Initialise(KDevice *parentDevice) {
 | 
			
		|||
	FlushOutputBuffer();
 | 
			
		||||
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_READ_CONFIG);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_READ_CONFIG);
 | 
			
		||||
	uint8_t configurationByte = ReadByte(&timeout);
 | 
			
		||||
	WaitInputBuffer();
 | 
			
		||||
	ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_CONFIG);
 | 
			
		||||
	ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_CONFIG);
 | 
			
		||||
	WriteByte(&timeout, configurationByte & ~(PS2_FIRST_IRQ_MASK | PS2_SECOND_IRQ_MASK | PS2_TRANSLATION));
 | 
			
		||||
	if (timeout.Hit()) return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -529,7 +525,7 @@ void PS2::Initialise(KDevice *parentDevice) {
 | 
			
		|||
	if (configurationByte & PS2_SECOND_CLOCK) {
 | 
			
		||||
		EnableDevices(2);
 | 
			
		||||
		WaitInputBuffer();
 | 
			
		||||
		ProcessorOut8(PS2_PORT_COMMAND, PS2_READ_CONFIG);
 | 
			
		||||
		ProcessorOut8(IO_PS2_COMMAND, PS2_READ_CONFIG);
 | 
			
		||||
		configurationByte = ReadByte(&timeout);
 | 
			
		||||
		if (!(configurationByte & PS2_SECOND_CLOCK)) {
 | 
			
		||||
			hasMouse = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -539,7 +535,7 @@ void PS2::Initialise(KDevice *parentDevice) {
 | 
			
		|||
 | 
			
		||||
	{
 | 
			
		||||
		WaitInputBuffer();
 | 
			
		||||
		ProcessorOut8(PS2_PORT_COMMAND, PS2_TEST_FIRST);
 | 
			
		||||
		ProcessorOut8(IO_PS2_COMMAND, PS2_TEST_FIRST);
 | 
			
		||||
		uint8_t b = ReadByte(&timeout);
 | 
			
		||||
		if (b) return;
 | 
			
		||||
		if (timeout.Hit()) return;
 | 
			
		||||
| 
						 | 
				
			
			@ -548,7 +544,7 @@ void PS2::Initialise(KDevice *parentDevice) {
 | 
			
		|||
 | 
			
		||||
	if (hasMouse) {
 | 
			
		||||
		WaitInputBuffer();
 | 
			
		||||
		ProcessorOut8(PS2_PORT_COMMAND, PS2_TEST_SECOND);
 | 
			
		||||
		ProcessorOut8(IO_PS2_COMMAND, PS2_TEST_SECOND);
 | 
			
		||||
		if (!ReadByte(&timeout) && !timeout.Hit()) channels = 2;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -565,10 +561,10 @@ void PS2::Initialise(KDevice *parentDevice) {
 | 
			
		|||
 | 
			
		||||
	{
 | 
			
		||||
		WaitInputBuffer();
 | 
			
		||||
		ProcessorOut8(PS2_PORT_COMMAND, PS2_READ_CONFIG);
 | 
			
		||||
		ProcessorOut8(IO_PS2_COMMAND, PS2_READ_CONFIG);
 | 
			
		||||
		uint8_t configurationByte = ReadByte(&timeout);
 | 
			
		||||
		WaitInputBuffer();
 | 
			
		||||
		ProcessorOut8(PS2_PORT_COMMAND, PS2_WRITE_CONFIG);
 | 
			
		||||
		ProcessorOut8(IO_PS2_COMMAND, PS2_WRITE_CONFIG);
 | 
			
		||||
		WriteByte(&timeout, configurationByte | PS2_FIRST_IRQ_MASK | PS2_SECOND_IRQ_MASK);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,10 +11,10 @@ uint8_t RTCRead(uint8_t index, bool convertFromBCD, bool convertFrom12Hour) {
 | 
			
		|||
 | 
			
		||||
	for (uint8_t i = 0; i < 10; i++) {
 | 
			
		||||
		// Write the index a few times to delay before reading.
 | 
			
		||||
		ProcessorOut8(0x70, index);
 | 
			
		||||
		ProcessorOut8(IO_RTC_INDEX, index);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	uint8_t value = ProcessorIn8(0x71);
 | 
			
		||||
	uint8_t value = ProcessorIn8(IO_RTC_DATA);
 | 
			
		||||
 | 
			
		||||
	if (convertFromBCD) {
 | 
			
		||||
		value = (value >> 4) * 10 + (value & 0xF);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -129,28 +129,6 @@ void InitialiseVBE(KDevice *parent) {
 | 
			
		|||
 | 
			
		||||
#if 0
 | 
			
		||||
 | 
			
		||||
#define VGA_AC_INDEX 0x3C0
 | 
			
		||||
#define VGA_AC_WRITE 0x3C0
 | 
			
		||||
#define VGA_AC_READ  0x3C1
 | 
			
		||||
 | 
			
		||||
#define VGA_MISC_WRITE 0x3C2
 | 
			
		||||
#define VGA_MISC_READ  0x3CC
 | 
			
		||||
 | 
			
		||||
#define VGA_SEQ_INDEX 0x3C4
 | 
			
		||||
#define VGA_SEQ_DATA  0x3C5
 | 
			
		||||
 | 
			
		||||
#define VGA_DAC_READ_INDEX  0x3C7
 | 
			
		||||
#define VGA_DAC_WRITE_INDEX 0x3C8
 | 
			
		||||
#define VGA_DAC_DATA        0x3C9
 | 
			
		||||
 | 
			
		||||
#define VGA_GC_INDEX 0x3CE
 | 
			
		||||
#define VGA_GC_DATA  0x3CF
 | 
			
		||||
 | 
			
		||||
#define VGA_CRTC_INDEX 0x3D4
 | 
			
		||||
#define VGA_CRTC_DATA  0x3D5
 | 
			
		||||
 | 
			
		||||
#define VGA_INSTAT_READ 0x3DA
 | 
			
		||||
 | 
			
		||||
uint8_t vgaMode18[] = {
 | 
			
		||||
	0xE3, 0x03, 0x01, 0x08, 0x00, 0x06, 0x5F, 0x4F,
 | 
			
		||||
	0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40,
 | 
			
		||||
| 
						 | 
				
			
			@ -182,8 +160,8 @@ void VGAUpdateScreen(uint8_t *_source, uint8_t *modifiedScanlineBitset, KModifie
 | 
			
		|||
	for (int plane = 0; plane < 4; plane++) {
 | 
			
		||||
		uint8_t *source = _source;
 | 
			
		||||
 | 
			
		||||
		ProcessorOut8(VGA_SEQ_INDEX, 2);
 | 
			
		||||
		ProcessorOut8(VGA_SEQ_DATA, 1 << plane);
 | 
			
		||||
		ProcessorOut8(IO_VGA_SEQ_INDEX, 2);
 | 
			
		||||
		ProcessorOut8(IO_VGA_SEQ_DATA, 1 << plane);
 | 
			
		||||
 | 
			
		||||
		for (uintptr_t y_ = 0; y_ < VGA_SCREEN_HEIGHT / 8; y_++) {
 | 
			
		||||
			if (modifiedScanlineBitset[y_] == 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -227,8 +205,8 @@ void VGAUpdateScreen(uint8_t *_source, uint8_t *modifiedScanlineBitset, KModifie
 | 
			
		|||
 | 
			
		||||
void VGAPutBlock(uintptr_t x, uintptr_t y, bool toggle) {
 | 
			
		||||
	for (int plane = 0; plane < 4; plane++) {
 | 
			
		||||
		ProcessorOut8(VGA_SEQ_INDEX, 2);
 | 
			
		||||
		ProcessorOut8(VGA_SEQ_DATA, 1 << plane);
 | 
			
		||||
		ProcessorOut8(IO_VGA_SEQ_INDEX, 2);
 | 
			
		||||
		ProcessorOut8(IO_VGA_SEQ_DATA, 1 << plane);
 | 
			
		||||
		
 | 
			
		||||
		if (toggle) {
 | 
			
		||||
			vgaAddress[y * 80 + x / 8] ^= 1 << (7 - (x & 7));
 | 
			
		||||
| 
						 | 
				
			
			@ -240,8 +218,8 @@ void VGAPutBlock(uintptr_t x, uintptr_t y, bool toggle) {
 | 
			
		|||
 | 
			
		||||
void VGAClearScreen() {
 | 
			
		||||
	for (int plane = 0; plane < 4; plane++) {
 | 
			
		||||
		ProcessorOut8(VGA_SEQ_INDEX, 2);
 | 
			
		||||
		ProcessorOut8(VGA_SEQ_DATA, 1 << plane);
 | 
			
		||||
		ProcessorOut8(IO_VGA_SEQ_INDEX, 2);
 | 
			
		||||
		ProcessorOut8(IO_VGA_SEQ_DATA, 1 << plane);
 | 
			
		||||
		EsMemoryZero((void *) vgaAddress, VGA_SCREEN_WIDTH / 8 * VGA_SCREEN_HEIGHT);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -253,19 +231,19 @@ void InitialiseVGA(KDevice *parent) {
 | 
			
		|||
 | 
			
		||||
	vgaAddress = (uint8_t *) MMMapPhysical(MMGetKernelSpace(), 0xA0000, 0x10000, MM_REGION_WRITE_COMBINING);
 | 
			
		||||
	uint8_t *registers = vgaMode18;
 | 
			
		||||
	ProcessorOut8(VGA_MISC_WRITE, *registers++);
 | 
			
		||||
	for (int i = 0; i < 5; i++) { ProcessorOut8(VGA_SEQ_INDEX, i); ProcessorOut8(VGA_SEQ_DATA, *registers++); }
 | 
			
		||||
	ProcessorOut8(VGA_CRTC_INDEX, 0x03);
 | 
			
		||||
	ProcessorOut8(VGA_CRTC_DATA, ProcessorIn8(VGA_CRTC_DATA) | 0x80);
 | 
			
		||||
	ProcessorOut8(VGA_CRTC_INDEX, 0x11);
 | 
			
		||||
	ProcessorOut8(VGA_CRTC_DATA, ProcessorIn8(VGA_CRTC_DATA) & ~0x80);
 | 
			
		||||
	ProcessorOut8(IO_VGA_MISC_WRITE, *registers++);
 | 
			
		||||
	for (int i = 0; i < 5; i++) { ProcessorOut8(IO_VGA_SEQ_INDEX, i); ProcessorOut8(IO_VGA_SEQ_DATA, *registers++); }
 | 
			
		||||
	ProcessorOut8(IO_VGA_CRTC_INDEX, 0x03);
 | 
			
		||||
	ProcessorOut8(IO_VGA_CRTC_DATA, ProcessorIn8(IO_VGA_CRTC_DATA) | 0x80);
 | 
			
		||||
	ProcessorOut8(IO_VGA_CRTC_INDEX, 0x11);
 | 
			
		||||
	ProcessorOut8(IO_VGA_CRTC_DATA, ProcessorIn8(IO_VGA_CRTC_DATA) & ~0x80);
 | 
			
		||||
	registers[0x03] |= 0x80;
 | 
			
		||||
	registers[0x11] &= ~0x80;
 | 
			
		||||
	for (int i = 0; i < 25; i++) { ProcessorOut8(VGA_CRTC_INDEX, i); ProcessorOut8(VGA_CRTC_DATA, *registers++); }
 | 
			
		||||
	for (int i = 0; i < 9; i++) { ProcessorOut8(VGA_GC_INDEX, i); ProcessorOut8(VGA_GC_DATA, *registers++); }
 | 
			
		||||
	for (int i = 0; i < 21; i++) { ProcessorIn8(VGA_INSTAT_READ); ProcessorOut8(VGA_AC_INDEX, i); ProcessorOut8(VGA_AC_WRITE, *registers++); }
 | 
			
		||||
	ProcessorIn8(VGA_INSTAT_READ);
 | 
			
		||||
	ProcessorOut8(VGA_AC_INDEX, 0x20);
 | 
			
		||||
	for (int i = 0; i < 25; i++) { ProcessorOut8(IO_VGA_CRTC_INDEX, i); ProcessorOut8(IO_VGA_CRTC_DATA, *registers++); }
 | 
			
		||||
	for (int i = 0; i < 9; i++) { ProcessorOut8(IO_VGA_GC_INDEX, i); ProcessorOut8(IO_VGA_GC_DATA, *registers++); }
 | 
			
		||||
	for (int i = 0; i < 21; i++) { ProcessorIn8(IO_VGA_INSTAT_READ); ProcessorOut8(IO_VGA_AC_INDEX, i); ProcessorOut8(IO_VGA_AC_WRITE, *registers++); }
 | 
			
		||||
	ProcessorIn8(IO_VGA_INSTAT_READ);
 | 
			
		||||
	ProcessorOut8(IO_VGA_AC_INDEX, 0x20);
 | 
			
		||||
 | 
			
		||||
	KGraphicsTarget *target = (KGraphicsTarget *) KDeviceCreate("VGA", parent, sizeof(KGraphicsTarget));
 | 
			
		||||
	target->screenWidth = VGA_SCREEN_WIDTH;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,13 +153,12 @@ KSpinlock ipiLock;
 | 
			
		|||
#include "files.cpp"
 | 
			
		||||
#include "windows.cpp"
 | 
			
		||||
#include "networking.cpp"
 | 
			
		||||
#include "terminal.cpp"
 | 
			
		||||
 | 
			
		||||
#ifdef ENABLE_POSIX_SUBSYSTEM
 | 
			
		||||
#include "posix.cpp"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "terminal.cpp"
 | 
			
		||||
 | 
			
		||||
#ifdef IMPLEMENTATION
 | 
			
		||||
 | 
			
		||||
//////////////////////////////////
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -664,16 +664,16 @@ uint64_t ArchGetTimeFromPITMs() {
 | 
			
		|||
	static uint64_t cumulative = 0, last = 0;
 | 
			
		||||
 | 
			
		||||
	if (!started) {
 | 
			
		||||
		ProcessorOut8(0x43, 0x30);
 | 
			
		||||
		ProcessorOut8(0x40, 0xFF);
 | 
			
		||||
		ProcessorOut8(0x40, 0xFF);
 | 
			
		||||
		ProcessorOut8(IO_PIT_COMMAND, 0x30);
 | 
			
		||||
		ProcessorOut8(IO_PIT_DATA, 0xFF);
 | 
			
		||||
		ProcessorOut8(IO_PIT_DATA, 0xFF);
 | 
			
		||||
		started = true;
 | 
			
		||||
		last = 0xFFFF;
 | 
			
		||||
		return 0;
 | 
			
		||||
	} else {
 | 
			
		||||
		ProcessorOut8(0x43, 0x00);
 | 
			
		||||
		uint16_t x = ProcessorIn8(0x40);
 | 
			
		||||
		x |= (ProcessorIn8(0x40)) << 8;
 | 
			
		||||
		ProcessorOut8(IO_PIT_COMMAND, 0x00);
 | 
			
		||||
		uint16_t x = ProcessorIn8(IO_PIT_DATA);
 | 
			
		||||
		x |= (ProcessorIn8(IO_PIT_DATA)) << 8;
 | 
			
		||||
		cumulative += last - x;
 | 
			
		||||
		if (x > last) cumulative += 0x10000;
 | 
			
		||||
		last = x;
 | 
			
		||||
| 
						 | 
				
			
			@ -682,14 +682,14 @@ uint64_t ArchGetTimeFromPITMs() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void ArchDelay1Ms() {
 | 
			
		||||
	ProcessorOut8(0x43, 0x30);
 | 
			
		||||
	ProcessorOut8(0x40, 0xA9);
 | 
			
		||||
	ProcessorOut8(0x40, 0x04);
 | 
			
		||||
	ProcessorOut8(IO_PIT_COMMAND, 0x30);
 | 
			
		||||
	ProcessorOut8(IO_PIT_DATA, 0xA9);
 | 
			
		||||
	ProcessorOut8(IO_PIT_DATA, 0x04);
 | 
			
		||||
 | 
			
		||||
	while (true) {
 | 
			
		||||
		ProcessorOut8(0x43, 0xE2);
 | 
			
		||||
		ProcessorOut8(IO_PIT_COMMAND, 0xE2);
 | 
			
		||||
 | 
			
		||||
		if (ProcessorIn8(0x40) & (1 << 7)) {
 | 
			
		||||
		if (ProcessorIn8(IO_PIT_DATA) & (1 << 7)) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1307,4 +1307,30 @@ uintptr_t GetBootloaderInformationOffset() {
 | 
			
		|||
	return bootloaderInformationOffset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Spinlock since some drivers need to access it in IRQs (e.g. ACPICA).
 | 
			
		||||
static KSpinlock pciConfigSpinlock; 
 | 
			
		||||
 | 
			
		||||
uint32_t KPCIReadConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, int size) {
 | 
			
		||||
	KSpinlockAcquire(&pciConfigSpinlock);
 | 
			
		||||
	EsDefer(KSpinlockRelease(&pciConfigSpinlock));
 | 
			
		||||
	if (offset & 3) KernelPanic("KPCIReadConfig - offset is not 4-byte aligned.");
 | 
			
		||||
	ProcessorOut32(IO_PCI_CONFIG, (uint32_t) (0x80000000 | (bus << 16) | (device << 11) | (function << 8) | offset));
 | 
			
		||||
	if (size == 8) return ProcessorIn8(IO_PCI_DATA);
 | 
			
		||||
	if (size == 16) return ProcessorIn16(IO_PCI_DATA);
 | 
			
		||||
	if (size == 32) return ProcessorIn32(IO_PCI_DATA);
 | 
			
		||||
	KernelPanic("PCIController::ReadConfig - Invalid size %d.\n", size);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void KPCIWriteConfig(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value, int size) {
 | 
			
		||||
	KSpinlockAcquire(&pciConfigSpinlock);
 | 
			
		||||
	EsDefer(KSpinlockRelease(&pciConfigSpinlock));
 | 
			
		||||
	if (offset & 3) KernelPanic("KPCIWriteConfig - offset is not 4-byte aligned.");
 | 
			
		||||
	ProcessorOut32(IO_PCI_CONFIG, (uint32_t) (0x80000000 | (bus << 16) | (device << 11) | (function << 8) | offset));
 | 
			
		||||
	if (size == 8) ProcessorOut8(IO_PCI_DATA, value);
 | 
			
		||||
	else if (size == 16) ProcessorOut16(IO_PCI_DATA, value);
 | 
			
		||||
	else if (size == 32) ProcessorOut32(IO_PCI_DATA, value);
 | 
			
		||||
	else KernelPanic("PCIController::WriteConfig - Invalid size %d.\n", size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,50 @@
 | 
			
		|||
#define LOW_MEMORY_MAP_START (0xFFFFFE0000000000)
 | 
			
		||||
#define LOW_MEMORY_LIMIT (0x100000) // The first 1MB is mapped here.
 | 
			
		||||
 | 
			
		||||
// --------------------------------- Standardised IO ports.
 | 
			
		||||
 | 
			
		||||
#define IO_PIC_1_COMMAND		(0x0020)
 | 
			
		||||
#define IO_PIC_1_DATA			(0x0021)
 | 
			
		||||
#define IO_PIT_DATA			(0x0040)
 | 
			
		||||
#define IO_PIT_COMMAND			(0x0043)
 | 
			
		||||
#define IO_PS2_DATA			(0x0060)
 | 
			
		||||
#define IO_PC_SPEAKER			(0x0061)
 | 
			
		||||
#define IO_PS2_STATUS			(0x0064)
 | 
			
		||||
#define IO_PS2_COMMAND			(0x0064)
 | 
			
		||||
#define IO_RTC_INDEX 			(0x0070)
 | 
			
		||||
#define IO_RTC_DATA 			(0x0071)
 | 
			
		||||
#define IO_PIC_2_COMMAND		(0x00A0)
 | 
			
		||||
#define IO_PIC_2_DATA			(0x00A1)
 | 
			
		||||
#define IO_BGA_INDEX			(0x01CE)
 | 
			
		||||
#define IO_BGA_DATA			(0x01CF)
 | 
			
		||||
#define IO_ATA_1			(0x0170) // To 0x0177.
 | 
			
		||||
#define IO_ATA_2			(0x01F0) // To 0x01F7.
 | 
			
		||||
#define IO_COM_4			(0x02E8) // To 0x02EF.
 | 
			
		||||
#define IO_COM_2			(0x02F8) // To 0x02FF.
 | 
			
		||||
#define IO_ATA_3			(0x0376)
 | 
			
		||||
#define IO_VGA_AC_INDEX 		(0x03C0)
 | 
			
		||||
#define IO_VGA_AC_WRITE 		(0x03C0)
 | 
			
		||||
#define IO_VGA_AC_READ  		(0x03C1)
 | 
			
		||||
#define IO_VGA_MISC_WRITE 		(0x03C2)
 | 
			
		||||
#define IO_VGA_MISC_READ  		(0x03CC)
 | 
			
		||||
#define IO_VGA_SEQ_INDEX 		(0x03C4)
 | 
			
		||||
#define IO_VGA_SEQ_DATA  		(0x03C5)
 | 
			
		||||
#define IO_VGA_DAC_READ_INDEX  		(0x03C7)
 | 
			
		||||
#define IO_VGA_DAC_WRITE_INDEX 		(0x03C8)
 | 
			
		||||
#define IO_VGA_DAC_DATA        		(0x03C9)
 | 
			
		||||
#define IO_VGA_GC_INDEX 		(0x03CE)
 | 
			
		||||
#define IO_VGA_GC_DATA  		(0x03CF)
 | 
			
		||||
#define IO_VGA_CRTC_INDEX 		(0x03D4)
 | 
			
		||||
#define IO_VGA_CRTC_DATA  		(0x03D5)
 | 
			
		||||
#define IO_VGA_INSTAT_READ 		(0x03DA)
 | 
			
		||||
#define IO_COM_3			(0x03E8) // To 0x03EF.
 | 
			
		||||
#define IO_ATA_4			(0x03F6)
 | 
			
		||||
#define IO_COM_1			(0x03F8) // To 0x03FF.
 | 
			
		||||
#define IO_PCI_CONFIG 			(0x0CF8)
 | 
			
		||||
#define IO_PCI_DATA   			(0x0CFC)
 | 
			
		||||
 | 
			
		||||
// --------------------------------- Forward declarations.
 | 
			
		||||
 | 
			
		||||
extern "C" uint64_t ProcessorReadCR3();
 | 
			
		||||
extern "C" void gdt_data();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue