• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 // Based heavily on GCE VMM's pit.cc.
5 
6 use std::fmt::{self, Display};
7 use std::io::Error as IoError;
8 use std::os::unix::io::AsRawFd;
9 use std::sync::Arc;
10 use std::thread;
11 use std::time::Duration;
12 
13 use bit_field::BitField1;
14 use bit_field::*;
15 use sync::Mutex;
16 use sys_util::{error, warn, Error as SysError, EventFd, Fd, PollContext, PollToken};
17 
18 #[cfg(not(test))]
19 use sys_util::Clock;
20 #[cfg(test)]
21 use sys_util::FakeClock as Clock;
22 
23 #[cfg(test)]
24 use sys_util::FakeTimerFd as TimerFd;
25 #[cfg(not(test))]
26 use sys_util::TimerFd;
27 
28 use crate::BusDevice;
29 
30 // Bitmask for areas of standard (non-ReadBack) Control Word Format. Constant
31 // names are kept the same as Intel PIT data sheet.
32 #[derive(Debug, Clone, Copy, PartialEq, enumn::N)]
33 enum CommandBit {
34     CommandBCD = 0x01,  // Binary/BCD input. x86 only uses binary mode.
35     CommandMode = 0x0e, // Operating Mode (mode 0-5).
36     CommandRW = 0x30,   // Access mode: Choose high/low byte(s) to Read/Write.
37     CommandSC = 0xc0,   // Select Counter/Read-back command.
38 }
39 
40 // Selects which counter is to be used by the associated command in the lower
41 // six bits of the byte. However, if 0xc0 is specified, it indicates that the
42 // command is a "Read-Back", which can latch count and/or status of the
43 // counters selected in the lower bits. See Intel 8254 data sheet for details.
44 #[allow(dead_code)]
45 #[derive(Debug, Clone, Copy, PartialEq, enumn::N)]
46 enum CommandCounter {
47     CommandCounter0 = 0x00, // Select counter 0.
48     CommandCounter1 = 0x40, // Select counter 1.
49     CommandCounter2 = 0x80, // Select counter 2.
50     CommandReadBack = 0xc0, // Execute Read-Back.
51 }
52 
53 // Used for both CommandRW and ReadBackAccess.
54 #[derive(Debug, Clone, Copy, PartialEq, enumn::N)]
55 enum CommandAccess {
56     CommandLatch = 0x00,   // Latch specified counter.
57     CommandRWLeast = 0x10, // Read/Write least significant byte.
58     CommandRWMost = 0x20,  // Read/Write most significant byte.
59     CommandRWBoth = 0x30,  // Read/Write both bytes.
60 }
61 
62 // Used for both CommandMode and ReadBackMode.
63 // For mode 2 & 3, bit 3 is don't care bit (does not matter to be 0 or 1) but
64 // per 8254 spec, should be 0 to insure compatibility with future Intel
65 // products.
66 #[derive(Debug, Clone, Copy, PartialEq, enumn::N)]
67 enum CommandMode {
68     // NOTE:  No h/w modes are currently implemented.
69     CommandInterrupt = 0x00,     // Mode 0, interrupt on terminal count.
70     CommandHWOneShot = 0x02,     // Mode 1, h/w re-triggerable one-shot.
71     CommandRateGen = 0x04,       // Mode 2, rate generator.
72     CommandSquareWaveGen = 0x06, // Mode 3, square wave generator.
73     CommandSWStrobe = 0x08,      // Mode 4, s/w triggered strobe.
74     CommandHWStrobe = 0x0a,      // Mode 5, h/w triggered strobe.
75 }
76 
77 // Bitmask for the latch portion of the ReadBack command.
78 #[derive(Debug, Clone, Copy, PartialEq, enumn::N)]
79 #[rustfmt::skip]  // rustfmt mangles comment indentation for trailing line comments.
80 enum CommandReadBackLatch {
81     CommandRBLatchBits = 0x30,   // Mask bits that determine latching.
82     CommandRBLatchBoth = 0x00,   // Latch both count and status. This should
83                                  // never happen in device, since bit 4 and 5 in
84                                  // read back command are inverted.
85     CommandRBLatchCount = 0x10,  // Latch count.
86     CommandRBLatchStatus = 0x20, // Latch status.
87 }
88 
89 // Bitmask for the counter portion of the ReadBack command.
90 #[derive(Debug, Clone, Copy, PartialEq, enumn::N)]
91 enum CommandReadBackCounters {
92     //CommandRBCounters = 0x0e, // Counters for which to provide ReadBack info.
93     CommandRBCounter2 = 0x08,
94     CommandRBCounter1 = 0x04,
95     CommandRBCounter0 = 0x02,
96 }
97 
98 // Bitmask for the ReadBack status command.
99 #[derive(Debug, Clone, Copy, PartialEq, enumn::N)]
100 #[rustfmt::skip]  // rustfmt mangles comment indentation for last line of this enum.
101 enum ReadBackData {
102     // Output format for ReadBack command.
103     ReadBackOutput = 0x80, // Output pin status.
104     ReadBackNullCount = 0x40, // Whether counter has value.
105     // ReadBackAccess, ReadBackMode, and ReadBackBCD intentionally omitted.
106 }
107 
108 // I/O Port mappings in I/O bus.
109 #[derive(Debug, Clone, Copy, PartialEq, enumn::N)]
110 enum PortIOSpace {
111     PortCounter0Data = 0x40, // Read/write.
112     PortCounter1Data = 0x41, // Read/write.
113     PortCounter2Data = 0x42, // Read/write.
114     PortCommand = 0x43,      // Write only.
115     PortSpeaker = 0x61,      // Read/write.
116 }
117 
118 #[bitfield]
119 #[derive(Clone, Copy, PartialEq)]
120 pub struct SpeakerPortFields {
121     // This field is documented in the chipset spec as NMI status and control
122     // register.  Bits 2, 3, 6, 7 and low level hardware bits that need no
123     // emulation for virtualized environments.  We call it speaker port because
124     // kvm, qemu, linux, and plan9 still call it speaker port, even though it
125     // has these other uses and is called something differently in the spec.
126     gate: BitField1,
127     speaker_on: BitField1,
128     pic_serr: BitField1,
129     iochk_enable: BitField1,
130     // This value changes as part of the refresh frequency of the board for
131     // piix4, this is about 1/15us.
132     refresh_clock: BitField1,
133     output: BitField1,
134     iochk_nmi: BitField1,
135     serr_nmi: BitField1,
136 }
137 
138 // PIT frequency (in Hertz). See http://wiki.osdev.org/pit.
139 const FREQUENCY_HZ: u64 = 1193182;
140 
141 const NUM_OF_COUNTERS: usize = 3;
142 
143 const NANOS_PER_SEC: u64 = 1_000_000_000;
144 
145 const MAX_TIMER_FREQ: u32 = 65536;
146 
147 #[derive(Debug)]
148 pub enum PitError {
149     TimerFdCreateError(SysError),
150     /// Creating PollContext failed.
151     CreatePollContext(SysError),
152     /// Error while polling for events.
153     PollError(SysError),
154     /// Error while trying to create worker thread.
155     SpawnThread(IoError),
156     /// Error while creating event FD.
157     CreateEventFd(SysError),
158     /// Error while cloning event FD for worker thread.
159     CloneEventFd(SysError),
160 }
161 
162 impl Display for PitError {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result163     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
164         use self::PitError::*;
165 
166         match self {
167             TimerFdCreateError(e) => {
168                 write!(f, "failed to create pit counter due to timer fd: {}", e)
169             }
170             CreatePollContext(e) => write!(f, "failed to create poll context: {}", e),
171             PollError(err) => write!(f, "failed to poll events: {}", err),
172             SpawnThread(err) => write!(f, "failed to spawn thread: {}", err),
173             CreateEventFd(err) => write!(f, "failed to create event fd: {}", err),
174             CloneEventFd(err) => write!(f, "failed to clone event fd: {}", err),
175         }
176     }
177 }
178 
179 impl std::error::Error for PitError {}
180 
181 type PitResult<T> = std::result::Result<T, PitError>;
182 
183 pub struct Pit {
184     // Structs that store each counter's state.
185     counters: Vec<Arc<Mutex<PitCounter>>>,
186     // Worker thread to update counter 0's state asynchronously. Counter 0 needs to send interrupts
187     // when timers expire, so it needs asynchronous updates. All other counters need only update
188     // when queried directly by the guest.
189     worker_thread: Option<thread::JoinHandle<PitResult<()>>>,
190     kill_evt: EventFd,
191 }
192 
193 impl Drop for Pit {
drop(&mut self)194     fn drop(&mut self) {
195         if let Err(e) = self.kill_evt.write(1) {
196             error!("failed to kill PIT worker threads: {}", e);
197             return;
198         }
199         if let Some(thread) = self.worker_thread.take() {
200             match thread.join() {
201                 Ok(r) => {
202                     if let Err(e) = r {
203                         error!("pit worker thread exited with error: {}", e)
204                     }
205                 }
206                 Err(e) => error!("pit worker thread panicked: {:?}", e),
207             }
208         }
209     }
210 }
211 
212 impl BusDevice for Pit {
debug_label(&self) -> String213     fn debug_label(&self) -> String {
214         "userspace PIT".to_string()
215     }
216 
write(&mut self, offset: u64, data: &[u8])217     fn write(&mut self, offset: u64, data: &[u8]) {
218         if data.len() != 1 {
219             warn!("Bad write size for Pit: {}", data.len());
220             return;
221         }
222         match PortIOSpace::n(offset as i64) {
223             Some(PortIOSpace::PortCounter0Data) => self.counters[0].lock().write_counter(data[0]),
224             Some(PortIOSpace::PortCounter1Data) => self.counters[1].lock().write_counter(data[0]),
225             Some(PortIOSpace::PortCounter2Data) => self.counters[2].lock().write_counter(data[0]),
226             Some(PortIOSpace::PortCommand) => self.command_write(data[0]),
227             Some(PortIOSpace::PortSpeaker) => self.counters[2].lock().write_speaker(data[0]),
228             None => warn!("PIT: bad write to offset {}", offset),
229         }
230     }
231 
read(&mut self, offset: u64, data: &mut [u8])232     fn read(&mut self, offset: u64, data: &mut [u8]) {
233         if data.len() != 1 {
234             warn!("Bad read size for Pit: {}", data.len());
235             return;
236         }
237         data[0] = match PortIOSpace::n(offset as i64) {
238             Some(PortIOSpace::PortCounter0Data) => self.counters[0].lock().read_counter(),
239             Some(PortIOSpace::PortCounter1Data) => self.counters[1].lock().read_counter(),
240             Some(PortIOSpace::PortCounter2Data) => self.counters[2].lock().read_counter(),
241             // This should function as a no-op, since the specification doesn't allow the
242             // command register to be read. However, software is free to ask for it to
243             // to be read.
244             Some(PortIOSpace::PortCommand) => {
245                 warn!("Ignoring read to command reg");
246                 0
247             }
248             Some(PortIOSpace::PortSpeaker) => self.counters[2].lock().read_speaker(),
249             None => {
250                 warn!("PIT: bad read from offset {}", offset);
251                 return;
252             }
253         };
254     }
255 }
256 
257 impl Pit {
new(interrupt_evt: EventFd, clock: Arc<Mutex<Clock>>) -> PitResult<Pit>258     pub fn new(interrupt_evt: EventFd, clock: Arc<Mutex<Clock>>) -> PitResult<Pit> {
259         let mut counters = Vec::new();
260         let mut interrupt = Some(interrupt_evt);
261         for i in 0..NUM_OF_COUNTERS {
262             let pit_counter = PitCounter::new(i, interrupt, clock.clone())?;
263             counters.push(Arc::new(Mutex::new(pit_counter)));
264             // pass interrupt IrqFd ONLY to counter 0; the rest do not deliver interrupts.
265             interrupt = None;
266         }
267         // We asssert here because:
268         // (a) this code only gets invoked at VM startup
269         // (b) the assert is very loud and would be easy to notice in tests
270         // (c) if we have the wrong number of counters, something is very wrong with the PIT and it
271         // may not make sense to continue operation.
272         assert_eq!(counters.len(), NUM_OF_COUNTERS);
273         let (self_kill_evt, kill_evt) = EventFd::new()
274             .and_then(|e| Ok((e.try_clone()?, e)))
275             .map_err(PitError::CreateEventFd)?;
276         let mut worker = Worker {
277             pit_counter: counters[0].clone(),
278             fd: Fd(counters[0].lock().timer.as_raw_fd()),
279         };
280         let evt = kill_evt.try_clone().map_err(PitError::CloneEventFd)?;
281         let worker_thread = thread::Builder::new()
282             .name("pit counter worker".to_string())
283             .spawn(move || worker.run(evt))
284             .map_err(PitError::SpawnThread)?;
285         Ok(Pit {
286             counters,
287             worker_thread: Some(worker_thread),
288             kill_evt: self_kill_evt,
289         })
290     }
291 
command_write(&mut self, control_word: u8)292     fn command_write(&mut self, control_word: u8) {
293         let command: u16 = (control_word & CommandBit::CommandSC as u8).into();
294         let counter_index: usize = (command >> 6).into();
295         if command == (CommandCounter::CommandReadBack as u16) {
296             // ReadBack commands can apply to multiple counters.
297             if (control_word & (CommandReadBackCounters::CommandRBCounter0 as u8)) != 0 {
298                 self.counters[0].lock().read_back_command(control_word);
299             }
300             if (control_word & (CommandReadBackCounters::CommandRBCounter1 as u8)) != 0 {
301                 self.counters[1].lock().read_back_command(control_word);
302             }
303             if (control_word & (CommandReadBackCounters::CommandRBCounter2 as u8)) != 0 {
304                 self.counters[2].lock().read_back_command(control_word);
305             }
306         } else if (control_word & (CommandBit::CommandRW as u8))
307             == (CommandAccess::CommandLatch as u8)
308         {
309             self.counters[counter_index].lock().latch_counter();
310         } else {
311             self.counters[counter_index]
312                 .lock()
313                 .store_command(control_word);
314         }
315     }
316 }
317 
318 // Each instance of this represents one of the PIT counters. They are used to
319 // implement one-shot and repeating timer alarms. An 8254 has three counters.
320 struct PitCounter {
321     // EventFd to write when asserting an interrupt.
322     interrupt_evt: Option<EventFd>,
323     // Stores the value with which the counter was initialized. Counters are 16-
324     // bit values with an effective range of 1-65536 (65536 represented by 0).
325     reload_value: u16,
326     // Stores value when latch was called.
327     latched_value: u16,
328     // Stores last command from command register.
329     command: u8,
330     // Stores status from readback command
331     status: u8,
332     // Stores time of starting timer. Used for calculating remaining count, if an alarm is
333     // scheduled.
334     start: Option<Clock>,
335     // Current time.
336     clock: Arc<Mutex<Clock>>,
337     // Time when object was created. Used for a 15us counter.
338     creation_time: Clock,
339     // The number of the counter. The behavior for each counter is slightly different.
340     // Note that once a PitCounter is created, this value should never change.
341     counter_id: usize,
342     // Indicates if the low byte has been written in RWBoth.
343     wrote_low_byte: bool,
344     // Indicates if the low byte has been read in RWBoth.
345     read_low_byte: bool,
346     // Indicates whether counter has been latched.
347     latched: bool,
348     // Indicates whether ReadBack status has been latched.
349     status_latched: bool,
350     // Only should be used for counter 2. See http://wiki.osdev.org/PIT.
351     gate: bool,
352     speaker_on: bool,
353     // The starting value for the counter.
354     count: u32,
355     // Indicates whether the current timer is valid.
356     timer_valid: bool,
357     // Timer to set and receive periodic notifications.
358     timer: TimerFd,
359 }
360 
361 impl Drop for PitCounter {
drop(&mut self)362     fn drop(&mut self) {
363         if self.timer_valid {
364             // This should not fail - timer.clear() only fails if timerfd_settime fails, which
365             // only happens due to invalid arguments or bad file descriptors. The arguments to
366             // timerfd_settime are constant, so its arguments won't be invalid, and it manages
367             // the file descriptor safely (we don't use the unsafe FromRawFd) so its file
368             // descriptor will be valid.
369             self.timer.clear().unwrap();
370         }
371     }
372 }
373 
adjust_count(count: u32) -> u32374 fn adjust_count(count: u32) -> u32 {
375     // As per spec 0 means max.
376     if count == 0 {
377         MAX_TIMER_FREQ
378     } else {
379         count
380     }
381 }
382 
383 impl PitCounter {
new( counter_id: usize, interrupt_evt: Option<EventFd>, clock: Arc<Mutex<Clock>>, ) -> PitResult<PitCounter>384     fn new(
385         counter_id: usize,
386         interrupt_evt: Option<EventFd>,
387         clock: Arc<Mutex<Clock>>,
388     ) -> PitResult<PitCounter> {
389         #[cfg(not(test))]
390         let timer = TimerFd::new().map_err(PitError::TimerFdCreateError)?;
391         #[cfg(test)]
392         let timer = TimerFd::new(clock.clone());
393         Ok(PitCounter {
394             interrupt_evt,
395             reload_value: 0,
396             latched_value: 0,
397             command: 0,
398             status: 0,
399             start: None,
400             clock: clock.clone(),
401             creation_time: clock.lock().now(),
402             counter_id,
403             wrote_low_byte: false,
404             read_low_byte: false,
405             latched: false,
406             status_latched: false,
407             gate: false,
408             speaker_on: false,
409             // `count` is undefined in real hardware and can't ever be programmed to 0, so we
410             // initialize it to max to prevent a misbehaving guest from triggering a divide by 0.
411             count: MAX_TIMER_FREQ,
412             timer_valid: false,
413             timer,
414         })
415     }
416 
get_access_mode(&self) -> Option<CommandAccess>417     fn get_access_mode(&self) -> Option<CommandAccess> {
418         CommandAccess::n(self.command & (CommandBit::CommandRW as u8))
419     }
420 
get_command_mode(&self) -> Option<CommandMode>421     fn get_command_mode(&self) -> Option<CommandMode> {
422         CommandMode::n(self.command & CommandBit::CommandMode as u8)
423     }
424 
read_counter(&mut self) -> u8425     fn read_counter(&mut self) -> u8 {
426         if self.status_latched {
427             self.status_latched = false;
428             return self.status;
429         };
430         let data_value: u16 = if self.latched {
431             self.latched_value
432         } else {
433             self.get_read_value()
434         };
435 
436         let access_mode = self.get_access_mode();
437         // Latch may be true without being indicated by the access mode if
438         // a ReadBack was issued.
439         match (access_mode, self.read_low_byte) {
440             (Some(CommandAccess::CommandRWLeast), _) => {
441                 self.latched = false; // Unlatch if only reading the low byte.
442                 (data_value & 0xff) as u8
443             }
444             (Some(CommandAccess::CommandRWBoth), false) => {
445                 self.read_low_byte = true;
446                 (data_value & 0xff) as u8
447             }
448             (Some(CommandAccess::CommandRWBoth), true)
449             | (Some(CommandAccess::CommandRWMost), _) => {
450                 self.read_low_byte = false; // Allow for future reads for RWBoth.
451                 self.latched = false;
452                 (data_value >> 8) as u8
453             }
454             (_, _) => 0, // Default for erroneous call
455         }
456     }
457 
write_counter(&mut self, written_datum: u8)458     fn write_counter(&mut self, written_datum: u8) {
459         let access_mode = self.get_access_mode();
460         let datum: u16 = written_datum.into();
461         let mut should_start_timer = true;
462         self.reload_value = match access_mode {
463             Some(CommandAccess::CommandRWLeast) => datum,
464             Some(CommandAccess::CommandRWMost) => datum << 8,
465             Some(CommandAccess::CommandRWBoth) => {
466                 // In kCommandRWBoth mode, the first guest write is the low byte and the
467                 // the second guest write is the high byte.  The timer isn't started
468                 // until after the second byte is written.
469                 if self.wrote_low_byte {
470                     self.wrote_low_byte = false;
471                     self.reload_value | (datum << 8)
472                 } else {
473                     self.wrote_low_byte = true;
474                     should_start_timer = false; // Don't start until high byte written.
475                     datum
476                 }
477             }
478             _ => {
479                 should_start_timer = false;
480                 self.reload_value
481             }
482         };
483         if should_start_timer {
484             let reload: u32 = self.reload_value.into();
485             self.load_and_start_timer(reload);
486         }
487     }
488 
get_output(&self) -> bool489     fn get_output(&self) -> bool {
490         let ticks_passed = self.get_ticks_passed();
491         let count: u64 = self.count.into();
492         match self.get_command_mode() {
493             Some(CommandMode::CommandInterrupt) => ticks_passed >= count,
494             Some(CommandMode::CommandHWOneShot) => ticks_passed < count,
495             Some(CommandMode::CommandRateGen) => ticks_passed != 0 && ticks_passed % count == 0,
496             Some(CommandMode::CommandSquareWaveGen) => ticks_passed < (count + 1) / 2,
497             Some(CommandMode::CommandSWStrobe) | Some(CommandMode::CommandHWStrobe) => {
498                 ticks_passed == count
499             }
500             None => {
501                 warn!("Invalid command mode based on command: {:#x}", self.command);
502                 false
503             }
504         }
505     }
506 
read_speaker(&self) -> u8507     fn read_speaker(&self) -> u8 {
508         // Refresh clock is a value independent of the actual
509         // counter that goes up and down approx every 15 us (~66000/s).
510         let us = self
511             .clock
512             .lock()
513             .now()
514             .duration_since(&self.creation_time)
515             .subsec_micros();
516         let refresh_clock = us % 15 == 0;
517         let mut speaker = SpeakerPortFields::new();
518         speaker.set_gate(self.gate.into());
519         speaker.set_speaker_on(self.speaker_on.into());
520         speaker.set_iochk_enable(0);
521         speaker.set_refresh_clock(refresh_clock.into());
522         speaker.set_output(self.get_output().into());
523         speaker.set_iochk_nmi(0);
524         speaker.set_serr_nmi(0);
525         speaker.get(/*offset=*/ 0, /*width=*/ 8) as u8
526     }
527 
write_speaker(&mut self, datum: u8)528     fn write_speaker(&mut self, datum: u8) {
529         let mut speaker = SpeakerPortFields::new();
530         speaker.set(/*offset=*/ 0, /*width=*/ 8, datum.into());
531         let new_gate = speaker.get_gate() != 0;
532         match self.get_command_mode() {
533             Some(CommandMode::CommandInterrupt) | Some(CommandMode::CommandSWStrobe) => (),
534             Some(_) => {
535                 if new_gate && !self.gate {
536                     self.start = Some(self.clock.lock().now());
537                 }
538             }
539             None => {
540                 warn!("Invalid command mode based on command {:#x}", self.command);
541                 return;
542             }
543         }
544         self.speaker_on = speaker.get_speaker_on() != 0;
545         self.gate = new_gate;
546     }
547 
load_and_start_timer(&mut self, initial_count: u32)548     fn load_and_start_timer(&mut self, initial_count: u32) {
549         self.count = adjust_count(initial_count);
550         self.start_timer();
551     }
552 
start_timer(&mut self)553     fn start_timer(&mut self) {
554         self.start = Some(self.clock.lock().now());
555 
556         // Counter 0 is the only counter that generates interrupts, so we
557         // don't need to set a timer for the other two counters.
558         if self.counter_id != 0 {
559             return;
560         }
561 
562         let timer_len = Duration::from_nanos(u64::from(self.count) * NANOS_PER_SEC / FREQUENCY_HZ);
563 
564         let period_ns = match self.get_command_mode() {
565             Some(CommandMode::CommandInterrupt)
566             | Some(CommandMode::CommandHWOneShot)
567             | Some(CommandMode::CommandSWStrobe)
568             | Some(CommandMode::CommandHWStrobe) => Duration::new(0, 0),
569             Some(CommandMode::CommandRateGen) | Some(CommandMode::CommandSquareWaveGen) => {
570                 timer_len
571             }
572             // Don't arm timer if invalid mode.
573             None => {
574                 // This will still result in start being set to the current time.
575                 // Per spec:
576                 //   A new initial count may be written to a Counter at any time without affecting
577                 //   the Counter’s programmed Mode in any way. Counting will be affected as
578                 //   described in the Mode definitions. The new count must follow the programmed
579                 //   count format
580                 // It's unclear whether setting `self.start` in this case is entirely compliant,
581                 // but the spec is fairly quiet on expected behavior in error cases, so OSs
582                 // shouldn't enter invalid modes in the first place.  If they do, and then try to
583                 // get out of it by first setting the counter then the command, this behavior will
584                 // (perhaps) be minimally surprising, but arguments can be made for other behavior.
585                 // It's uncertain if this behavior matches real PIT hardware.
586                 warn!("Invalid command mode based on command {:#x}", self.command);
587                 return;
588             }
589         };
590 
591         self.safe_arm_timer(timer_len, period_ns);
592         self.timer_valid = true;
593     }
594 
read_back_command(&mut self, control_word: u8)595     fn read_back_command(&mut self, control_word: u8) {
596         let latch_cmd =
597             CommandReadBackLatch::n(control_word & CommandReadBackLatch::CommandRBLatchBits as u8);
598         match latch_cmd {
599             Some(CommandReadBackLatch::CommandRBLatchCount) => {
600                 self.latch_counter();
601             }
602             Some(CommandReadBackLatch::CommandRBLatchStatus) => {
603                 self.latch_status();
604             }
605             _ => warn!(
606                 "Unexpected ReadBackLatch. control_word: {:#x}",
607                 control_word
608             ),
609         };
610     }
611 
latch_counter(&mut self)612     fn latch_counter(&mut self) {
613         if self.latched {
614             return;
615         }
616 
617         self.latched_value = self.get_read_value();
618         self.latched = true;
619         self.read_low_byte = false;
620     }
621 
latch_status(&mut self)622     fn latch_status(&mut self) {
623         // Including BCD here, even though it currently never gets used.
624         self.status = self.command
625             & (CommandBit::CommandRW as u8
626                 | CommandBit::CommandMode as u8
627                 | CommandBit::CommandBCD as u8);
628         if self.start.is_none() {
629             self.status |= ReadBackData::ReadBackNullCount as u8;
630         }
631         if self.get_output() {
632             self.status |= ReadBackData::ReadBackOutput as u8;
633         }
634         self.status_latched = true;
635     }
636 
store_command(&mut self, datum: u8)637     fn store_command(&mut self, datum: u8) {
638         self.command = datum;
639         self.latched = false;
640 
641         // If a new RW command is written, cancel the current timer.
642         if self.timer_valid {
643             self.start = None;
644             self.timer_valid = false;
645             // See the comment in the impl of Drop for PitCounter for justification of the unwrap()
646             self.timer.clear().unwrap();
647         }
648 
649         self.wrote_low_byte = false;
650         self.read_low_byte = false;
651     }
652 
timer_handler(&mut self)653     fn timer_handler(&mut self) {
654         if let Err(e) = self.timer.wait() {
655             // Under the current timerfd implementation (as of Jan 2019), this failure shouldn't
656             // happen but implementation details may change in the future, and the failure
657             // cases are complex to reason about. Because of this, avoid unwrap().
658             error!("pit: timer wait unexpectedly failed: {}", e);
659             return;
660         }
661         let mode = self.get_command_mode();
662         if mode == Some(CommandMode::CommandRateGen)
663             || mode == Some(CommandMode::CommandSquareWaveGen)
664         {
665             // Reset the start time for timer modes that repeat.
666             self.start = Some(self.clock.lock().now());
667         }
668 
669         // For square wave mode, this isn't quite accurate to the spec, but the
670         // difference isn't meaningfully visible to the guest in any important way,
671         // and the code is simpler without the special case.
672         if let Some(interrupt) = &mut self.interrupt_evt {
673             // This is safe because the file descriptor is nonblocking and we're writing 1.
674             interrupt.write(1).unwrap();
675         }
676     }
677 
safe_arm_timer(&mut self, mut due: Duration, period: Duration)678     fn safe_arm_timer(&mut self, mut due: Duration, period: Duration) {
679         if due == Duration::new(0, 0) {
680             due = Duration::from_nanos(1);
681         }
682 
683         if let Err(e) = self.timer.reset(due, Some(period)) {
684             error!("failed to reset timer: {}", e);
685         }
686     }
687 
get_ticks_passed(&self) -> u64688     fn get_ticks_passed(&self) -> u64 {
689         match &self.start {
690             None => 0,
691             Some(t) => {
692                 let dur = self.clock.lock().now().duration_since(t);
693                 let dur_ns: u64 = dur.as_secs() * NANOS_PER_SEC + u64::from(dur.subsec_nanos());
694                 (dur_ns * FREQUENCY_HZ / NANOS_PER_SEC)
695             }
696         }
697     }
698 
get_read_value(&self) -> u16699     fn get_read_value(&self) -> u16 {
700         match self.start {
701             None => 0,
702             Some(_) => {
703                 let count: u64 = adjust_count(self.reload_value.into()).into();
704                 let ticks_passed = self.get_ticks_passed();
705                 match self.get_command_mode() {
706                     Some(CommandMode::CommandInterrupt)
707                     | Some(CommandMode::CommandHWOneShot)
708                     | Some(CommandMode::CommandSWStrobe)
709                     | Some(CommandMode::CommandHWStrobe) => {
710                         if ticks_passed > count {
711                             // Some risk of raciness here in that the count may return a value
712                             // indicating that the count has expired when the interrupt hasn't
713                             // yet been injected.
714                             0
715                         } else {
716                             ((count - ticks_passed) & 0xFFFF) as u16
717                         }
718                     }
719                     Some(CommandMode::CommandRateGen) => (count - (ticks_passed % count)) as u16,
720                     Some(CommandMode::CommandSquareWaveGen) => {
721                         (count - ((ticks_passed * 2) % count)) as u16
722                     }
723                     None => {
724                         warn!("Invalid command mode: command = {:#x}", self.command);
725                         0
726                     }
727                 }
728             }
729         }
730     }
731 }
732 
733 struct Worker {
734     pit_counter: Arc<Mutex<PitCounter>>,
735     fd: Fd,
736 }
737 
738 impl Worker {
run(&mut self, kill_evt: EventFd) -> PitResult<()>739     fn run(&mut self, kill_evt: EventFd) -> PitResult<()> {
740         #[derive(PollToken)]
741         enum Token {
742             // The timer expired.
743             TimerExpire,
744             // The parent thread requested an exit.
745             Kill,
746         }
747 
748         let poll_ctx: PollContext<Token> = PollContext::new()
749             .and_then(|pc| pc.add(&self.fd, Token::TimerExpire).and(Ok(pc)))
750             .and_then(|pc| pc.add(&kill_evt, Token::Kill).and(Ok(pc)))
751             .map_err(PitError::CreatePollContext)?;
752 
753         loop {
754             let events = poll_ctx.wait().map_err(PitError::PollError)?;
755             for event in events.iter_readable() {
756                 match event.token() {
757                     Token::TimerExpire => {
758                         let mut pit = self.pit_counter.lock();
759                         pit.timer_handler();
760                     }
761                     Token::Kill => return Ok(()),
762                 }
763             }
764         }
765     }
766 }
767 
768 #[cfg(test)]
769 mod tests {
770     use super::*;
771     struct TestData {
772         pit: Pit,
773         irqfd: EventFd,
774         clock: Arc<Mutex<Clock>>,
775     }
776 
777     /// Utility method for writing a command word to a command register.
write_command(pit: &mut Pit, command: u8)778     fn write_command(pit: &mut Pit, command: u8) {
779         pit.write(PortIOSpace::PortCommand as u64, &[command])
780     }
781 
782     /// Utility method for writing a command word to the speaker register.
write_speaker(pit: &mut Pit, command: u8)783     fn write_speaker(pit: &mut Pit, command: u8) {
784         pit.write(PortIOSpace::PortSpeaker as u64, &[command])
785     }
786 
787     /// Utility method for writing to a counter.
write_counter(pit: &mut Pit, counter_idx: usize, data: u16, access_mode: CommandAccess)788     fn write_counter(pit: &mut Pit, counter_idx: usize, data: u16, access_mode: CommandAccess) {
789         let port = match counter_idx {
790             0 => PortIOSpace::PortCounter0Data,
791             1 => PortIOSpace::PortCounter1Data,
792             2 => PortIOSpace::PortCounter2Data,
793             _ => panic!("Invalid counter_idx: {}", counter_idx),
794         } as u64;
795         // Write the least, then the most, significant byte.
796         if access_mode == CommandAccess::CommandRWLeast
797             || access_mode == CommandAccess::CommandRWBoth
798         {
799             pit.write(port, &[(data & 0xff) as u8]);
800         }
801         if access_mode == CommandAccess::CommandRWMost
802             || access_mode == CommandAccess::CommandRWBoth
803         {
804             pit.write(port, &[(data >> 8) as u8]);
805         }
806     }
807 
808     /// Utility method for reading a counter. Check if the read value matches expected_value.
read_counter(pit: &mut Pit, counter_idx: usize, expected: u16, access_mode: CommandAccess)809     fn read_counter(pit: &mut Pit, counter_idx: usize, expected: u16, access_mode: CommandAccess) {
810         let port = match counter_idx {
811             0 => PortIOSpace::PortCounter0Data,
812             1 => PortIOSpace::PortCounter1Data,
813             2 => PortIOSpace::PortCounter2Data,
814             _ => panic!("Invalid counter_idx: {}", counter_idx),
815         } as u64;
816         let mut result: u16 = 0;
817         if access_mode == CommandAccess::CommandRWLeast
818             || access_mode == CommandAccess::CommandRWBoth
819         {
820             let mut buffer = [0];
821             pit.read(port, &mut buffer);
822             result = buffer[0].into();
823         }
824         if access_mode == CommandAccess::CommandRWMost
825             || access_mode == CommandAccess::CommandRWBoth
826         {
827             let mut buffer = [0];
828             pit.read(port, &mut buffer);
829             result |= u16::from(buffer[0]) << 8;
830         }
831         assert_eq!(result, expected);
832     }
833 
set_up() -> TestData834     fn set_up() -> TestData {
835         let irqfd = EventFd::new().unwrap();
836         let clock = Arc::new(Mutex::new(Clock::new()));
837         TestData {
838             pit: Pit::new(irqfd.try_clone().unwrap(), clock.clone()).unwrap(),
839             irqfd,
840             clock,
841         }
842     }
843 
advance_by_tick(data: &mut TestData)844     fn advance_by_tick(data: &mut TestData) {
845         advance_by_ticks(data, 1);
846     }
847 
advance_by_ticks(data: &mut TestData, ticks: u64)848     fn advance_by_ticks(data: &mut TestData, ticks: u64) {
849         println!(
850             "Advancing by {:#x} ticks ({} ns)",
851             ticks,
852             (NANOS_PER_SEC * ticks) / FREQUENCY_HZ + 1
853         );
854         let mut lock = data.clock.lock();
855         lock.add_ns((NANOS_PER_SEC * ticks) / FREQUENCY_HZ + 1);
856     }
857 
858     /// Tests the ability to write a command and data and read the data back using latch.
859     #[test]
write_and_latch()860     fn write_and_latch() {
861         let mut data = set_up();
862         let both_interrupt =
863             CommandAccess::CommandRWBoth as u8 | CommandMode::CommandInterrupt as u8;
864         // Issue a command to write both digits of counter 0 in interrupt mode.
865         write_command(
866             &mut data.pit,
867             CommandCounter::CommandCounter0 as u8 | both_interrupt,
868         );
869         write_counter(&mut data.pit, 0, 24, CommandAccess::CommandRWBoth);
870         // Advance time by one tick -- value read back should decrease.
871         advance_by_tick(&mut data);
872 
873         // Latch and read back the value written.
874         write_command(
875             &mut data.pit,
876             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
877         );
878         // Advance again after latching to verify that value read back doesn't change.
879         advance_by_tick(&mut data);
880         read_counter(&mut data.pit, 0, 23, CommandAccess::CommandRWBoth);
881 
882         // Repeat with counter 1.
883         write_command(
884             &mut data.pit,
885             CommandCounter::CommandCounter1 as u8 | both_interrupt,
886         );
887         write_counter(&mut data.pit, 1, 314, CommandAccess::CommandRWBoth);
888         advance_by_tick(&mut data);
889         write_command(
890             &mut data.pit,
891             CommandCounter::CommandCounter1 as u8 | CommandAccess::CommandLatch as u8,
892         );
893         advance_by_tick(&mut data);
894         read_counter(&mut data.pit, 1, 313, CommandAccess::CommandRWBoth);
895 
896         // Repeat with counter 2.
897         write_command(
898             &mut data.pit,
899             CommandCounter::CommandCounter2 as u8 | both_interrupt,
900         );
901         write_counter(&mut data.pit, 2, 0xffff, CommandAccess::CommandRWBoth);
902         advance_by_tick(&mut data);
903         write_command(
904             &mut data.pit,
905             CommandCounter::CommandCounter2 as u8 | CommandAccess::CommandLatch as u8,
906         );
907         advance_by_tick(&mut data);
908         read_counter(&mut data.pit, 2, 0xfffe, CommandAccess::CommandRWBoth);
909     }
910 
911     /// Tests the ability to read only the least significant byte.
912     #[test]
write_and_read_least()913     fn write_and_read_least() {
914         let mut data = set_up();
915         write_command(
916             &mut data.pit,
917             CommandCounter::CommandCounter0 as u8
918                 | CommandAccess::CommandRWLeast as u8
919                 | CommandMode::CommandInterrupt as u8,
920         );
921         write_counter(&mut data.pit, 0, 0x3424, CommandAccess::CommandRWLeast);
922         read_counter(&mut data.pit, 0, 0x0024, CommandAccess::CommandRWLeast);
923         write_command(
924             &mut data.pit,
925             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
926         );
927         advance_by_tick(&mut data);
928         read_counter(&mut data.pit, 0, 0x0024, CommandAccess::CommandRWLeast);
929     }
930 
931     /// Tests the ability to read only the most significant byte.
932     #[test]
write_and_read_most()933     fn write_and_read_most() {
934         let mut data = set_up();
935         write_command(
936             &mut data.pit,
937             CommandCounter::CommandCounter0 as u8
938                 | CommandAccess::CommandRWMost as u8
939                 | CommandMode::CommandInterrupt as u8,
940         );
941         write_counter(&mut data.pit, 0, 0x3424, CommandAccess::CommandRWMost);
942         read_counter(&mut data.pit, 0, 0x3400, CommandAccess::CommandRWMost);
943         write_command(
944             &mut data.pit,
945             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
946         );
947         advance_by_tick(&mut data);
948         read_counter(&mut data.pit, 0, 0x3400, CommandAccess::CommandRWMost);
949     }
950 
951     /// Tests that reading the command register does nothing.
952     #[test]
read_command()953     fn read_command() {
954         let mut data = set_up();
955         let mut buf = [0];
956         data.pit.read(PortIOSpace::PortCommand as u64, &mut buf);
957         assert_eq!(buf, [0]);
958     }
959 
960     /// Tests that latching prevents the read time from actually advancing.
961     #[test]
test_timed_latch()962     fn test_timed_latch() {
963         let mut data = set_up();
964         write_command(
965             &mut data.pit,
966             CommandCounter::CommandCounter0 as u8
967                 | CommandAccess::CommandRWBoth as u8
968                 | CommandMode::CommandInterrupt as u8,
969         );
970         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
971         write_command(
972             &mut data.pit,
973             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
974         );
975         data.clock.lock().add_ns(25_000_000);
976         // The counter should ignore this second latch.
977         write_command(
978             &mut data.pit,
979             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
980         );
981         read_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
982         // It should, however, store the count for this latch.
983         write_command(
984             &mut data.pit,
985             CommandCounter::CommandCounter0 as u8 | CommandAccess::CommandLatch as u8,
986         );
987         read_counter(
988             &mut data.pit,
989             0,
990             0xffff - ((25_000_000 * FREQUENCY_HZ) / NANOS_PER_SEC) as u16,
991             CommandAccess::CommandRWBoth,
992         );
993     }
994 
995     /// Tests Mode 0 (Interrupt on terminal count); checks whether IRQ has been asserted.
996     #[test]
interrupt_mode()997     fn interrupt_mode() {
998         let mut data = set_up();
999         write_command(
1000             &mut data.pit,
1001             CommandCounter::CommandCounter0 as u8
1002                 | CommandAccess::CommandRWBoth as u8
1003                 | CommandMode::CommandInterrupt as u8,
1004         );
1005         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1006         // Advance clock enough to trigger interrupt.
1007         advance_by_ticks(&mut data, 0xffff);
1008         assert_eq!(data.irqfd.read().unwrap(), 1);
1009     }
1010 
1011     /// Tests that Rate Generator mode (mode 2) handls the interrupt properly when the timer
1012     /// expires and that it resets the timer properly.
1013     #[test]
rate_gen_mode()1014     fn rate_gen_mode() {
1015         let mut data = set_up();
1016         write_command(
1017             &mut data.pit,
1018             CommandCounter::CommandCounter0 as u8
1019                 | CommandAccess::CommandRWBoth as u8
1020                 | CommandMode::CommandRateGen as u8,
1021         );
1022         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1023         // Repatedly advance clock and expect interrupt.
1024         advance_by_ticks(&mut data, 0xffff);
1025         assert_eq!(data.irqfd.read().unwrap(), 1);
1026 
1027         // Repatedly advance clock and expect interrupt.
1028         advance_by_ticks(&mut data, 0xffff);
1029         assert_eq!(data.irqfd.read().unwrap(), 1);
1030 
1031         // Repatedly advance clock and expect interrupt.
1032         advance_by_ticks(&mut data, 0xffff);
1033         assert_eq!(data.irqfd.read().unwrap(), 1);
1034     }
1035 
1036     /// Tests that square wave mode advances the counter correctly.
1037     #[test]
square_wave_counter_read()1038     fn square_wave_counter_read() {
1039         let mut data = set_up();
1040         write_command(
1041             &mut data.pit,
1042             CommandCounter::CommandCounter0 as u8
1043                 | CommandAccess::CommandRWBoth as u8
1044                 | CommandMode::CommandSquareWaveGen as u8,
1045         );
1046         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1047 
1048         advance_by_ticks(&mut data, 10_000);
1049         read_counter(
1050             &mut data.pit,
1051             0,
1052             0xffff - 10_000 * 2,
1053             CommandAccess::CommandRWBoth,
1054         );
1055     }
1056 
1057     /// Tests that rategen mode updates the counter correctly.
1058     #[test]
rate_gen_counter_read()1059     fn rate_gen_counter_read() {
1060         let mut data = set_up();
1061         write_command(
1062             &mut data.pit,
1063             CommandCounter::CommandCounter0 as u8
1064                 | CommandAccess::CommandRWBoth as u8
1065                 | CommandMode::CommandRateGen as u8,
1066         );
1067         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1068 
1069         advance_by_ticks(&mut data, 10_000);
1070         read_counter(
1071             &mut data.pit,
1072             0,
1073             0xffff - 10_000,
1074             CommandAccess::CommandRWBoth,
1075         );
1076     }
1077 
1078     /// Tests that interrupt counter mode updates the counter correctly.
1079     #[test]
interrupt_counter_read()1080     fn interrupt_counter_read() {
1081         let mut data = set_up();
1082         write_command(
1083             &mut data.pit,
1084             CommandCounter::CommandCounter0 as u8
1085                 | CommandAccess::CommandRWBoth as u8
1086                 | CommandMode::CommandInterrupt as u8,
1087         );
1088         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1089 
1090         advance_by_ticks(&mut data, 10_000);
1091         read_counter(
1092             &mut data.pit,
1093             0,
1094             0xffff - 10_000,
1095             CommandAccess::CommandRWBoth,
1096         );
1097 
1098         advance_by_ticks(&mut data, (3 * FREQUENCY_HZ).into());
1099         read_counter(&mut data.pit, 0, 0, CommandAccess::CommandRWBoth);
1100     }
1101 
1102     /// Tests that ReadBack count works properly for `low` access mode.
1103     #[test]
read_back_count_access_low()1104     fn read_back_count_access_low() {
1105         let mut data = set_up();
1106         write_command(
1107             &mut data.pit,
1108             CommandCounter::CommandCounter0 as u8
1109                 | CommandAccess::CommandRWLeast as u8
1110                 | CommandMode::CommandInterrupt as u8,
1111         );
1112         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWLeast);
1113         write_command(
1114             &mut data.pit,
1115             CommandCounter::CommandReadBack as u8
1116                 | CommandReadBackLatch::CommandRBLatchCount as u8
1117                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1118         );
1119 
1120         // Advance 100 ticks and verify that low byte of counter is appropriately updated.
1121         advance_by_ticks(&mut data, 100);
1122         write_command(
1123             &mut data.pit,
1124             CommandCounter::CommandReadBack as u8
1125                 | CommandReadBackLatch::CommandRBLatchCount as u8
1126                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1127         );
1128         read_counter(&mut data.pit, 0, 0x00ff, CommandAccess::CommandRWLeast);
1129         write_command(
1130             &mut data.pit,
1131             CommandCounter::CommandReadBack as u8
1132                 | CommandReadBackLatch::CommandRBLatchCount as u8
1133                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1134         );
1135         read_counter(
1136             &mut data.pit,
1137             0,
1138             (0xffff - 100) & 0x00ff,
1139             CommandAccess::CommandRWLeast,
1140         );
1141     }
1142 
1143     /// Tests that ReadBack count works properly for `high` access mode.
1144     #[test]
read_back_count_access_high()1145     fn read_back_count_access_high() {
1146         let mut data = set_up();
1147         write_command(
1148             &mut data.pit,
1149             CommandCounter::CommandCounter0 as u8
1150                 | CommandAccess::CommandRWMost as u8
1151                 | CommandMode::CommandInterrupt as u8,
1152         );
1153         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWLeast);
1154         write_command(
1155             &mut data.pit,
1156             CommandCounter::CommandReadBack as u8
1157                 | CommandReadBackLatch::CommandRBLatchCount as u8
1158                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1159         );
1160 
1161         // Advance 100 ticks and verify that low byte of counter is appropriately updated.
1162         advance_by_ticks(&mut data, 512);
1163         write_command(
1164             &mut data.pit,
1165             CommandCounter::CommandReadBack as u8
1166                 | CommandReadBackLatch::CommandRBLatchCount as u8
1167                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1168         );
1169         read_counter(&mut data.pit, 0, 0xff00, CommandAccess::CommandRWMost);
1170         write_command(
1171             &mut data.pit,
1172             CommandCounter::CommandReadBack as u8
1173                 | CommandReadBackLatch::CommandRBLatchCount as u8
1174                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1175         );
1176         read_counter(
1177             &mut data.pit,
1178             0,
1179             (0xffff - 512) & 0xff00,
1180             CommandAccess::CommandRWMost,
1181         );
1182     }
1183 
1184     /// Tests that ReadBack status returns the expected values.
1185     #[test]
read_back_status()1186     fn read_back_status() {
1187         let mut data = set_up();
1188         write_command(
1189             &mut data.pit,
1190             CommandCounter::CommandCounter0 as u8
1191                 | CommandAccess::CommandRWBoth as u8
1192                 | CommandMode::CommandSWStrobe as u8,
1193         );
1194         write_counter(&mut data.pit, 0, 0xffff, CommandAccess::CommandRWBoth);
1195         write_command(
1196             &mut data.pit,
1197             CommandCounter::CommandReadBack as u8
1198                 | CommandReadBackLatch::CommandRBLatchStatus as u8
1199                 | CommandReadBackCounters::CommandRBCounter0 as u8,
1200         );
1201 
1202         read_counter(
1203             &mut data.pit,
1204             0,
1205             CommandAccess::CommandRWBoth as u16 | CommandMode::CommandSWStrobe as u16,
1206             CommandAccess::CommandRWLeast,
1207         );
1208     }
1209 
1210     #[test]
speaker_square_wave()1211     fn speaker_square_wave() {
1212         let mut data = set_up();
1213         write_command(
1214             &mut data.pit,
1215             CommandCounter::CommandCounter2 as u8
1216                 | CommandAccess::CommandRWBoth as u8
1217                 | CommandMode::CommandSquareWaveGen as u8,
1218         );
1219         write_counter(&mut data.pit, 2, 0xffff, CommandAccess::CommandRWBoth);
1220 
1221         advance_by_ticks(&mut data, 128);
1222         read_counter(
1223             &mut data.pit,
1224             2,
1225             0xffff - 128 * 2,
1226             CommandAccess::CommandRWBoth,
1227         );
1228     }
1229 
1230     #[test]
speaker_rate_gen()1231     fn speaker_rate_gen() {
1232         let mut data = set_up();
1233         write_command(
1234             &mut data.pit,
1235             CommandCounter::CommandCounter2 as u8
1236                 | CommandAccess::CommandRWBoth as u8
1237                 | CommandMode::CommandRateGen as u8,
1238         );
1239         write_counter(&mut data.pit, 2, 0xffff, CommandAccess::CommandRWBoth);
1240 
1241         // In Rate Gen mode, the counter should start over when the gate is
1242         // set to high using SpeakerWrite.
1243         advance_by_ticks(&mut data, 128);
1244         read_counter(&mut data.pit, 2, 0xffff - 128, CommandAccess::CommandRWBoth);
1245 
1246         write_speaker(&mut data.pit, 0x1);
1247         advance_by_ticks(&mut data, 128);
1248         read_counter(&mut data.pit, 2, 0xffff - 128, CommandAccess::CommandRWBoth);
1249     }
1250 
1251     #[test]
speaker_interrupt()1252     fn speaker_interrupt() {
1253         let mut data = set_up();
1254 
1255         write_command(
1256             &mut data.pit,
1257             CommandCounter::CommandCounter2 as u8
1258                 | CommandAccess::CommandRWBoth as u8
1259                 | CommandMode::CommandInterrupt as u8,
1260         );
1261         write_counter(&mut data.pit, 2, 0xffff, CommandAccess::CommandRWBoth);
1262 
1263         // In Interrupt mode, the counter should NOT start over when the gate is
1264         // set to high using SpeakerWrite.
1265         advance_by_ticks(&mut data, 128);
1266         read_counter(&mut data.pit, 2, 0xffff - 128, CommandAccess::CommandRWBoth);
1267 
1268         write_speaker(&mut data.pit, 0x1);
1269         advance_by_ticks(&mut data, 128);
1270         read_counter(&mut data.pit, 2, 0xffff - 256, CommandAccess::CommandRWBoth);
1271     }
1272 
1273     /// Verify that invalid reads and writes do not cause crashes.
1274     #[test]
invalid_write_and_read()1275     fn invalid_write_and_read() {
1276         let mut data = set_up();
1277         data.pit.write(0x44, &[0]);
1278         data.pit.read(0x55, &mut [0]);
1279     }
1280 }
1281