Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/bhyve/amd64/atkbdc.c
106842 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2014 Tycho Nightingale <[email protected]>
5
* Copyright (c) 2015 Nahanni Systems Inc.
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <sys/types.h>
31
32
#include <machine/vmm.h>
33
#include <machine/vmm_snapshot.h>
34
35
#include <vmmapi.h>
36
37
#include <assert.h>
38
#include <errno.h>
39
#include <stdbool.h>
40
#include <stdlib.h>
41
#include <stdio.h>
42
#include <string.h>
43
#include <unistd.h>
44
#include <pthread.h>
45
#include <pthread_np.h>
46
47
#include "acpi.h"
48
#include "atkbdc.h"
49
#include "inout.h"
50
#include "pci_emul.h"
51
#include "pci_irq.h"
52
#include "pci_lpc.h"
53
#include "ps2kbd.h"
54
#include "ps2mouse.h"
55
56
#define KBD_DATA_PORT 0x60
57
58
#define KBD_STS_CTL_PORT 0x64
59
60
#define KBDC_RESET 0xfe
61
62
#define KBD_DEV_IRQ 1
63
#define AUX_DEV_IRQ 12
64
65
/* controller commands */
66
#define KBDC_SET_COMMAND_BYTE 0x60
67
#define KBDC_GET_COMMAND_BYTE 0x20
68
#define KBDC_DISABLE_AUX_PORT 0xa7
69
#define KBDC_ENABLE_AUX_PORT 0xa8
70
#define KBDC_TEST_AUX_PORT 0xa9
71
#define KBDC_TEST_CTRL 0xaa
72
#define KBDC_TEST_KBD_PORT 0xab
73
#define KBDC_DISABLE_KBD_PORT 0xad
74
#define KBDC_ENABLE_KBD_PORT 0xae
75
#define KBDC_READ_INPORT 0xc0
76
#define KBDC_READ_OUTPORT 0xd0
77
#define KBDC_WRITE_OUTPORT 0xd1
78
#define KBDC_WRITE_KBD_OUTBUF 0xd2
79
#define KBDC_WRITE_AUX_OUTBUF 0xd3
80
#define KBDC_WRITE_TO_AUX 0xd4
81
82
/* controller command byte (set by KBDC_SET_COMMAND_BYTE) */
83
#define KBD_TRANSLATION 0x40
84
#define KBD_SYS_FLAG_BIT 0x04
85
#define KBD_DISABLE_KBD_PORT 0x10
86
#define KBD_DISABLE_AUX_PORT 0x20
87
#define KBD_ENABLE_AUX_INT 0x02
88
#define KBD_ENABLE_KBD_INT 0x01
89
#define KBD_KBD_CONTROL_BITS (KBD_DISABLE_KBD_PORT | KBD_ENABLE_KBD_INT)
90
#define KBD_AUX_CONTROL_BITS (KBD_DISABLE_AUX_PORT | KBD_ENABLE_AUX_INT)
91
92
/* controller status bits */
93
#define KBDS_KBD_BUFFER_FULL 0x01
94
#define KBDS_SYS_FLAG 0x04
95
#define KBDS_CTRL_FLAG 0x08
96
#define KBDS_AUX_BUFFER_FULL 0x20
97
98
/* controller output port */
99
#define KBDO_KBD_OUTFULL 0x10
100
#define KBDO_AUX_OUTFULL 0x20
101
102
#define RAMSZ 32
103
#define FIFOSZ 15
104
#define CTRL_CMD_FLAG 0x8000
105
106
struct kbd_dev {
107
bool irq_active;
108
int irq;
109
110
uint8_t buffer[FIFOSZ];
111
int brd, bwr;
112
int bcnt;
113
};
114
115
struct aux_dev {
116
bool irq_active;
117
int irq;
118
};
119
120
struct atkbdc_softc {
121
struct vmctx *ctx;
122
pthread_mutex_t mtx;
123
124
struct ps2kbd_softc *ps2kbd_sc;
125
struct ps2mouse_softc *ps2mouse_sc;
126
127
uint8_t status; /* status register */
128
uint8_t outport; /* controller output port */
129
uint8_t ram[RAMSZ]; /* byte0 = controller config */
130
131
uint32_t curcmd; /* current command for next byte */
132
uint32_t ctrlbyte;
133
134
struct kbd_dev kbd;
135
struct aux_dev aux;
136
};
137
138
#ifdef BHYVE_SNAPSHOT
139
static struct atkbdc_softc *atkbdc_sc = NULL;
140
#endif
141
142
static void
143
atkbdc_assert_kbd_intr(struct atkbdc_softc *sc)
144
{
145
if ((sc->ram[0] & KBD_ENABLE_KBD_INT) != 0) {
146
sc->kbd.irq_active = true;
147
vm_isa_pulse_irq(sc->ctx, sc->kbd.irq, sc->kbd.irq);
148
}
149
}
150
151
static void
152
atkbdc_assert_aux_intr(struct atkbdc_softc *sc)
153
{
154
if ((sc->ram[0] & KBD_ENABLE_AUX_INT) != 0) {
155
sc->aux.irq_active = true;
156
vm_isa_pulse_irq(sc->ctx, sc->aux.irq, sc->aux.irq);
157
}
158
}
159
160
static int
161
atkbdc_kbd_queue_data(struct atkbdc_softc *sc, uint8_t val)
162
{
163
assert(pthread_mutex_isowned_np(&sc->mtx));
164
165
if (sc->kbd.bcnt < FIFOSZ) {
166
sc->kbd.buffer[sc->kbd.bwr] = val;
167
sc->kbd.bwr = (sc->kbd.bwr + 1) % FIFOSZ;
168
sc->kbd.bcnt++;
169
sc->status |= KBDS_KBD_BUFFER_FULL;
170
sc->outport |= KBDO_KBD_OUTFULL;
171
} else {
172
printf("atkbd data buffer full\n");
173
}
174
175
return (sc->kbd.bcnt < FIFOSZ);
176
}
177
178
static void
179
atkbdc_kbd_read(struct atkbdc_softc *sc)
180
{
181
const uint8_t translation[256] = {
182
0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58,
183
0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
184
0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a,
185
0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
186
0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c,
187
0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
188
0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e,
189
0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
190
0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60,
191
0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
192
0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e,
193
0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
194
0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b,
195
0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
196
0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45,
197
0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
198
0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87,
199
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
200
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
201
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
202
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
203
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
204
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
205
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
206
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
207
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
208
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
209
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
210
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
211
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
212
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
213
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
214
};
215
uint8_t val;
216
uint8_t release = 0;
217
218
assert(pthread_mutex_isowned_np(&sc->mtx));
219
220
if (sc->ram[0] & KBD_TRANSLATION) {
221
while (ps2kbd_read(sc->ps2kbd_sc, &val) != -1) {
222
if (val == 0xf0) {
223
release = 0x80;
224
continue;
225
} else {
226
val = translation[val] | release;
227
}
228
atkbdc_kbd_queue_data(sc, val);
229
break;
230
}
231
} else {
232
while (sc->kbd.bcnt < FIFOSZ) {
233
if (ps2kbd_read(sc->ps2kbd_sc, &val) != -1)
234
atkbdc_kbd_queue_data(sc, val);
235
else
236
break;
237
}
238
}
239
240
if (((sc->ram[0] & KBD_DISABLE_AUX_PORT) ||
241
ps2mouse_fifocnt(sc->ps2mouse_sc) == 0) && sc->kbd.bcnt > 0)
242
atkbdc_assert_kbd_intr(sc);
243
}
244
245
static void
246
atkbdc_aux_poll(struct atkbdc_softc *sc)
247
{
248
if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0) {
249
sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL;
250
sc->outport |= KBDO_AUX_OUTFULL;
251
atkbdc_assert_aux_intr(sc);
252
}
253
}
254
255
static void
256
atkbdc_kbd_poll(struct atkbdc_softc *sc)
257
{
258
assert(pthread_mutex_isowned_np(&sc->mtx));
259
260
atkbdc_kbd_read(sc);
261
}
262
263
static void
264
atkbdc_poll(struct atkbdc_softc *sc)
265
{
266
atkbdc_aux_poll(sc);
267
atkbdc_kbd_poll(sc);
268
}
269
270
static void
271
atkbdc_dequeue_data(struct atkbdc_softc *sc, uint8_t *buf)
272
{
273
assert(pthread_mutex_isowned_np(&sc->mtx));
274
275
if (ps2mouse_read(sc->ps2mouse_sc, buf) == 0) {
276
if (ps2mouse_fifocnt(sc->ps2mouse_sc) == 0) {
277
if (sc->kbd.bcnt == 0)
278
sc->status &= ~(KBDS_AUX_BUFFER_FULL |
279
KBDS_KBD_BUFFER_FULL);
280
else
281
sc->status &= ~(KBDS_AUX_BUFFER_FULL);
282
sc->outport &= ~KBDO_AUX_OUTFULL;
283
}
284
285
atkbdc_poll(sc);
286
return;
287
}
288
289
if (sc->kbd.bcnt > 0) {
290
*buf = sc->kbd.buffer[sc->kbd.brd];
291
sc->kbd.brd = (sc->kbd.brd + 1) % FIFOSZ;
292
sc->kbd.bcnt--;
293
if (sc->kbd.bcnt == 0) {
294
sc->status &= ~KBDS_KBD_BUFFER_FULL;
295
sc->outport &= ~KBDO_KBD_OUTFULL;
296
}
297
298
atkbdc_poll(sc);
299
}
300
301
if (ps2mouse_fifocnt(sc->ps2mouse_sc) == 0 && sc->kbd.bcnt == 0) {
302
sc->status &= ~(KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL);
303
}
304
}
305
306
static int
307
atkbdc_data_handler(struct vmctx *ctx __unused, int in,
308
int port __unused, int bytes, uint32_t *eax, void *arg)
309
{
310
struct atkbdc_softc *sc;
311
uint8_t buf;
312
int retval;
313
314
if (bytes != 1)
315
return (-1);
316
sc = arg;
317
retval = 0;
318
319
pthread_mutex_lock(&sc->mtx);
320
if (in) {
321
sc->curcmd = 0;
322
if (sc->ctrlbyte != 0) {
323
*eax = sc->ctrlbyte & 0xff;
324
sc->ctrlbyte = 0;
325
} else {
326
/* read device buffer; includes kbd cmd responses */
327
atkbdc_dequeue_data(sc, &buf);
328
*eax = buf;
329
}
330
331
sc->status &= ~KBDS_CTRL_FLAG;
332
pthread_mutex_unlock(&sc->mtx);
333
return (retval);
334
}
335
336
if (sc->status & KBDS_CTRL_FLAG) {
337
/*
338
* Command byte for the controller.
339
*/
340
switch (sc->curcmd) {
341
case KBDC_SET_COMMAND_BYTE:
342
sc->ram[0] = *eax;
343
if (sc->ram[0] & KBD_SYS_FLAG_BIT)
344
sc->status |= KBDS_SYS_FLAG;
345
else
346
sc->status &= ~KBDS_SYS_FLAG;
347
break;
348
case KBDC_WRITE_OUTPORT:
349
sc->outport = *eax;
350
break;
351
case KBDC_WRITE_TO_AUX:
352
ps2mouse_write(sc->ps2mouse_sc, *eax, 0);
353
atkbdc_poll(sc);
354
break;
355
case KBDC_WRITE_KBD_OUTBUF:
356
atkbdc_kbd_queue_data(sc, *eax);
357
break;
358
case KBDC_WRITE_AUX_OUTBUF:
359
ps2mouse_write(sc->ps2mouse_sc, *eax, 1);
360
sc->status |= (KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL);
361
atkbdc_aux_poll(sc);
362
break;
363
default:
364
/* write to particular RAM byte */
365
if (sc->curcmd >= 0x61 && sc->curcmd <= 0x7f) {
366
int byten;
367
368
byten = (sc->curcmd - 0x60) & 0x1f;
369
sc->ram[byten] = *eax & 0xff;
370
}
371
break;
372
}
373
374
sc->curcmd = 0;
375
sc->status &= ~KBDS_CTRL_FLAG;
376
377
pthread_mutex_unlock(&sc->mtx);
378
return (retval);
379
}
380
381
/*
382
* Data byte for the device.
383
*/
384
ps2kbd_write(sc->ps2kbd_sc, *eax);
385
atkbdc_poll(sc);
386
387
pthread_mutex_unlock(&sc->mtx);
388
389
return (retval);
390
}
391
392
static int
393
atkbdc_sts_ctl_handler(struct vmctx *ctx, int in,
394
int port __unused, int bytes, uint32_t *eax, void *arg)
395
{
396
struct atkbdc_softc *sc;
397
int error, retval;
398
399
if (bytes != 1)
400
return (-1);
401
402
sc = arg;
403
retval = 0;
404
405
pthread_mutex_lock(&sc->mtx);
406
407
if (in) {
408
/* read status register */
409
*eax = sc->status;
410
pthread_mutex_unlock(&sc->mtx);
411
return (retval);
412
}
413
414
415
sc->curcmd = 0;
416
sc->status |= KBDS_CTRL_FLAG;
417
sc->ctrlbyte = 0;
418
419
switch (*eax) {
420
case KBDC_GET_COMMAND_BYTE:
421
sc->ctrlbyte = CTRL_CMD_FLAG | sc->ram[0];
422
break;
423
case KBDC_TEST_CTRL:
424
sc->ctrlbyte = CTRL_CMD_FLAG | 0x55;
425
break;
426
case KBDC_TEST_AUX_PORT:
427
case KBDC_TEST_KBD_PORT:
428
sc->ctrlbyte = CTRL_CMD_FLAG | 0;
429
break;
430
case KBDC_READ_INPORT:
431
sc->ctrlbyte = CTRL_CMD_FLAG | 0;
432
break;
433
case KBDC_READ_OUTPORT:
434
sc->ctrlbyte = CTRL_CMD_FLAG | sc->outport;
435
break;
436
case KBDC_SET_COMMAND_BYTE:
437
case KBDC_WRITE_OUTPORT:
438
case KBDC_WRITE_KBD_OUTBUF:
439
case KBDC_WRITE_AUX_OUTBUF:
440
sc->curcmd = *eax;
441
break;
442
case KBDC_DISABLE_KBD_PORT:
443
sc->ram[0] |= KBD_DISABLE_KBD_PORT;
444
break;
445
case KBDC_ENABLE_KBD_PORT:
446
sc->ram[0] &= ~KBD_DISABLE_KBD_PORT;
447
if (sc->kbd.bcnt > 0)
448
sc->status |= KBDS_KBD_BUFFER_FULL;
449
atkbdc_poll(sc);
450
break;
451
case KBDC_WRITE_TO_AUX:
452
sc->curcmd = *eax;
453
break;
454
case KBDC_DISABLE_AUX_PORT:
455
sc->ram[0] |= KBD_DISABLE_AUX_PORT;
456
ps2mouse_toggle(sc->ps2mouse_sc, 0);
457
sc->status &= ~(KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL);
458
sc->outport &= ~KBDS_AUX_BUFFER_FULL;
459
break;
460
case KBDC_ENABLE_AUX_PORT:
461
sc->ram[0] &= ~KBD_DISABLE_AUX_PORT;
462
ps2mouse_toggle(sc->ps2mouse_sc, 1);
463
if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0)
464
sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL;
465
break;
466
case KBDC_RESET: /* Pulse "reset" line */
467
error = vm_suspend(ctx, VM_SUSPEND_RESET);
468
assert(error == 0 || errno == EALREADY);
469
break;
470
default:
471
if (*eax >= 0x21 && *eax <= 0x3f) {
472
/* read "byte N" from RAM */
473
int byten;
474
475
byten = (*eax - 0x20) & 0x1f;
476
sc->ctrlbyte = CTRL_CMD_FLAG | sc->ram[byten];
477
}
478
break;
479
}
480
481
pthread_mutex_unlock(&sc->mtx);
482
483
if (sc->ctrlbyte != 0) {
484
sc->status |= KBDS_KBD_BUFFER_FULL;
485
sc->status &= ~KBDS_AUX_BUFFER_FULL;
486
atkbdc_assert_kbd_intr(sc);
487
} else if (ps2mouse_fifocnt(sc->ps2mouse_sc) > 0 &&
488
(sc->ram[0] & KBD_DISABLE_AUX_PORT) == 0) {
489
sc->status |= KBDS_AUX_BUFFER_FULL | KBDS_KBD_BUFFER_FULL;
490
atkbdc_assert_aux_intr(sc);
491
} else if (sc->kbd.bcnt > 0 && (sc->ram[0] & KBD_DISABLE_KBD_PORT) == 0) {
492
sc->status |= KBDS_KBD_BUFFER_FULL;
493
atkbdc_assert_kbd_intr(sc);
494
}
495
496
return (retval);
497
}
498
499
void
500
atkbdc_event(struct atkbdc_softc *sc, int iskbd)
501
{
502
pthread_mutex_lock(&sc->mtx);
503
504
if (iskbd)
505
atkbdc_kbd_poll(sc);
506
else
507
atkbdc_aux_poll(sc);
508
pthread_mutex_unlock(&sc->mtx);
509
}
510
511
void
512
atkbdc_init(struct vmctx *ctx)
513
{
514
struct inout_port iop;
515
struct atkbdc_softc *sc;
516
int error;
517
518
sc = calloc(1, sizeof(struct atkbdc_softc));
519
sc->ctx = ctx;
520
521
pthread_mutex_init(&sc->mtx, NULL);
522
523
bzero(&iop, sizeof(struct inout_port));
524
iop.name = "atkdbc";
525
iop.port = KBD_STS_CTL_PORT;
526
iop.size = 1;
527
iop.flags = IOPORT_F_INOUT;
528
iop.handler = atkbdc_sts_ctl_handler;
529
iop.arg = sc;
530
531
error = register_inout(&iop);
532
assert(error == 0);
533
534
bzero(&iop, sizeof(struct inout_port));
535
iop.name = "atkdbc";
536
iop.port = KBD_DATA_PORT;
537
iop.size = 1;
538
iop.flags = IOPORT_F_INOUT;
539
iop.handler = atkbdc_data_handler;
540
iop.arg = sc;
541
542
error = register_inout(&iop);
543
assert(error == 0);
544
545
pci_irq_reserve(KBD_DEV_IRQ);
546
sc->kbd.irq = KBD_DEV_IRQ;
547
548
pci_irq_reserve(AUX_DEV_IRQ);
549
sc->aux.irq = AUX_DEV_IRQ;
550
551
sc->ps2kbd_sc = ps2kbd_init(sc);
552
sc->ps2mouse_sc = ps2mouse_init(sc);
553
554
#ifdef BHYVE_SNAPSHOT
555
assert(atkbdc_sc == NULL);
556
atkbdc_sc = sc;
557
#endif
558
}
559
560
#ifdef BHYVE_SNAPSHOT
561
int
562
atkbdc_snapshot(struct vm_snapshot_meta *meta)
563
{
564
int ret;
565
566
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->status, meta, ret, done);
567
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->outport, meta, ret, done);
568
SNAPSHOT_BUF_OR_LEAVE(atkbdc_sc->ram,
569
sizeof(atkbdc_sc->ram), meta, ret, done);
570
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->curcmd, meta, ret, done);
571
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->ctrlbyte, meta, ret, done);
572
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd, meta, ret, done);
573
574
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.irq_active, meta, ret, done);
575
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.irq, meta, ret, done);
576
SNAPSHOT_BUF_OR_LEAVE(atkbdc_sc->kbd.buffer,
577
sizeof(atkbdc_sc->kbd.buffer), meta, ret, done);
578
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.brd, meta, ret, done);
579
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.bwr, meta, ret, done);
580
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->kbd.bcnt, meta, ret, done);
581
582
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq_active, meta, ret, done);
583
SNAPSHOT_VAR_OR_LEAVE(atkbdc_sc->aux.irq, meta, ret, done);
584
585
ret = ps2kbd_snapshot(atkbdc_sc->ps2kbd_sc, meta);
586
if (ret != 0)
587
goto done;
588
589
ret = ps2mouse_snapshot(atkbdc_sc->ps2mouse_sc, meta);
590
591
done:
592
return (ret);
593
}
594
#endif
595
596
static void
597
atkbdc_dsdt(void)
598
{
599
600
dsdt_line("");
601
dsdt_line("Device (KBD)");
602
dsdt_line("{");
603
dsdt_line(" Name (_HID, EisaId (\"PNP0303\"))");
604
dsdt_line(" Name (_CRS, ResourceTemplate ()");
605
dsdt_line(" {");
606
dsdt_indent(2);
607
dsdt_fixed_ioport(KBD_DATA_PORT, 1);
608
dsdt_fixed_ioport(KBD_STS_CTL_PORT, 1);
609
dsdt_fixed_irq(1);
610
dsdt_unindent(2);
611
dsdt_line(" })");
612
dsdt_line("}");
613
614
dsdt_line("");
615
dsdt_line("Device (MOU)");
616
dsdt_line("{");
617
dsdt_line(" Name (_HID, EisaId (\"PNP0F13\"))");
618
dsdt_line(" Name (_CRS, ResourceTemplate ()");
619
dsdt_line(" {");
620
dsdt_indent(2);
621
dsdt_fixed_ioport(KBD_DATA_PORT, 1);
622
dsdt_fixed_ioport(KBD_STS_CTL_PORT, 1);
623
dsdt_fixed_irq(12);
624
dsdt_unindent(2);
625
dsdt_line(" })");
626
dsdt_line("}");
627
}
628
LPC_DSDT(atkbdc_dsdt);
629
630
631