mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-16 21:34:10 +00:00
Add support for the PIT 'readback' command -- based on a patch by grehan@.
Approved by: grehan (co-mentor)
This commit is contained in:
parent
1d6be92ac6
commit
c46ff7fa0b
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=264651
|
@ -56,6 +56,15 @@ static MALLOC_DEFINE(M_VATPIT, "atpit", "bhyve virtual atpit (8254)");
|
|||
#define TIMER_MODE_MASK 0x0f
|
||||
#define TIMER_SEL_READBACK 0xc0
|
||||
|
||||
#define TIMER_STS_OUT 0x80
|
||||
#define TIMER_STS_NULLCNT 0x40
|
||||
|
||||
#define TIMER_RB_LCTR 0x20
|
||||
#define TIMER_RB_LSTATUS 0x10
|
||||
#define TIMER_RB_CTR_2 0x08
|
||||
#define TIMER_RB_CTR_1 0x04
|
||||
#define TIMER_RB_CTR_0 0x02
|
||||
|
||||
#define TMR2_OUT_STS 0x20
|
||||
|
||||
#define PIT_8254_FREQ 1193182
|
||||
|
@ -73,6 +82,8 @@ struct channel {
|
|||
sbintime_t now_sbt; /* uptime when counter was loaded */
|
||||
uint8_t cr[2];
|
||||
uint8_t ol[2];
|
||||
bool slatched; /* status latched */
|
||||
uint8_t status;
|
||||
int crbyte;
|
||||
int olbyte;
|
||||
int frbyte;
|
||||
|
@ -198,6 +209,7 @@ pit_update_counter(struct vatpit *vatpit, struct channel *c, bool latch)
|
|||
*/
|
||||
c->initial = TIMER_DIV(PIT_8254_FREQ, 100);
|
||||
c->now_sbt = sbinuptime();
|
||||
c->status &= ~TIMER_STS_NULLCNT;
|
||||
}
|
||||
|
||||
delta_ticks = (sbinuptime() - c->now_sbt) / vatpit->freq_sbt;
|
||||
|
@ -213,6 +225,57 @@ pit_update_counter(struct vatpit *vatpit, struct channel *c, bool latch)
|
|||
return (lval);
|
||||
}
|
||||
|
||||
static int
|
||||
pit_readback1(struct vatpit *vatpit, int channel, uint8_t cmd)
|
||||
{
|
||||
struct channel *c;
|
||||
|
||||
c = &vatpit->channel[channel];
|
||||
|
||||
/*
|
||||
* Latch the count/status of the timer if not already latched.
|
||||
* N.B. that the count/status latch-select bits are active-low.
|
||||
*/
|
||||
if (!(cmd & TIMER_RB_LCTR) && !c->olbyte) {
|
||||
(void) pit_update_counter(vatpit, c, true);
|
||||
}
|
||||
|
||||
if (!(cmd & TIMER_RB_LSTATUS) && !c->slatched) {
|
||||
c->slatched = true;
|
||||
/*
|
||||
* For mode 0, see if the elapsed time is greater
|
||||
* than the initial value - this results in the
|
||||
* output pin being set to 1 in the status byte.
|
||||
*/
|
||||
if (c->mode == TIMER_INTTC && vatpit_get_out(vatpit, channel))
|
||||
c->status |= TIMER_STS_OUT;
|
||||
else
|
||||
c->status &= ~TIMER_STS_OUT;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
pit_readback(struct vatpit *vatpit, uint8_t cmd)
|
||||
{
|
||||
int error;
|
||||
|
||||
/*
|
||||
* The readback command can apply to all timers.
|
||||
*/
|
||||
error = 0;
|
||||
if (cmd & TIMER_RB_CTR_0)
|
||||
error = pit_readback1(vatpit, 0, cmd);
|
||||
if (!error && cmd & TIMER_RB_CTR_1)
|
||||
error = pit_readback1(vatpit, 1, cmd);
|
||||
if (!error && cmd & TIMER_RB_CTR_2)
|
||||
error = pit_readback1(vatpit, 2, cmd);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
vatpit_update_mode(struct vatpit *vatpit, uint8_t val)
|
||||
{
|
||||
|
@ -224,7 +287,7 @@ vatpit_update_mode(struct vatpit *vatpit, uint8_t val)
|
|||
mode = val & TIMER_MODE_MASK;
|
||||
|
||||
if (sel == TIMER_SEL_READBACK)
|
||||
return (-1);
|
||||
return (pit_readback(vatpit, val));
|
||||
|
||||
if (rw != TIMER_LATCH && rw != TIMER_16BIT)
|
||||
return (-1);
|
||||
|
@ -247,6 +310,7 @@ vatpit_update_mode(struct vatpit *vatpit, uint8_t val)
|
|||
else {
|
||||
c->mode = mode;
|
||||
c->olbyte = 0; /* reset latch after reprogramming */
|
||||
c->status |= TIMER_STS_NULLCNT;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
@ -287,7 +351,14 @@ vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes,
|
|||
c = &vatpit->channel[port - TIMER_CNTR0];
|
||||
|
||||
VATPIT_LOCK(vatpit);
|
||||
if (in) {
|
||||
if (in && c->slatched) {
|
||||
/*
|
||||
* Return the status byte if latched
|
||||
*/
|
||||
*eax = c->status;
|
||||
c->slatched = false;
|
||||
c->status = 0;
|
||||
} else if (in) {
|
||||
/*
|
||||
* The spec says that once the output latch is completely
|
||||
* read it should revert to "following" the counter. Use
|
||||
|
@ -309,6 +380,7 @@ vatpit_handler(void *vm, int vcpuid, bool in, int port, int bytes,
|
|||
} else {
|
||||
c->cr[c->crbyte++] = *eax;
|
||||
if (c->crbyte == 2) {
|
||||
c->status &= ~TIMER_STS_NULLCNT;
|
||||
c->frbyte = 0;
|
||||
c->crbyte = 0;
|
||||
c->initial = c->cr[0] | (uint16_t)c->cr[1] << 8;
|
||||
|
|
Loading…
Reference in a new issue