The CGA card gets its clock timings from the ISA bus, so it runs off the same 14.32 MHz base crystal as the motherboard (standard NTSC frequency generators).
This means it is also in sync with the CPU and PIT.
A scanline takes exactly 76 PIT cycles, or 304 CPU cycles.
An entire frame is 262 scanlines, so 262*76 = 19912 PIT cycles or 79648 CPU cycles.
You can find the CGA manual here: www.minuszerodegrees.net/oa/OA%20-%20IB ... 0(CGA).pdf
It contains the default values of the registers for all modes.
These values are the 6845 CRTC's internal registers: http://www.classiccmp.org/dunfield/r/6845.pdf
In graphics mode, you can see the following:
Vertical total: 7Fh (127)
Vertical total adjust: 06h (6)
Vertical displayed: 64h (100)
Vertical sync position: 70h (112)
All these values (except total adjust) should be multiplied by 2 in graphics mode, since CGA works with pairs of even/odd scanlines as 'character rows'.
Vertical total should also be adjusted by one, because 1 row (2 scanlines) is the minimum height of a screen, so vertical total 0 means 1 row.
Vertical sync position should also be adjusted by one
So, if we interpret these values correctly, we get:
Vertical total: 256 scanlines.
Vertical total adjust: 6 scanlines.
Vertical displayed: 200 scanlines.
Vertical sync position: 226.
This gives us a total of 262 scanlines, of which 200 scanlines are visible, and vsync starts at 226.
On the original 6845, vsync is fixed to 16 scanlines. On later ones it can be reprogrammed from 1-15 (taken from the top 4 bits of the horizontal sync width register), but by default the value is 0, which translates to 16 scanlines.
So vsync would be from 226 to 242.
Then a new screen starts, and you have lines 242 to 262 as the 'top border', then it starts displaying the first scanline.
You can do more or less the same for the horizontal case:
Horizontal total: 38h (56)
Horizontal displayed: 28h (40)
Horizontal sync position: 2Dh (45)
Horizontal sync width: 0Ah (10)
These values are in character columns, and in graphics mode you have 8 pixels per column (which is 2 bytes).
So the sync push is 10 columns large, starting at column 45.
Given the clock signal, you should be able to work out the timings in absolute times.