/**
 * A module for interfacing with the $(I Programmable Interval Timer), also called PIT.
 *
 * Copyright: Â© 2015-2017, Dan Printzell
 * License: $(LINK2 https://www.mozilla.org/en-US/MPL/2.0/, Mozilla Public License Version 2.0)
 *  (See accompanying file LICENSE)
 * Authors: $(LINK2 https://vild.io/, Dan Printzell)
 */
module arch.amd64.pit;

import stl.register;

@safe static struct PIT {
public static:
	void init(uint hz = 1000) @trusted {
		import stl.arch.amd64.idt : IDT, irq;
		import stl.arch.amd64.ioport : outp;

		IDT.register(irq(0), &_onTick);
		_hz = hz;
		uint divisor = 1193180 / hz;
		outp!ubyte(0x43, 0x36);

		ubyte l = cast(ubyte)(divisor & 0xFF);
		ubyte h = cast(ubyte)((divisor >> 8) & 0xFF);

		outp!ubyte(0x40, l);
		outp!ubyte(0x40, h);
	}

	void earlySleep(size_t amount) @trusted {
		size_t endAt = _counter + amount;

		while (_counter < endAt) {
			asm pure @trusted nothrow @nogc {
				hlt;
			}
		}
	}

private static:
	__gshared bool _enabled;
	__gshared uint _hz;
	__gshared size_t _counter;

	void _onTick(Registers* regs) @trusted {
		_counter++;
	}
}
