The value of MO_VBI_GPCNT doesn't necessarily reflect which pages from
the CX card have made it to main memory. I.e. it's possible for
MO_VBI_GPCNT to return 1 yet the first page is not yet in main
memory.
Previously this was handled by only assuming MO_VBI_GPCNT - 1 have
been written. The -1 here serves as a heuristic that tends to works in
most cases but I've noticed that in some rare cases the GPCNT can be
out of sync by 2 pages. The other side effect is that we start the
capture from 1 page behind the current page which may not be desirable
either.
To address this we only trust the value of MO_VBI_GPCNT after an
interrupt has occurred. We round the value down to the last value that
we know should have caused the interrupt. Note that if the interrupt
is delayed by an excessively long time then we may read a MO_VBI_GPCNT
value that corresponds to a subsequent interrupt that hasn't occured
yet. In practice the interrupt occurs every 0x200 pages, which ends up
being 0x200 * 4096 / 40000000 = ~52ms and latency that high should
almost never occur in practice.
An alternative here is to not read MO_VBI_GPCNT at all and to instead
just count interrupts. This is what the official cx88 Linux driver
does. I opted not to take that route to avoid excessive churn and I'm
not sure if interrupts queue. If interrupts indeed do queue, then that
may be an even more robust approach.
The value of MO_VBI_GPCNT doesn't necessarily reflect which pages from the CX card have made it to main memory. I.e. it's possible for MO_VBI_GPCNT to return 1 yet the first page is not yet in main memory.
Previously this was handled by only assuming MO_VBI_GPCNT - 1 have been written. The -1 here serves as a heuristic that tends to works in most cases but I've noticed that in some rare cases the GPCNT can be out of sync by 2 pages. The other side effect is that we start the capture from 1 page behind the current page which may not be desirable either.
To address this we only trust the value of MO_VBI_GPCNT after an interrupt has occurred. We round the value down to the last value that we know should have caused the interrupt. Note that if the interrupt is delayed by an excessively long time then we may read a MO_VBI_GPCNT value that corresponds to a subsequent interrupt that hasn't occured yet. In practice the interrupt occurs every 0x200 pages, which ends up being 0x200 * 4096 / 40000000 = ~52ms and latency that high should almost never occur in practice.
An alternative here is to not read MO_VBI_GPCNT at all and to instead just count interrupts. This is what the official cx88 Linux driver does. I opted not to take that route to avoid excessive churn and I'm not sure if interrupts queue. If interrupts indeed do queue, then that may be an even more robust approach.