VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/DevPit-i8254.cpp@ 82265

最後變更 在這個檔案從82265是 81945,由 vboxsync 提交於 5 年 前

DevPit-i8254: saved state fix. bugref:9218

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 56.9 KB
 
1/* $Id: DevPit-i8254.cpp 81945 2019-11-18 15:57:04Z vboxsync $ */
2/** @file
3 * DevPIT-i8254 - Intel 8254 Programmable Interval Timer (PIT) And Dummy Speaker Device.
4 */
5
6/*
7 * Copyright (C) 2006-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 * --------------------------------------------------------------------
17 *
18 * This code is based on:
19 *
20 * QEMU 8253/8254 interval timer emulation
21 *
22 * Copyright (c) 2003-2004 Fabrice Bellard
23 *
24 * Permission is hereby granted, free of charge, to any person obtaining a copy
25 * of this software and associated documentation files (the "Software"), to deal
26 * in the Software without restriction, including without limitation the rights
27 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28 * copies of the Software, and to permit persons to whom the Software is
29 * furnished to do so, subject to the following conditions:
30 *
31 * The above copyright notice and this permission notice shall be included in
32 * all copies or substantial portions of the Software.
33 *
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
37 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
40 * THE SOFTWARE.
41 */
42
43
44/*********************************************************************************************************************************
45* Header Files *
46*********************************************************************************************************************************/
47#define LOG_GROUP LOG_GROUP_DEV_PIT
48#include <VBox/vmm/pdmdev.h>
49#include <VBox/log.h>
50#include <VBox/vmm/stam.h>
51#include <iprt/assert.h>
52#include <iprt/asm-math.h>
53
54#ifdef IN_RING3
55# ifdef RT_OS_LINUX
56# include <fcntl.h>
57# include <errno.h>
58# include <unistd.h>
59# include <stdio.h>
60# include <linux/kd.h>
61# include <linux/input.h>
62# include <sys/ioctl.h>
63# endif
64# include <iprt/alloc.h>
65# include <iprt/string.h>
66# include <iprt/uuid.h>
67#endif /* IN_RING3 */
68
69#include "VBoxDD.h"
70
71
72/*********************************************************************************************************************************
73* Defined Constants And Macros *
74*********************************************************************************************************************************/
75/** The PIT frequency. */
76#define PIT_FREQ 1193182
77
78#define RW_STATE_LSB 1
79#define RW_STATE_MSB 2
80#define RW_STATE_WORD0 3
81#define RW_STATE_WORD1 4
82
83/** The current saved state version. */
84#define PIT_SAVED_STATE_VERSION 4
85/** The saved state version used by VirtualBox 3.1 and earlier.
86 * This did not include disable by HPET flag. */
87#define PIT_SAVED_STATE_VERSION_VBOX_31 3
88/** The saved state version used by VirtualBox 3.0 and earlier.
89 * This did not include the config part. */
90#define PIT_SAVED_STATE_VERSION_VBOX_30 2
91
92/** @def FAKE_REFRESH_CLOCK
93 * Define this to flip the 15usec refresh bit on every read.
94 * If not defined, it will be flipped correctly. */
95/* #define FAKE_REFRESH_CLOCK */
96#ifdef DOXYGEN_RUNNING
97# define FAKE_REFRESH_CLOCK
98#endif
99
100/** The effective counter mode - if bit 1 is set, bit 2 is ignored. */
101#define EFFECTIVE_MODE(x) ((x) & ~(((x) & 2) << 1))
102
103
104/**
105 * Acquires the PIT lock or returns.
106 */
107#define DEVPIT_LOCK_RETURN(a_pDevIns, a_pThis, a_rcBusy) \
108 do { \
109 int rcLock = PDMDevHlpCritSectEnter((a_pDevIns), &(a_pThis)->CritSect, (a_rcBusy)); \
110 if (rcLock != VINF_SUCCESS) \
111 return rcLock; \
112 } while (0)
113
114/**
115 * Releases the PIT lock.
116 */
117#define DEVPIT_UNLOCK(a_pDevIns, a_pThis) \
118 do { PDMDevHlpCritSectLeave((a_pDevIns), &(a_pThis)->CritSect); } while (0)
119
120
121/**
122 * Acquires the TM lock and PIT lock, returns on failure.
123 */
124#define DEVPIT_LOCK_BOTH_RETURN(a_pDevIns, a_pThis, a_rcBusy) \
125 do { \
126 int rcLock = PDMDevHlpTimerLock((a_pDevIns), (a_pThis)->channels[0].hTimer, (a_rcBusy)); \
127 if (rcLock != VINF_SUCCESS) \
128 return rcLock; \
129 rcLock = PDMDevHlpCritSectEnter((a_pDevIns), &(a_pThis)->CritSect, (a_rcBusy)); \
130 if (rcLock != VINF_SUCCESS) \
131 { \
132 PDMDevHlpTimerUnlock((a_pDevIns), (a_pThis)->channels[0].hTimer); \
133 return rcLock; \
134 } \
135 } while (0)
136
137#ifdef IN_RING3
138/**
139 * Acquires the TM lock and PIT lock, ignores failures.
140 */
141# define DEVPIT_R3_LOCK_BOTH(a_pDevIns, a_pThis) \
142 do { \
143 PDMDevHlpTimerLock((a_pDevIns), (a_pThis)->channels[0].hTimer, VERR_IGNORED); \
144 PDMDevHlpCritSectEnter((a_pDevIns), &(a_pThis)->CritSect, VERR_IGNORED); \
145 } while (0)
146#endif /* IN_RING3 */
147
148/**
149 * Releases the PIT lock and TM lock.
150 */
151#define DEVPIT_UNLOCK_BOTH(a_pDevIns, a_pThis) \
152 do { \
153 PDMDevHlpCritSectLeave((a_pDevIns), &(a_pThis)->CritSect); \
154 PDMDevHlpTimerUnlock((a_pDevIns), (a_pThis)->channels[0].hTimer); \
155 } while (0)
156
157
158
159/*********************************************************************************************************************************
160* Structures and Typedefs *
161*********************************************************************************************************************************/
162/**
163 * The state of one PIT channel.
164 */
165typedef struct PITCHANNEL
166{
167 /** The timer.
168 * @note Only channel 0 has a timer. */
169 TMTIMERHANDLE hTimer;
170 /** The virtual time stamp at the last reload (only used in mode 2 for now). */
171 uint64_t u64ReloadTS;
172 /** The actual time of the next tick.
173 * As apposed to the next_transition_time which contains the correct time of the next tick. */
174 uint64_t u64NextTS;
175
176 /** (count_load_time is only set by PDMDevHlpTimerGet() which returns uint64_t) */
177 uint64_t count_load_time;
178 /* irq handling */
179 int64_t next_transition_time;
180 int32_t irq;
181 /** Number of release log entries. Used to prevent flooding. */
182 uint8_t cRelLogEntries;
183 /** The channel number. */
184 uint8_t iChan;
185 uint8_t abAlignment[2];
186
187 uint32_t count; /* can be 65536 */
188 uint16_t latched_count;
189 uint8_t count_latched;
190 uint8_t status_latched;
191
192 uint8_t status;
193 uint8_t read_state;
194 uint8_t write_state;
195 uint8_t write_latch;
196
197 uint8_t rw_mode;
198 uint8_t mode;
199 uint8_t bcd; /* not supported */
200 uint8_t gate; /* timer start */
201
202} PITCHANNEL;
203/** Pointer to the state of one PIT channel. */
204typedef PITCHANNEL *PPITCHANNEL;
205
206/** Speaker emulation state. */
207typedef enum PITSPEAKEREMU
208{
209 PIT_SPEAKER_EMU_NONE = 0,
210 PIT_SPEAKER_EMU_CONSOLE,
211 PIT_SPEAKER_EMU_EVDEV,
212 PIT_SPEAKER_EMU_TTY
213} PITSPEAKEREMU;
214
215/**
216 * The shared PIT state.
217 */
218typedef struct PITSTATE
219{
220 /** Channel state. Must come first? */
221 PITCHANNEL channels[3];
222 /** Speaker data. */
223 int32_t speaker_data_on;
224#ifdef FAKE_REFRESH_CLOCK
225 /** Refresh dummy. */
226 int32_t dummy_refresh_clock;
227#else
228 uint32_t Alignment1;
229#endif
230 /** Config: I/O port base. */
231 RTIOPORT IOPortBaseCfg;
232 /** Config: Speaker enabled. */
233 bool fSpeakerCfg;
234 /** Disconnect PIT from the interrupt controllers if requested by HPET. */
235 bool fDisabledByHpet;
236 /** Config: What to do with speaker activity. */
237 PITSPEAKEREMU enmSpeakerEmu;
238#ifdef RT_OS_LINUX
239 /** File handle for host speaker functionality. */
240 int hHostSpeaker;
241 int afAlignment2;
242#endif
243 /** Number of IRQs that's been raised. */
244 STAMCOUNTER StatPITIrq;
245 /** Profiling the timer callback handler. */
246 STAMPROFILEADV StatPITHandler;
247 /** Critical section protecting the state. */
248 PDMCRITSECT CritSect;
249 /** The primary I/O port range (0x40-0x43). */
250 IOMIOPORTHANDLE hIoPorts;
251 /** The speaker I/O port range (0x40-0x43). */
252 IOMIOPORTHANDLE hIoPortSpeaker;
253} PITSTATE;
254/** Pointer to the shared PIT device state. */
255typedef PITSTATE *PPITSTATE;
256
257
258/**
259 * The ring-3 PIT state.
260 */
261typedef struct PITSTATER3
262{
263 /** PIT port interface. */
264 PDMIHPETLEGACYNOTIFY IHpetLegacyNotify;
265 /** Pointer to the device instance. */
266 PPDMDEVINSR3 pDevIns;
267} PITSTATER3;
268/** Pointer to the ring-3 PIT device state. */
269typedef PITSTATER3 *PPITSTATER3;
270
271
272#ifndef VBOX_DEVICE_STRUCT_TESTCASE
273
274
275
276static int pit_get_count(PPDMDEVINS pDevIns, PPITSTATE pThis, PPITCHANNEL pChan)
277{
278 uint64_t d;
279 TMTIMERHANDLE hTimer = pThis->channels[0].hTimer;
280 Assert(PDMDevHlpTimerIsLockOwner(pDevIns, hTimer));
281
282 if (EFFECTIVE_MODE(pChan->mode) == 2)
283 {
284 if (pChan->u64NextTS == UINT64_MAX)
285 {
286 d = ASMMultU64ByU32DivByU32(PDMDevHlpTimerGet(pDevIns, hTimer) - pChan->count_load_time,
287 PIT_FREQ, PDMDevHlpTimerGetFreq(pDevIns, hTimer));
288 return pChan->count - (d % pChan->count); /** @todo check this value. */
289 }
290 uint64_t Interval = pChan->u64NextTS - pChan->u64ReloadTS;
291 if (!Interval)
292 return pChan->count - 1; /** @todo This is WRONG! But I'm too tired to fix it properly and just want to shut up a DIV/0 trap now. */
293 d = PDMDevHlpTimerGet(pDevIns, hTimer);
294 d = ASMMultU64ByU32DivByU32(d - pChan->u64ReloadTS, pChan->count, Interval);
295 if (d >= pChan->count)
296 return 1;
297 return pChan->count - d;
298 }
299
300 d = ASMMultU64ByU32DivByU32(PDMDevHlpTimerGet(pDevIns, hTimer) - pChan->count_load_time,
301 PIT_FREQ, PDMDevHlpTimerGetFreq(pDevIns, hTimer));
302 int counter;
303 switch (EFFECTIVE_MODE(pChan->mode))
304 {
305 case 0:
306 case 1:
307 case 4:
308 case 5:
309 counter = (pChan->count - d) & 0xffff;
310 break;
311 case 3:
312 /* XXX: may be incorrect for odd counts */
313 counter = pChan->count - ((2 * d) % pChan->count);
314 break;
315 default:
316 counter = pChan->count - (d % pChan->count);
317 break;
318 }
319 /** @todo check that we don't return 0, in most modes (all?) the counter shouldn't be zero. */
320 return counter;
321}
322
323
324/* get pit output bit */
325static int pit_get_out1(PPDMDEVINS pDevIns, PPITSTATE pThis, PPITCHANNEL pChan, int64_t current_time)
326{
327 TMTIMERHANDLE hTimer = pThis->channels[0].hTimer;
328 uint64_t d;
329 int out;
330
331 d = ASMMultU64ByU32DivByU32(current_time - pChan->count_load_time, PIT_FREQ, PDMDevHlpTimerGetFreq(pDevIns, hTimer));
332 switch (EFFECTIVE_MODE(pChan->mode))
333 {
334 default:
335 case 0:
336 out = (d >= pChan->count);
337 break;
338 case 1:
339 out = (d < pChan->count);
340 break;
341 case 2:
342 Log2(("pit_get_out1: d=%llx c=%x %x \n", d, pChan->count, (unsigned)(d % pChan->count)));
343 if ((d % pChan->count) == 0 && d != 0)
344 out = 1;
345 else
346 out = 0;
347 break;
348 case 3:
349 out = (d % pChan->count) < ((pChan->count + 1) >> 1);
350 break;
351 case 4:
352 case 5:
353 out = (d != pChan->count);
354 break;
355 }
356 return out;
357}
358
359
360static int pit_get_out(PPDMDEVINS pDevIns, PPITSTATE pThis, int channel, int64_t current_time)
361{
362 PPITCHANNEL pChan = &pThis->channels[channel];
363 return pit_get_out1(pDevIns, pThis, pChan, current_time);
364}
365
366
367static int pit_get_gate(PPITSTATE pThis, int channel)
368{
369 PPITCHANNEL pChan = &pThis->channels[channel];
370 return pChan->gate;
371}
372
373
374/* if already latched, do not latch again */
375static void pit_latch_count(PPDMDEVINS pDevIns, PPITSTATE pThis, PPITCHANNEL pChan)
376{
377 if (!pChan->count_latched)
378 {
379 pChan->latched_count = pit_get_count(pDevIns, pThis, pChan);
380 pChan->count_latched = pChan->rw_mode;
381 LogFlow(("pit_latch_count: latched_count=%#06x / %10RU64 ns (c=%#06x m=%d)\n",
382 pChan->latched_count, ASMMultU64ByU32DivByU32(pChan->count - pChan->latched_count, 1000000000, PIT_FREQ),
383 pChan->count, pChan->mode));
384 }
385}
386
387#ifdef IN_RING3
388
389/* return -1 if no transition will occur. */
390static int64_t pitR3GetNextTransitionTime(PPDMDEVINS pDevIns, PPITSTATE pThis, PPITCHANNEL pChan, uint64_t current_time)
391{
392 TMTIMERHANDLE hTimer = pThis->channels[0].hTimer;
393 uint64_t d, next_time, base;
394 uint32_t period2;
395
396 d = ASMMultU64ByU32DivByU32(current_time - pChan->count_load_time, PIT_FREQ, PDMDevHlpTimerGetFreq(pDevIns, hTimer));
397 switch (EFFECTIVE_MODE(pChan->mode))
398 {
399 default:
400 case 0:
401 case 1:
402 if (d < pChan->count)
403 next_time = pChan->count;
404 else
405 return -1;
406 break;
407
408 /*
409 * Mode 2: The period is 'count' PIT ticks.
410 * When the counter reaches 1 we set the output low (for channel 0 that
411 * means lowering IRQ0). On the next tick, where we should be decrementing
412 * from 1 to 0, the count is loaded and the output goes high (channel 0
413 * means raising IRQ0 again and triggering timer interrupt).
414 *
415 * In VirtualBox we compress the pulse and flip-flop the IRQ line at the
416 * end of the period, which signals an interrupt at the exact same time.
417 */
418 case 2:
419 base = (d / pChan->count) * pChan->count;
420# ifndef VBOX /* see above */
421 if ((d - base) == 0 && d != 0)
422 next_time = base + pChan->count - 1;
423 else
424# endif
425 next_time = base + pChan->count;
426 break;
427 case 3:
428 base = (d / pChan->count) * pChan->count;
429 period2 = ((pChan->count + 1) >> 1);
430 if ((d - base) < period2)
431 next_time = base + period2;
432 else
433 next_time = base + pChan->count;
434 break;
435
436 /* Modes 4 and 5 generate a short pulse at the end of the time delay. This
437 * is similar to mode 2, except modes 4/5 aren't periodic. We use the same
438 * optimization - only use one timer callback and pulse the IRQ.
439 * Note: Tickless Linux kernels use PIT mode 4 with 'nolapic'.
440 */
441 case 4:
442 case 5:
443# ifdef VBOX
444 if (d <= pChan->count)
445 next_time = pChan->count;
446# else
447 if (d < pChan->count)
448 next_time = pChan->count;
449 else if (d == pChan->count)
450 next_time = pChan->count + 1;
451# endif
452 else
453 return -1;
454 break;
455 }
456
457 /* convert to timer units */
458 LogFlow(("PIT: next_time=%'14RU64 %'20RU64 mode=%#x count=%#06x\n", next_time,
459 ASMMultU64ByU32DivByU32(next_time, PDMDevHlpTimerGetFreq(pDevIns, hTimer), PIT_FREQ), pChan->mode, pChan->count));
460 next_time = pChan->count_load_time + ASMMultU64ByU32DivByU32(next_time, PDMDevHlpTimerGetFreq(pDevIns, hTimer), PIT_FREQ);
461
462 /* fix potential rounding problems */
463 if (next_time <= current_time)
464 next_time = current_time;
465
466 /* Add one to next_time; if we don't, integer truncation will cause
467 * the algorithm to think that at the end of each period, it'pChan still
468 * within the first one instead of at the beginning of the next one.
469 */
470 return next_time + 1;
471}
472
473
474static void pitR3IrqTimerUpdate(PPDMDEVINS pDevIns, PPITSTATE pThis, PPITCHANNEL pChan,
475 uint64_t current_time, uint64_t now, bool in_timer)
476{
477 int64_t expire_time;
478 int irq_level;
479 Assert(PDMDevHlpTimerIsLockOwner(pDevIns, pThis->channels[0].hTimer));
480
481 if (pChan->hTimer == NIL_TMTIMERHANDLE)
482 return;
483 expire_time = pitR3GetNextTransitionTime(pDevIns, pThis, pChan, current_time);
484 irq_level = pit_get_out1(pDevIns, pThis, pChan, current_time) ? PDM_IRQ_LEVEL_HIGH : PDM_IRQ_LEVEL_LOW;
485
486 /* If PIT is disabled by HPET - simply disconnect ticks from interrupt controllers,
487 * but do not modify other aspects of device operation.
488 */
489 if (!pThis->fDisabledByHpet)
490 {
491 switch (EFFECTIVE_MODE(pChan->mode))
492 {
493 case 2:
494 case 4:
495 case 5:
496 /* We just flip-flop the IRQ line to save an extra timer call,
497 * which isn't generally required. However, the pulse is only
498 * generated when running on the timer callback (and thus on
499 * the trailing edge of the output signal pulse).
500 */
501 if (in_timer)
502 {
503 PDMDevHlpISASetIrq(pDevIns, pChan->irq, PDM_IRQ_LEVEL_FLIP_FLOP);
504 break;
505 }
506 RT_FALL_THRU();
507 default:
508 PDMDevHlpISASetIrq(pDevIns, pChan->irq, irq_level);
509 break;
510 }
511 }
512
513 if (irq_level)
514 {
515 pChan->u64ReloadTS = now;
516 STAM_COUNTER_INC(&pThis->StatPITIrq);
517 }
518
519 if (expire_time != -1)
520 {
521 Log3(("pitR3IrqTimerUpdate: next=%'RU64 now=%'RU64\n", expire_time, now));
522 pChan->u64NextTS = expire_time;
523 PDMDevHlpTimerSet(pDevIns, pChan->hTimer, pChan->u64NextTS);
524 }
525 else
526 {
527 LogFlow(("PIT: m=%d count=%#4x irq_level=%#x stopped\n", pChan->mode, pChan->count, irq_level));
528 PDMDevHlpTimerStop(pDevIns, pChan->hTimer);
529 pChan->u64NextTS = UINT64_MAX;
530 }
531 pChan->next_transition_time = expire_time;
532}
533
534
535/* val must be 0 or 1 */
536static void pitR3SetGate(PPDMDEVINS pDevIns, PPITSTATE pThis, int channel, int val)
537{
538 PPITCHANNEL pChan = &pThis->channels[channel];
539 TMTIMERHANDLE hTimer = pThis->channels[0].hTimer;
540
541 Assert((val & 1) == val);
542 Assert(PDMDevHlpTimerIsLockOwner(pDevIns, hTimer));
543
544 switch (EFFECTIVE_MODE(pChan->mode))
545 {
546 default:
547 case 0:
548 case 4:
549 /* XXX: just disable/enable counting */
550 break;
551 case 1:
552 case 5:
553 if (pChan->gate < val)
554 {
555 /* restart counting on rising edge */
556 Log(("pitR3SetGate: restarting mode %d\n", pChan->mode));
557 pChan->count_load_time = PDMDevHlpTimerGet(pDevIns, hTimer);
558 pitR3IrqTimerUpdate(pDevIns, pThis, pChan, pChan->count_load_time, pChan->count_load_time, false);
559 }
560 break;
561 case 2:
562 case 3:
563 if (pChan->gate < val)
564 {
565 /* restart counting on rising edge */
566 Log(("pitR3SetGate: restarting mode %d\n", pChan->mode));
567 pChan->count_load_time = pChan->u64ReloadTS = PDMDevHlpTimerGet(pDevIns, hTimer);
568 pitR3IrqTimerUpdate(pDevIns, pThis, pChan, pChan->count_load_time, pChan->count_load_time, false);
569 }
570 /* XXX: disable/enable counting */
571 break;
572 }
573 pChan->gate = val;
574}
575
576
577static void pitR3LoadCount(PPDMDEVINS pDevIns, PPITSTATE pThis, PPITCHANNEL pChan, int val)
578{
579 TMTIMERHANDLE hTimer = pThis->channels[0].hTimer;
580 Assert(PDMDevHlpTimerIsLockOwner(pDevIns, hTimer));
581
582 if (val == 0)
583 val = 0x10000;
584 pChan->count_load_time = pChan->u64ReloadTS = PDMDevHlpTimerGet(pDevIns, hTimer);
585 pChan->count = val;
586 pitR3IrqTimerUpdate(pDevIns, pThis, pChan, pChan->count_load_time, pChan->count_load_time, false);
587
588 /* log the new rate (ch 0 only). */
589 if (pChan->hTimer != NIL_TMTIMERHANDLE /* ch 0 */)
590 {
591 if (pChan->cRelLogEntries < 32)
592 {
593 pChan->cRelLogEntries++;
594 LogRel(("PIT: mode=%d count=%#x (%u) - %d.%02d Hz (ch=0)\n",
595 pChan->mode, pChan->count, pChan->count, PIT_FREQ / pChan->count, (PIT_FREQ * 100 / pChan->count) % 100));
596 }
597 else
598 Log(("PIT: mode=%d count=%#x (%u) - %d.%02d Hz (ch=0)\n",
599 pChan->mode, pChan->count, pChan->count, PIT_FREQ / pChan->count, (PIT_FREQ * 100 / pChan->count) % 100));
600 PDMDevHlpTimerSetFrequencyHint(pDevIns, hTimer, PIT_FREQ / pChan->count);
601 }
602 else
603 Log(("PIT: mode=%d count=%#x (%u) - %d.%02d Hz (ch=%d)\n",
604 pChan->mode, pChan->count, pChan->count, PIT_FREQ / pChan->count, (PIT_FREQ * 100 / pChan->count) % 100,
605 pChan - &pThis->channels[0]));
606}
607
608#endif /* IN_RING3 */
609
610/**
611 * @callback_method_impl{FNIOMIOPORTNEWIN}
612 */
613static DECLCALLBACK(VBOXSTRICTRC) pitIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
614{
615 Log2(("pitIOPortRead: offPort=%#x cb=%x\n", offPort, cb));
616 NOREF(pvUser);
617 Assert(offPort < 4);
618 if (cb != 1 || offPort == 3)
619 {
620 Log(("pitIOPortRead: offPort=%#x cb=%x *pu32=unused!\n", offPort, cb));
621 return VERR_IOM_IOPORT_UNUSED;
622 }
623 RT_UNTRUSTED_VALIDATED_FENCE(); /* paranoia */
624
625 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
626 PPITCHANNEL pChan = &pThis->channels[offPort];
627 int ret;
628
629 DEVPIT_LOCK_RETURN(pDevIns, pThis, VINF_IOM_R3_IOPORT_READ);
630 if (pChan->status_latched)
631 {
632 pChan->status_latched = 0;
633 ret = pChan->status;
634 DEVPIT_UNLOCK(pDevIns, pThis);
635 }
636 else if (pChan->count_latched)
637 {
638 switch (pChan->count_latched)
639 {
640 default:
641 case RW_STATE_LSB:
642 ret = pChan->latched_count & 0xff;
643 pChan->count_latched = 0;
644 break;
645 case RW_STATE_MSB:
646 ret = pChan->latched_count >> 8;
647 pChan->count_latched = 0;
648 break;
649 case RW_STATE_WORD0:
650 ret = pChan->latched_count & 0xff;
651 pChan->count_latched = RW_STATE_MSB;
652 break;
653 }
654 DEVPIT_UNLOCK(pDevIns, pThis);
655 }
656 else
657 {
658 DEVPIT_UNLOCK(pDevIns, pThis);
659 DEVPIT_LOCK_BOTH_RETURN(pDevIns, pThis, VINF_IOM_R3_IOPORT_READ);
660 int count;
661 switch (pChan->read_state)
662 {
663 default:
664 case RW_STATE_LSB:
665 count = pit_get_count(pDevIns, pThis, pChan);
666 ret = count & 0xff;
667 break;
668 case RW_STATE_MSB:
669 count = pit_get_count(pDevIns, pThis, pChan);
670 ret = (count >> 8) & 0xff;
671 break;
672 case RW_STATE_WORD0:
673 count = pit_get_count(pDevIns, pThis, pChan);
674 ret = count & 0xff;
675 pChan->read_state = RW_STATE_WORD1;
676 break;
677 case RW_STATE_WORD1:
678 count = pit_get_count(pDevIns, pThis, pChan);
679 ret = (count >> 8) & 0xff;
680 pChan->read_state = RW_STATE_WORD0;
681 break;
682 }
683 DEVPIT_UNLOCK_BOTH(pDevIns, pThis);
684 }
685
686 *pu32 = ret;
687 Log2(("pitIOPortRead: offPort=%#x cb=%x *pu32=%#04x\n", offPort, cb, *pu32));
688 return VINF_SUCCESS;
689}
690
691
692/**
693 * @callback_method_impl{FNIOMIOPORTNEWOUT}
694 */
695static DECLCALLBACK(VBOXSTRICTRC) pitIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
696{
697 Log2(("pitIOPortWrite: offPort=%#x cb=%x u32=%#04x\n", offPort, cb, u32));
698 NOREF(pvUser);
699 Assert(offPort < 4);
700
701 if (cb != 1)
702 return VINF_SUCCESS;
703
704 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
705 if (offPort == 3)
706 {
707 /*
708 * Port 43h - Mode/Command Register.
709 * 7 6 5 4 3 2 1 0
710 * * * . . . . . . Select channel: 0 0 = Channel 0
711 * 0 1 = Channel 1
712 * 1 0 = Channel 2
713 * 1 1 = Read-back command (8254 only)
714 * (Illegal on 8253)
715 * (Illegal on PS/2 {JAM})
716 * . . * * . . . . Command/Access mode: 0 0 = Latch count value command
717 * 0 1 = Access mode: lobyte only
718 * 1 0 = Access mode: hibyte only
719 * 1 1 = Access mode: lobyte/hibyte
720 * . . . . * * * . Operating mode: 0 0 0 = Mode 0, 0 0 1 = Mode 1,
721 * 0 1 0 = Mode 2, 0 1 1 = Mode 3,
722 * 1 0 0 = Mode 4, 1 0 1 = Mode 5,
723 * 1 1 0 = Mode 2, 1 1 1 = Mode 3
724 * . . . . . . . * BCD/Binary mode: 0 = 16-bit binary, 1 = four-digit BCD
725 */
726 unsigned channel = (u32 >> 6) & 0x3;
727 RT_UNTRUSTED_VALIDATED_FENCE(); /* paranoia */
728 if (channel == 3)
729 {
730 /* read-back command */
731 DEVPIT_LOCK_BOTH_RETURN(pDevIns, pThis, VINF_IOM_R3_IOPORT_WRITE);
732 for (channel = 0; channel < RT_ELEMENTS(pThis->channels); channel++)
733 {
734 PPITCHANNEL pChan = &pThis->channels[channel];
735 if (u32 & (2 << channel))
736 {
737 if (!(u32 & 0x20))
738 pit_latch_count(pDevIns, pThis, pChan);
739 if (!(u32 & 0x10) && !pChan->status_latched)
740 {
741 /* status latch */
742 /* XXX: add BCD and null count */
743 pChan->status = (pit_get_out1(pDevIns, pThis, pChan,
744 PDMDevHlpTimerGet(pDevIns, pThis->channels[0].hTimer)) << 7)
745 | (pChan->rw_mode << 4)
746 | (pChan->mode << 1)
747 | pChan->bcd;
748 pChan->status_latched = 1;
749 }
750 }
751 }
752 DEVPIT_UNLOCK_BOTH(pDevIns, pThis);
753 }
754 else
755 {
756 PPITCHANNEL pChan = &pThis->channels[channel];
757 unsigned access = (u32 >> 4) & 3;
758 if (access == 0)
759 {
760 DEVPIT_LOCK_BOTH_RETURN(pDevIns, pThis, VINF_IOM_R3_IOPORT_WRITE);
761 pit_latch_count(pDevIns, pThis, pChan);
762 DEVPIT_UNLOCK_BOTH(pDevIns, pThis);
763 }
764 else
765 {
766 DEVPIT_LOCK_RETURN(pDevIns, pThis, VINF_IOM_R3_IOPORT_WRITE);
767 pChan->rw_mode = access;
768 pChan->read_state = access;
769 pChan->write_state = access;
770
771 pChan->mode = (u32 >> 1) & 7;
772 pChan->bcd = u32 & 1;
773 /* XXX: update irq timer ? */
774 DEVPIT_UNLOCK(pDevIns, pThis);
775 }
776 }
777 }
778 else
779 {
780#ifndef IN_RING3
781 /** @todo There is no reason not to do this in all contexts these
782 * days... */
783 return VINF_IOM_R3_IOPORT_WRITE;
784#else /* IN_RING3 */
785 /*
786 * Port 40-42h - Channel Data Ports.
787 */
788 RT_UNTRUSTED_VALIDATED_FENCE(); /* paranoia */
789 PPITCHANNEL pChan = &pThis->channels[offPort];
790 DEVPIT_LOCK_BOTH_RETURN(pDevIns, pThis, VINF_IOM_R3_IOPORT_WRITE);
791 switch (pChan->write_state)
792 {
793 default:
794 case RW_STATE_LSB:
795 pitR3LoadCount(pDevIns, pThis, pChan, u32);
796 break;
797 case RW_STATE_MSB:
798 pitR3LoadCount(pDevIns, pThis, pChan, u32 << 8);
799 break;
800 case RW_STATE_WORD0:
801 pChan->write_latch = u32;
802 pChan->write_state = RW_STATE_WORD1;
803 break;
804 case RW_STATE_WORD1:
805 pitR3LoadCount(pDevIns, pThis, pChan, pChan->write_latch | (u32 << 8));
806 pChan->write_state = RW_STATE_WORD0;
807 break;
808 }
809 DEVPIT_UNLOCK_BOTH(pDevIns, pThis);
810#endif /* !IN_RING3 */
811 }
812 return VINF_SUCCESS;
813}
814
815
816/**
817 * @callback_method_impl{FNIOMIOPORTNEWIN, Speaker}
818 */
819static DECLCALLBACK(VBOXSTRICTRC)
820pitIOPortSpeakerRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
821{
822 RT_NOREF(pvUser, offPort);
823 if (cb == 1)
824 {
825 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
826 DEVPIT_LOCK_BOTH_RETURN(pDevIns, pThis, VINF_IOM_R3_IOPORT_READ);
827
828 const uint64_t u64Now = PDMDevHlpTimerGet(pDevIns, pThis->channels[0].hTimer);
829 Assert(PDMDevHlpTimerGetFreq(pDevIns, pThis->channels[0].hTimer) == 1000000000); /* lazy bird. */
830
831 /* bit 6,7 Parity error stuff. */
832 /* bit 5 - mirrors timer 2 output condition. */
833 const int fOut = pit_get_out(pDevIns, pThis, 2, u64Now);
834 /* bit 4 - toggled with each (DRAM?) refresh request, every 15.085 u-op Chan.
835 ASSUMES ns timer freq, see assertion above. */
836#ifndef FAKE_REFRESH_CLOCK
837 const int fRefresh = (u64Now / 15085) & 1;
838#else
839 pThis->dummy_refresh_clock ^= 1;
840 const int fRefresh = pThis->dummy_refresh_clock;
841#endif
842 /* bit 2,3 NMI / parity status stuff. */
843 /* bit 1 - speaker data status */
844 const int fSpeakerStatus = pThis->speaker_data_on;
845 /* bit 0 - timer 2 clock gate to speaker status. */
846 const int fTimer2GateStatus = pit_get_gate(pThis, 2);
847
848 DEVPIT_UNLOCK_BOTH(pDevIns, pThis);
849
850 *pu32 = fTimer2GateStatus
851 | (fSpeakerStatus << 1)
852 | (fRefresh << 4)
853 | (fOut << 5);
854 Log(("pitIOPortSpeakerRead: offPort=%#x cb=%x *pu32=%#x\n", offPort, cb, *pu32));
855 return VINF_SUCCESS;
856 }
857 Log(("pitIOPortSpeakerRead: offPort=%#x cb=%x *pu32=unused!\n", offPort, cb));
858 return VERR_IOM_IOPORT_UNUSED;
859}
860
861#ifdef IN_RING3
862
863/**
864 * @callback_method_impl{FNIOMIOPORTNEWOUT, Speaker}
865 */
866static DECLCALLBACK(VBOXSTRICTRC)
867pitR3IOPortSpeakerWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
868{
869 RT_NOREF(pvUser, offPort);
870 if (cb == 1)
871 {
872 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
873 DEVPIT_LOCK_BOTH_RETURN(pDevIns, pThis, VERR_IGNORED);
874
875 pThis->speaker_data_on = (u32 >> 1) & 1;
876 pitR3SetGate(pDevIns, pThis, 2, u32 & 1);
877
878 /** @todo r=klaus move this to a (system-specific) driver, which can
879 * abstract the details, and if necessary create a thread to minimize
880 * impact on VM execution. */
881# ifdef RT_OS_LINUX
882 if (pThis->enmSpeakerEmu != PIT_SPEAKER_EMU_NONE)
883 {
884 PPITCHANNEL pChan = &pThis->channels[2];
885 if (pThis->speaker_data_on)
886 {
887 Log2Func(("starting beep freq=%d\n", PIT_FREQ / pChan->count));
888 switch (pThis->enmSpeakerEmu)
889 {
890 case PIT_SPEAKER_EMU_CONSOLE:
891 {
892 int res;
893 res = ioctl(pThis->hHostSpeaker, KIOCSOUND, pChan->count);
894 if (res == -1)
895 {
896 LogRel(("PIT: speaker: ioctl failed errno=%d, disabling emulation\n", errno));
897 pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
898 }
899 break;
900 }
901 case PIT_SPEAKER_EMU_EVDEV:
902 {
903 struct input_event e;
904 e.type = EV_SND;
905 e.code = SND_TONE;
906 e.value = PIT_FREQ / pChan->count;
907 int res = write(pThis->hHostSpeaker, &e, sizeof(struct input_event));
908 NOREF(res);
909 break;
910 }
911 case PIT_SPEAKER_EMU_TTY:
912 {
913 int res = write(pThis->hHostSpeaker, "\a", 1);
914 NOREF(res);
915 break;
916 }
917 case PIT_SPEAKER_EMU_NONE:
918 break;
919 default:
920 Log2Func(("unknown speaker emulation %d, disabling emulation\n", pThis->enmSpeakerEmu));
921 pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
922 }
923 }
924 else
925 {
926 Log2Func(("stopping beep\n"));
927 switch (pThis->enmSpeakerEmu)
928 {
929 case PIT_SPEAKER_EMU_CONSOLE:
930 /* No error checking here. The Linux device driver
931 * implementation considers it an error (errno=22,
932 * EINVAL) to stop sound if it hasn't been started.
933 * Of course we could detect this by checking only
934 * for enabled->disabled transitions and ignoring
935 * disabled->disabled ones, but it's not worth the
936 * effort. */
937 ioctl(pThis->hHostSpeaker, KIOCSOUND, 0);
938 break;
939 case PIT_SPEAKER_EMU_EVDEV:
940 {
941 struct input_event e;
942 e.type = EV_SND;
943 e.code = SND_TONE;
944 e.value = 0;
945 int res = write(pThis->hHostSpeaker, &e, sizeof(struct input_event));
946 NOREF(res);
947 break;
948 }
949 case PIT_SPEAKER_EMU_TTY:
950 break;
951 case PIT_SPEAKER_EMU_NONE:
952 break;
953 default:
954 Log2Func(("unknown speaker emulation %d, disabling emulation\n", pThis->enmSpeakerEmu));
955 pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
956 }
957 }
958 }
959# endif /* RT_OS_LINUX */
960
961 DEVPIT_UNLOCK_BOTH(pDevIns, pThis);
962 }
963 Log(("pitR3IOPortSpeakerWrite: offPort=%#x cb=%x u32=%#x\n", offPort, cb, u32));
964 return VINF_SUCCESS;
965}
966
967
968/* -=-=-=-=-=- Saved state -=-=-=-=-=- */
969
970/**
971 * @callback_method_impl{FNSSMDEVLIVEEXEC}
972 */
973static DECLCALLBACK(int) pitR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
974{
975 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
976 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
977 RT_NOREF(uPass);
978 pHlp->pfnSSMPutIOPort(pSSM, pThis->IOPortBaseCfg);
979 pHlp->pfnSSMPutU8( pSSM, pThis->channels[0].irq);
980 pHlp->pfnSSMPutBool( pSSM, pThis->fSpeakerCfg);
981 return VINF_SSM_DONT_CALL_AGAIN;
982}
983
984
985/**
986 * @callback_method_impl{FNSSMDEVSAVEEXEC}
987 */
988static DECLCALLBACK(int) pitR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
989{
990 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
991 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
992 PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
993
994 /* The config. */
995 pitR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
996
997 /* The state. */
998 for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++)
999 {
1000 PPITCHANNEL pChan = &pThis->channels[i];
1001 pHlp->pfnSSMPutU32(pSSM, pChan->count);
1002 pHlp->pfnSSMPutU16(pSSM, pChan->latched_count);
1003 pHlp->pfnSSMPutU8(pSSM, pChan->count_latched);
1004 pHlp->pfnSSMPutU8(pSSM, pChan->status_latched);
1005 pHlp->pfnSSMPutU8(pSSM, pChan->status);
1006 pHlp->pfnSSMPutU8(pSSM, pChan->read_state);
1007 pHlp->pfnSSMPutU8(pSSM, pChan->write_state);
1008 pHlp->pfnSSMPutU8(pSSM, pChan->write_latch);
1009 pHlp->pfnSSMPutU8(pSSM, pChan->rw_mode);
1010 pHlp->pfnSSMPutU8(pSSM, pChan->mode);
1011 pHlp->pfnSSMPutU8(pSSM, pChan->bcd);
1012 pHlp->pfnSSMPutU8(pSSM, pChan->gate);
1013 pHlp->pfnSSMPutU64(pSSM, pChan->count_load_time);
1014 pHlp->pfnSSMPutU64(pSSM, pChan->u64NextTS);
1015 pHlp->pfnSSMPutU64(pSSM, pChan->u64ReloadTS);
1016 pHlp->pfnSSMPutS64(pSSM, pChan->next_transition_time);
1017 if (pChan->hTimer != NIL_TMTIMERHANDLE)
1018 PDMDevHlpTimerSave(pDevIns, pChan->hTimer, pSSM);
1019 }
1020
1021 pHlp->pfnSSMPutS32(pSSM, pThis->speaker_data_on);
1022# ifdef FAKE_REFRESH_CLOCK
1023 pHlp->pfnSSMPutS32(pSSM, pThis->dummy_refresh_clock);
1024# else
1025 pHlp->pfnSSMPutS32(pSSM, 0);
1026# endif
1027
1028 pHlp->pfnSSMPutBool(pSSM, pThis->fDisabledByHpet);
1029
1030 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
1031 return VINF_SUCCESS;
1032}
1033
1034
1035/**
1036 * @callback_method_impl{FNSSMDEVLOADEXEC}
1037 */
1038static DECLCALLBACK(int) pitR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1039{
1040 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
1041 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
1042 int rc;
1043
1044 if ( uVersion != PIT_SAVED_STATE_VERSION
1045 && uVersion != PIT_SAVED_STATE_VERSION_VBOX_30
1046 && uVersion != PIT_SAVED_STATE_VERSION_VBOX_31)
1047 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1048
1049 /* The config. */
1050 if (uVersion > PIT_SAVED_STATE_VERSION_VBOX_30)
1051 {
1052 RTIOPORT IOPortBaseCfg;
1053 rc = pHlp->pfnSSMGetIOPort(pSSM, &IOPortBaseCfg); AssertRCReturn(rc, rc);
1054 if (IOPortBaseCfg != pThis->IOPortBaseCfg)
1055 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - IOPortBaseCfg: saved=%RTiop config=%RTiop"),
1056 IOPortBaseCfg, pThis->IOPortBaseCfg);
1057
1058 uint8_t u8Irq;
1059 rc = pHlp->pfnSSMGetU8(pSSM, &u8Irq); AssertRCReturn(rc, rc);
1060 if (u8Irq != pThis->channels[0].irq)
1061 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - u8Irq: saved=%#x config=%#x"),
1062 u8Irq, pThis->channels[0].irq);
1063
1064 bool fSpeakerCfg;
1065 rc = pHlp->pfnSSMGetBool(pSSM, &fSpeakerCfg); AssertRCReturn(rc, rc);
1066 if (fSpeakerCfg != pThis->fSpeakerCfg)
1067 return pHlp->pfnSSMSetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - fSpeakerCfg: saved=%RTbool config=%RTbool"),
1068 fSpeakerCfg, pThis->fSpeakerCfg);
1069 }
1070
1071 if (uPass != SSM_PASS_FINAL)
1072 return VINF_SUCCESS;
1073
1074 /* The state. */
1075 for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++)
1076 {
1077 PPITCHANNEL pChan = &pThis->channels[i];
1078 pHlp->pfnSSMGetU32(pSSM, &pChan->count);
1079 pHlp->pfnSSMGetU16(pSSM, &pChan->latched_count);
1080 pHlp->pfnSSMGetU8(pSSM, &pChan->count_latched);
1081 pHlp->pfnSSMGetU8(pSSM, &pChan->status_latched);
1082 pHlp->pfnSSMGetU8(pSSM, &pChan->status);
1083 pHlp->pfnSSMGetU8(pSSM, &pChan->read_state);
1084 pHlp->pfnSSMGetU8(pSSM, &pChan->write_state);
1085 pHlp->pfnSSMGetU8(pSSM, &pChan->write_latch);
1086 pHlp->pfnSSMGetU8(pSSM, &pChan->rw_mode);
1087 pHlp->pfnSSMGetU8(pSSM, &pChan->mode);
1088 pHlp->pfnSSMGetU8(pSSM, &pChan->bcd);
1089 pHlp->pfnSSMGetU8(pSSM, &pChan->gate);
1090 pHlp->pfnSSMGetU64(pSSM, &pChan->count_load_time);
1091 pHlp->pfnSSMGetU64(pSSM, &pChan->u64NextTS);
1092 pHlp->pfnSSMGetU64(pSSM, &pChan->u64ReloadTS);
1093 pHlp->pfnSSMGetS64(pSSM, &pChan->next_transition_time);
1094 if (pChan->hTimer != NIL_TMTIMERHANDLE)
1095 {
1096 PDMDevHlpTimerLoad(pDevIns, pChan->hTimer, pSSM);
1097 LogRel(("PIT: mode=%d count=%#x (%u) - %d.%02d Hz (ch=%d) (restore)\n",
1098 pChan->mode, pChan->count, pChan->count, PIT_FREQ / pChan->count, (PIT_FREQ * 100 / pChan->count) % 100, i));
1099 PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
1100 PDMDevHlpTimerSetFrequencyHint(pDevIns, pChan->hTimer, PIT_FREQ / pChan->count);
1101 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
1102 }
1103 pThis->channels[i].cRelLogEntries = 0;
1104 }
1105
1106 pHlp->pfnSSMGetS32(pSSM, &pThis->speaker_data_on);
1107# ifdef FAKE_REFRESH_CLOCK
1108 pHlp->pfnSSMGetS32(pSSM, &pThis->dummy_refresh_clock);
1109# else
1110 int32_t u32Dummy;
1111 pHlp->pfnSSMGetS32(pSSM, &u32Dummy);
1112# endif
1113 if (uVersion > PIT_SAVED_STATE_VERSION_VBOX_31)
1114 pHlp->pfnSSMGetBool(pSSM, &pThis->fDisabledByHpet);
1115
1116 return VINF_SUCCESS;
1117}
1118
1119
1120/* -=-=-=-=-=- Timer -=-=-=-=-=- */
1121
1122/**
1123 * @callback_method_impl{FNTMTIMERDEV}
1124 * @param pvUser Pointer to the PIT channel state.
1125 */
1126static DECLCALLBACK(void) pitR3Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
1127{
1128 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
1129 PPITCHANNEL pChan = (PPITCHANNEL)pvUser;
1130 RT_NOREF(pTimer);
1131 STAM_PROFILE_ADV_START(&pThis->StatPITHandler, a);
1132
1133 Log(("pitR3Timer\n"));
1134 Assert(PDMDevHlpCritSectIsOwner(pDevIns, &pThis->CritSect));
1135 Assert(PDMDevHlpTimerIsLockOwner(pDevIns, pChan->hTimer));
1136
1137 pitR3IrqTimerUpdate(pDevIns, pThis, pChan, pChan->next_transition_time, PDMDevHlpTimerGet(pDevIns, pChan->hTimer), true);
1138
1139 STAM_PROFILE_ADV_STOP(&pThis->StatPITHandler, a);
1140}
1141
1142
1143/* -=-=-=-=-=- Debug Info -=-=-=-=-=- */
1144
1145/**
1146 * @callback_method_impl{FNDBGFHANDLERDEV}
1147 */
1148static DECLCALLBACK(void) pitR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
1149{
1150 RT_NOREF(pszArgs);
1151 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
1152 unsigned i;
1153 for (i = 0; i < RT_ELEMENTS(pThis->channels); i++)
1154 {
1155 const PITCHANNEL *pChan = &pThis->channels[i];
1156
1157 pHlp->pfnPrintf(pHlp,
1158 "PIT (i8254) channel %d status: irq=%#x\n"
1159 " count=%08x" " latched_count=%04x count_latched=%02x\n"
1160 " status=%02x status_latched=%02x read_state=%02x\n"
1161 " write_state=%02x write_latch=%02x rw_mode=%02x\n"
1162 " mode=%02x bcd=%02x gate=%02x\n"
1163 " count_load_time=%016RX64 next_transition_time=%016RX64\n"
1164 " u64ReloadTS=%016RX64 u64NextTS=%016RX64\n"
1165 ,
1166 i, pChan->irq,
1167 pChan->count, pChan->latched_count, pChan->count_latched,
1168 pChan->status, pChan->status_latched, pChan->read_state,
1169 pChan->write_state, pChan->write_latch, pChan->rw_mode,
1170 pChan->mode, pChan->bcd, pChan->gate,
1171 pChan->count_load_time, pChan->next_transition_time,
1172 pChan->u64ReloadTS, pChan->u64NextTS);
1173 }
1174# ifdef FAKE_REFRESH_CLOCK
1175 pHlp->pfnPrintf(pHlp, "speaker_data_on=%#x dummy_refresh_clock=%#x\n",
1176 pThis->speaker_data_on, pThis->dummy_refresh_clock);
1177# else
1178 pHlp->pfnPrintf(pHlp, "speaker_data_on=%#x\n", pThis->speaker_data_on);
1179# endif
1180 if (pThis->fDisabledByHpet)
1181 pHlp->pfnPrintf(pHlp, "Disabled by HPET\n");
1182}
1183
1184
1185/* -=-=-=-=-=- IHpetLegacyNotify -=-=-=-=-=- */
1186
1187/**
1188 * @interface_method_impl{PDMIHPETLEGACYNOTIFY,pfnModeChanged}
1189 */
1190static DECLCALLBACK(void) pitR3NotifyHpetLegacyNotify_ModeChanged(PPDMIHPETLEGACYNOTIFY pInterface, bool fActivated)
1191{
1192 PPITSTATER3 pThisCC = RT_FROM_MEMBER(pInterface, PITSTATER3, IHpetLegacyNotify);
1193 PPDMDEVINS pDevIns = pThisCC->pDevIns;
1194 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
1195 PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
1196
1197 pThis->fDisabledByHpet = fActivated;
1198
1199 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
1200}
1201
1202
1203/* -=-=-=-=-=- PDMDEVINS::IBase -=-=-=-=-=- */
1204
1205/**
1206 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
1207 */
1208static DECLCALLBACK(void *) pitR3QueryInterface(PPDMIBASE pInterface, const char *pszIID)
1209{
1210 PPDMDEVINS pDevIns = RT_FROM_MEMBER(pInterface, PDMDEVINS, IBase);
1211 PPITSTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PPITSTATER3);
1212 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevIns->IBase);
1213 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIHPETLEGACYNOTIFY, &pThisCC->IHpetLegacyNotify);
1214 return NULL;
1215}
1216
1217
1218/* -=-=-=-=-=- PDMDEVREG -=-=-=-=-=- */
1219
1220/**
1221 * @interface_method_impl{PDMDEVREG,pfnReset}
1222 */
1223static DECLCALLBACK(void) pitR3Reset(PPDMDEVINS pDevIns)
1224{
1225 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
1226 LogFlow(("pitR3Reset: \n"));
1227
1228 DEVPIT_R3_LOCK_BOTH(pDevIns, pThis);
1229
1230 pThis->fDisabledByHpet = false;
1231
1232 for (unsigned i = 0; i < RT_ELEMENTS(pThis->channels); i++)
1233 {
1234 PPITCHANNEL pChan = &pThis->channels[i];
1235
1236# if 1 /* Set everything back to virgin state. (might not be strictly correct) */
1237 pChan->latched_count = 0;
1238 pChan->count_latched = 0;
1239 pChan->status_latched = 0;
1240 pChan->status = 0;
1241 pChan->read_state = 0;
1242 pChan->write_state = 0;
1243 pChan->write_latch = 0;
1244 pChan->rw_mode = 0;
1245 pChan->bcd = 0;
1246# endif
1247 pChan->u64NextTS = UINT64_MAX;
1248 pChan->cRelLogEntries = 0;
1249 pChan->mode = 3;
1250 pChan->gate = (i != 2);
1251 pitR3LoadCount(pDevIns, pThis, pChan, 0);
1252 }
1253
1254 DEVPIT_UNLOCK_BOTH(pDevIns, pThis);
1255}
1256
1257# ifdef RT_OS_LINUX
1258
1259static int pitR3TryDeviceOpen(const char *pszPath, int flags)
1260{
1261 int fd = open(pszPath, flags);
1262 if (fd == -1)
1263 LogRel(("PIT: speaker: cannot open \"%s\", errno=%d\n", pszPath, errno));
1264 else
1265 LogRel(("PIT: speaker: opened \"%s\"\n", pszPath));
1266 return fd;
1267}
1268
1269
1270static int pitR3TryDeviceOpenSanitizeIoctl(const char *pszPath, int flags)
1271{
1272 int fd = open(pszPath, flags);
1273 if (fd == -1)
1274 LogRel(("PIT: speaker: cannot open \"%s\", errno=%d\n", pszPath, errno));
1275 else
1276 {
1277 int errno_eviocgsnd0 = 0;
1278 int errno_kiocsound = 0;
1279 if (ioctl(fd, EVIOCGSND(0)) == -1)
1280 {
1281 errno_eviocgsnd0 = errno;
1282 if (ioctl(fd, KIOCSOUND, 1) == -1)
1283 errno_kiocsound = errno;
1284 else
1285 ioctl(fd, KIOCSOUND, 0);
1286 }
1287 if (errno_eviocgsnd0 && errno_kiocsound)
1288 {
1289 LogRel(("PIT: speaker: cannot use \"%s\", ioctl failed errno=%d/errno=%d\n", pszPath, errno_eviocgsnd0, errno_kiocsound));
1290 close(fd);
1291 fd = -1;
1292 }
1293 else
1294 LogRel(("PIT: speaker: opened \"%s\"\n", pszPath));
1295 }
1296 return fd;
1297}
1298
1299# endif /* RT_OS_LINUX */
1300
1301/**
1302 * @interface_method_impl{PDMDEVREG,pfnConstruct}
1303 */
1304static DECLCALLBACK(int) pitR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
1305{
1306 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
1307 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
1308 PPITSTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PPITSTATER3);
1309 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
1310 int rc;
1311 uint8_t u8Irq;
1312 uint16_t u16Base;
1313 bool fSpeaker;
1314 unsigned i;
1315 Assert(iInstance == 0);
1316
1317 /*
1318 * Validate and read the configuration.
1319 */
1320 PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, "Irq|Base|SpeakerEnabled|PassthroughSpeaker|PassthroughSpeakerDevice", "");
1321
1322 rc = pHlp->pfnCFGMQueryU8Def(pCfg, "Irq", &u8Irq, 0);
1323 if (RT_FAILURE(rc))
1324 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Querying \"Irq\" as a uint8_t failed"));
1325
1326 rc = pHlp->pfnCFGMQueryU16Def(pCfg, "Base", &u16Base, 0x40);
1327 if (RT_FAILURE(rc))
1328 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Querying \"Base\" as a uint16_t failed"));
1329
1330 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "SpeakerEnabled", &fSpeaker, true);
1331 if (RT_FAILURE(rc))
1332 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: Querying \"SpeakerEnabled\" as a bool failed"));
1333
1334 uint8_t uPassthroughSpeaker;
1335 char *pszPassthroughSpeakerDevice = NULL;
1336 rc = pHlp->pfnCFGMQueryU8Def(pCfg, "PassthroughSpeaker", &uPassthroughSpeaker, 0);
1337 if (RT_FAILURE(rc))
1338 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: failed to read PassthroughSpeaker as uint8_t"));
1339 if (uPassthroughSpeaker)
1340 {
1341 rc = pHlp->pfnCFGMQueryStringAllocDef(pCfg, "PassthroughSpeakerDevice", &pszPassthroughSpeakerDevice, NULL);
1342 if (RT_FAILURE(rc))
1343 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Configuration error: failed to read PassthroughSpeakerDevice as string"));
1344 }
1345
1346 /*
1347 * Init the data.
1348 */
1349 pThis->IOPortBaseCfg = u16Base;
1350 pThis->channels[0].irq = u8Irq;
1351 for (i = 0; i < RT_ELEMENTS(pThis->channels); i++)
1352 {
1353 pThis->channels[i].hTimer = NIL_TMTIMERHANDLE;
1354 pThis->channels[i].iChan = i;
1355 }
1356 pThis->fSpeakerCfg = fSpeaker;
1357 pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_NONE;
1358 if (uPassthroughSpeaker)
1359 {
1360 /** @todo r=klaus move this to a (system-specific) driver */
1361#ifdef RT_OS_LINUX
1362 int fd = -1;
1363 if ((uPassthroughSpeaker == 1 || uPassthroughSpeaker == 100) && fd == -1)
1364 fd = pitR3TryDeviceOpenSanitizeIoctl("/dev/input/by-path/platform-pcspkr-event-spkr", O_WRONLY);
1365 if ((uPassthroughSpeaker == 2 || uPassthroughSpeaker == 100) && fd == -1)
1366 fd = pitR3TryDeviceOpenSanitizeIoctl("/dev/tty", O_WRONLY);
1367 if ((uPassthroughSpeaker == 3 || uPassthroughSpeaker == 100) && fd == -1)
1368 {
1369 fd = pitR3TryDeviceOpenSanitizeIoctl("/dev/tty0", O_WRONLY);
1370 if (fd == -1)
1371 fd = pitR3TryDeviceOpenSanitizeIoctl("/dev/vc/0", O_WRONLY);
1372 }
1373 if ((uPassthroughSpeaker == 9 || uPassthroughSpeaker == 100) && pszPassthroughSpeakerDevice && fd == -1)
1374 fd = pitR3TryDeviceOpenSanitizeIoctl(pszPassthroughSpeakerDevice, O_WRONLY);
1375 if (pThis->enmSpeakerEmu == PIT_SPEAKER_EMU_NONE && fd != -1)
1376 {
1377 pThis->hHostSpeaker = fd;
1378 if (ioctl(fd, EVIOCGSND(0)) != -1)
1379 {
1380 pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_EVDEV;
1381 LogRel(("PIT: speaker: emulation mode evdev\n"));
1382 }
1383 else
1384 {
1385 pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_CONSOLE;
1386 LogRel(("PIT: speaker: emulation mode console\n"));
1387 }
1388 }
1389 if ((uPassthroughSpeaker == 70 || uPassthroughSpeaker == 100) && fd == -1)
1390 fd = pitR3TryDeviceOpen("/dev/tty", O_WRONLY);
1391 if ((uPassthroughSpeaker == 79 || uPassthroughSpeaker == 100) && pszPassthroughSpeakerDevice && fd == -1)
1392 fd = pitR3TryDeviceOpen(pszPassthroughSpeakerDevice, O_WRONLY);
1393 if (pThis->enmSpeakerEmu == PIT_SPEAKER_EMU_NONE && fd != -1)
1394 {
1395 pThis->hHostSpeaker = fd;
1396 pThis->enmSpeakerEmu = PIT_SPEAKER_EMU_TTY;
1397 LogRel(("PIT: speaker: emulation mode tty\n"));
1398 }
1399 if (pThis->enmSpeakerEmu == PIT_SPEAKER_EMU_NONE)
1400 {
1401 Assert(fd == -1);
1402 LogRel(("PIT: speaker: no emulation possible\n"));
1403 }
1404#else
1405 LogRel(("PIT: speaker: emulation deactivated\n"));
1406#endif
1407 if (pszPassthroughSpeakerDevice)
1408 {
1409 PDMDevHlpMMHeapFree(pDevIns, pszPassthroughSpeakerDevice);
1410 pszPassthroughSpeakerDevice = NULL;
1411 }
1412 }
1413
1414 /*
1415 * Interfaces
1416 */
1417 /* IBase */
1418 pDevIns->IBase.pfnQueryInterface = pitR3QueryInterface;
1419 /* IHpetLegacyNotify */
1420 pThisCC->IHpetLegacyNotify.pfnModeChanged = pitR3NotifyHpetLegacyNotify_ModeChanged;
1421 pThisCC->pDevIns = pDevIns;
1422
1423 /*
1424 * We do our own locking. This must be done before creating timers.
1425 */
1426 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, RT_SRC_POS, "pit#%u", iInstance);
1427 AssertRCReturn(rc, rc);
1428
1429 rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
1430 AssertRCReturn(rc, rc);
1431
1432 /*
1433 * Create the timer, make it take our critsect.
1434 */
1435 rc = PDMDevHlpTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, pitR3Timer, &pThis->channels[0],
1436 TMTIMER_FLAGS_NO_CRIT_SECT, "i8254 Programmable Interval Timer", &pThis->channels[0].hTimer);
1437 AssertRCReturn(rc, rc);
1438 rc = PDMDevHlpTimerSetCritSect(pDevIns, pThis->channels[0].hTimer, &pThis->CritSect);
1439 AssertRCReturn(rc, rc);
1440
1441 /*
1442 * Register I/O ports.
1443 */
1444 rc = PDMDevHlpIoPortCreateAndMap(pDevIns, u16Base, 4 /*cPorts*/, pitIOPortWrite, pitIOPortRead,
1445 "i8254 Programmable Interval Timer", NULL /*paExtDescs*/, &pThis->hIoPorts);
1446 AssertRCReturn(rc, rc);
1447
1448 if (fSpeaker)
1449 {
1450 rc = PDMDevHlpIoPortCreateAndMap(pDevIns, 0x61, 1 /*cPorts*/, pitR3IOPortSpeakerWrite, pitIOPortSpeakerRead,
1451 "PC Speaker", NULL /*paExtDescs*/, &pThis->hIoPortSpeaker);
1452 AssertRCReturn(rc, rc);
1453 }
1454
1455 /*
1456 * Saved state.
1457 */
1458 rc = PDMDevHlpSSMRegister3(pDevIns, PIT_SAVED_STATE_VERSION, sizeof(*pThis), pitR3LiveExec, pitR3SaveExec, pitR3LoadExec);
1459 if (RT_FAILURE(rc))
1460 return rc;
1461
1462 /*
1463 * Initialize the device state.
1464 */
1465 pitR3Reset(pDevIns);
1466
1467 /*
1468 * Register statistics and debug info.
1469 */
1470 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatPITIrq, STAMTYPE_COUNTER, "/TM/PIT/Irq", STAMUNIT_OCCURENCES, "The number of times a timer interrupt was triggered.");
1471 PDMDevHlpSTAMRegister(pDevIns, &pThis->StatPITHandler, STAMTYPE_PROFILE, "/TM/PIT/Handler", STAMUNIT_TICKS_PER_CALL, "Profiling timer callback handler.");
1472
1473 PDMDevHlpDBGFInfoRegister(pDevIns, "pit", "Display PIT (i8254) status. (no arguments)", pitR3Info);
1474
1475 return VINF_SUCCESS;
1476}
1477
1478#else /* !IN_RING3 */
1479
1480/**
1481 * @callback_method_impl{PDMDEVREGR0,pfnConstruct}
1482 */
1483static DECLCALLBACK(int) picRZConstruct(PPDMDEVINS pDevIns)
1484{
1485 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
1486 PPITSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PPITSTATE);
1487
1488 int rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
1489 AssertRCReturn(rc, rc);
1490
1491 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPorts, pitIOPortWrite, pitIOPortRead, NULL /*pvUser*/);
1492 AssertRCReturn(rc, rc);
1493
1494 rc = PDMDevHlpIoPortSetUpContext(pDevIns, pThis->hIoPortSpeaker, NULL /*pfnWrite*/, pitIOPortSpeakerRead, NULL /*pvUser*/);
1495 AssertRCReturn(rc, rc);
1496
1497 return VINF_SUCCESS;
1498}
1499
1500#endif /* !IN_RING3 */
1501
1502/**
1503 * The device registration structure.
1504 */
1505const PDMDEVREG g_DeviceI8254 =
1506{
1507 /* .u32Version = */ PDM_DEVREG_VERSION,
1508 /* .uReserved0 = */ 0,
1509 /* .szName = */ "i8254",
1510 /* .fFlags = */ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RZ | PDM_DEVREG_FLAGS_NEW_STYLE,
1511 /* .fClass = */ PDM_DEVREG_CLASS_PIT,
1512 /* .cMaxInstances = */ 1,
1513 /* .uSharedVersion = */ 42,
1514 /* .cbInstanceShared = */ sizeof(PITSTATE),
1515 /* .cbInstanceCC = */ CTX_EXPR(sizeof(PITSTATER3), 0, 0),
1516 /* .cbInstanceRC = */ 0,
1517 /* .cMaxPciDevices = */ 0,
1518 /* .cMaxMsixVectors = */ 0,
1519 /* .pszDescription = */ "Intel 8254 Programmable Interval Timer (PIT) And Dummy Speaker Device",
1520#if defined(IN_RING3)
1521 /* .pszRCMod = */ "VBoxDDRC.rc",
1522 /* .pszR0Mod = */ "VBoxDDR0.r0",
1523 /* .pfnConstruct = */ pitR3Construct,
1524 /* .pfnDestruct = */ NULL,
1525 /* .pfnRelocate = */ NULL,
1526 /* .pfnMemSetup = */ NULL,
1527 /* .pfnPowerOn = */ NULL,
1528 /* .pfnReset = */ pitR3Reset,
1529 /* .pfnSuspend = */ NULL,
1530 /* .pfnResume = */ NULL,
1531 /* .pfnAttach = */ NULL,
1532 /* .pfnDetach = */ NULL,
1533 /* .pfnQueryInterface = */ NULL,
1534 /* .pfnInitComplete = */ NULL,
1535 /* .pfnPowerOff = */ NULL,
1536 /* .pfnSoftReset = */ NULL,
1537 /* .pfnReserved0 = */ NULL,
1538 /* .pfnReserved1 = */ NULL,
1539 /* .pfnReserved2 = */ NULL,
1540 /* .pfnReserved3 = */ NULL,
1541 /* .pfnReserved4 = */ NULL,
1542 /* .pfnReserved5 = */ NULL,
1543 /* .pfnReserved6 = */ NULL,
1544 /* .pfnReserved7 = */ NULL,
1545#elif defined(IN_RING0)
1546 /* .pfnEarlyConstruct = */ NULL,
1547 /* .pfnConstruct = */ picRZConstruct,
1548 /* .pfnDestruct = */ NULL,
1549 /* .pfnFinalDestruct = */ NULL,
1550 /* .pfnRequest = */ NULL,
1551 /* .pfnReserved0 = */ NULL,
1552 /* .pfnReserved1 = */ NULL,
1553 /* .pfnReserved2 = */ NULL,
1554 /* .pfnReserved3 = */ NULL,
1555 /* .pfnReserved4 = */ NULL,
1556 /* .pfnReserved5 = */ NULL,
1557 /* .pfnReserved6 = */ NULL,
1558 /* .pfnReserved7 = */ NULL,
1559#elif defined(IN_RC)
1560 /* .pfnConstruct = */ picRZConstruct,
1561 /* .pfnReserved0 = */ NULL,
1562 /* .pfnReserved1 = */ NULL,
1563 /* .pfnReserved2 = */ NULL,
1564 /* .pfnReserved3 = */ NULL,
1565 /* .pfnReserved4 = */ NULL,
1566 /* .pfnReserved5 = */ NULL,
1567 /* .pfnReserved6 = */ NULL,
1568 /* .pfnReserved7 = */ NULL,
1569#else
1570# error "Not in IN_RING3, IN_RING0 or IN_RC!"
1571#endif
1572 /* .u32VersionEnd = */ PDM_DEVREG_VERSION
1573};
1574
1575#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette