| 336 | } |
| 337 | |
| 338 | int |
| 339 | vatpit_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes, |
| 340 | uint32_t *eax) |
| 341 | { |
| 342 | struct vatpit *vatpit; |
| 343 | struct channel *c; |
| 344 | uint8_t val; |
| 345 | int error; |
| 346 | |
| 347 | vatpit = vm_atpit(vm); |
| 348 | |
| 349 | if (bytes != 1) |
| 350 | return (-1); |
| 351 | |
| 352 | val = *eax; |
| 353 | |
| 354 | if (port == TIMER_MODE) { |
| 355 | if (in) { |
| 356 | VM_CTR0(vatpit->vm, "vatpit attempt to read mode"); |
| 357 | return (-1); |
| 358 | } |
| 359 | |
| 360 | VATPIT_LOCK(vatpit); |
| 361 | error = vatpit_update_mode(vatpit, val); |
| 362 | VATPIT_UNLOCK(vatpit); |
| 363 | |
| 364 | return (error); |
| 365 | } |
| 366 | |
| 367 | /* counter ports */ |
| 368 | KASSERT(port >= TIMER_CNTR0 && port <= TIMER_CNTR2, |
| 369 | ("invalid port 0x%x", port)); |
| 370 | c = &vatpit->channel[port - TIMER_CNTR0]; |
| 371 | |
| 372 | VATPIT_LOCK(vatpit); |
| 373 | if (in && c->slatched) { |
| 374 | /* |
| 375 | * Return the status byte if latched |
| 376 | */ |
| 377 | *eax = c->status; |
| 378 | c->slatched = false; |
| 379 | c->status = 0; |
| 380 | } else if (in) { |
| 381 | /* |
| 382 | * The spec says that once the output latch is completely |
| 383 | * read it should revert to "following" the counter. Use |
| 384 | * the free running counter for this case (i.e. Linux |
| 385 | * TSC calibration). Assuming the access mode is 16-bit, |
| 386 | * toggle the MSB/LSB bit on each read. |
| 387 | */ |
| 388 | if (c->olbyte == 0) { |
| 389 | uint16_t tmp; |
| 390 | |
| 391 | tmp = pit_update_counter(vatpit, c, false); |
| 392 | if (c->frbyte) |
| 393 | tmp >>= 8; |
| 394 | tmp &= 0xff; |
| 395 | *eax = tmp; |
nothing calls this directly
no test coverage detected