Committed the two missing files.
This commit is contained in:
2111
src/device/kbc_at.c
Normal file
2111
src/device/kbc_at.c
Normal file
File diff suppressed because it is too large
Load Diff
198
src/device/kbc_at_dev.c
Normal file
198
src/device/kbc_at_dev.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* AT / PS/2 attached device emulation.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2023 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/ppi.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/m_at_t3100e.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/sound.h>
|
||||
#include <86box/snd_speaker.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/keyboard.h>
|
||||
|
||||
#ifdef ENABLE_KBC_AT_DEV_LOG
|
||||
int kbc_at_dev_do_log = ENABLE_KBC_AT_DEV_LOG;
|
||||
|
||||
static void
|
||||
kbc_at_dev_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (kbc_at_dev_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define kbc_at_dev_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
kbc_at_dev_queue_reset(atkbc_dev_t *dev, uint8_t reset_main)
|
||||
{
|
||||
if (reset_main) {
|
||||
dev->queue_start = dev->queue_end = 0;
|
||||
memset(dev->queue, 0x00, sizeof(dev->queue));
|
||||
}
|
||||
|
||||
dev->cmd_queue_start = dev->cmd_queue_end = 0;
|
||||
memset(dev->cmd_queue, 0x00, sizeof(dev->cmd_queue));
|
||||
}
|
||||
|
||||
uint8_t
|
||||
kbc_at_dev_queue_pos(atkbc_dev_t *dev, uint8_t main)
|
||||
{
|
||||
uint8_t ret;
|
||||
|
||||
if (main)
|
||||
ret = ((dev->queue_end - dev->queue_start) & 0xf);
|
||||
else
|
||||
ret = ((dev->cmd_queue_end - dev->cmd_queue_start) & 0xf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_dev_queue_add(atkbc_dev_t *dev, uint8_t val, uint8_t main)
|
||||
{
|
||||
if (main) {
|
||||
kbc_at_dev_log("%s: dev->queue[%02X] = %02X;\n", dev->name, dev->queue_end, val);
|
||||
dev->queue[dev->queue_end] = val;
|
||||
dev->queue_end = (dev->queue_end + 1) & 0xf;
|
||||
} else {
|
||||
kbc_at_dev_log("%s: dev->cmd_queue[%02X] = %02X;\n", dev->name, dev->cmd_queue_end, val);
|
||||
dev->cmd_queue[dev->cmd_queue_end] = val;
|
||||
dev->cmd_queue_end = (dev->cmd_queue_end + 1) & 0xf;
|
||||
}
|
||||
|
||||
/* TODO: This should be done on actual send to host. */
|
||||
if (val != 0xfe)
|
||||
dev->last_scan_code = val;
|
||||
}
|
||||
|
||||
static void
|
||||
kbc_at_dev_poll(void *priv)
|
||||
{
|
||||
atkbc_dev_t *dev = (atkbc_dev_t *) priv;
|
||||
|
||||
switch (dev->state) {
|
||||
case DEV_STATE_MAIN_1:
|
||||
/* Process the command if needed and then return to main loop #2. */
|
||||
if (dev->port->wantcmd) {
|
||||
kbc_at_dev_log("%s: Processing keyboard command %02X...\n", dev->name, dev->port->dat);
|
||||
kbc_at_dev_queue_reset(dev, 0);
|
||||
dev->process_cmd(dev);
|
||||
dev->port->wantcmd = 0;
|
||||
} else
|
||||
dev->state = DEV_STATE_MAIN_2;
|
||||
break;
|
||||
case DEV_STATE_MAIN_2:
|
||||
/* Output from scan queue if needed and then return to main loop #1. */
|
||||
if (*dev->scan && (dev->port->out_new == -1) && (dev->queue_start != dev->queue_end)) {
|
||||
kbc_at_dev_log("%s %1: %02X (DATA) on channel 1\n", dev->name, dev->inst, dev->queue[dev->queue_start]);
|
||||
dev->port->out_new = dev->queue[dev->queue_start];
|
||||
dev->queue_start = (dev->queue_start + 1) & 0xf;
|
||||
}
|
||||
if (!(*dev->scan) || dev->port->wantcmd)
|
||||
dev->state = DEV_STATE_MAIN_1;
|
||||
break;
|
||||
case DEV_STATE_MAIN_OUT:
|
||||
/* If host wants to send command while we're sending a byte to host, process the command. */
|
||||
if (dev->port->wantcmd) {
|
||||
kbc_at_dev_log("%s: Processing keyboard command %02X...\n", dev->name, dev->port->dat);
|
||||
kbc_at_dev_queue_reset(dev, 0);
|
||||
dev->process_cmd(dev);
|
||||
dev->port->wantcmd = 0;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case DEV_STATE_MAIN_WANT_IN:
|
||||
/* Output command response and then return to main loop #2. */
|
||||
if ((dev->port->out_new == -1) && (dev->cmd_queue_start != dev->cmd_queue_end)) {
|
||||
kbc_at_dev_log("%s: %02X (CMD ) on channel 1\n", dev->name, dev->cmd_queue[dev->cmd_queue_start]);
|
||||
dev->port->out_new = dev->cmd_queue[dev->cmd_queue_start];
|
||||
dev->cmd_queue_start = (dev->cmd_queue_start + 1) & 0xf;
|
||||
}
|
||||
if (dev->cmd_queue_start == dev->cmd_queue_end)
|
||||
dev->state = (dev->state == DEV_STATE_MAIN_OUT) ? DEV_STATE_MAIN_2 : DEV_STATE_MAIN_IN;
|
||||
break;
|
||||
case DEV_STATE_MAIN_IN:
|
||||
/* Wait for host data. */
|
||||
if (dev->port->wantcmd) {
|
||||
kbc_at_dev_log("%s: Processing keyboard command %02X parameter %02X...\n", dev->name, dev->command, dev->port->dat);
|
||||
kbc_at_dev_queue_reset(dev, 0);
|
||||
dev->process_cmd(dev);
|
||||
dev->port->wantcmd = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
kbc_at_dev_reset(atkbc_dev_t *dev, int do_fa)
|
||||
{
|
||||
dev->port->out_new = -1;
|
||||
dev->port->wantcmd = 0;
|
||||
|
||||
kbc_at_dev_queue_reset(dev, 1);
|
||||
|
||||
dev->last_scan_code = 0x00;
|
||||
|
||||
*dev->scan = 1;
|
||||
|
||||
if (do_fa)
|
||||
kbc_at_dev_queue_add(dev, 0xfa, 0);
|
||||
|
||||
dev->execute_bat(dev);
|
||||
|
||||
dev->state = DEV_STATE_MAIN_OUT;
|
||||
}
|
||||
|
||||
atkbc_dev_t *
|
||||
kbc_at_dev_init(uint8_t inst)
|
||||
{
|
||||
atkbc_dev_t *dev;
|
||||
|
||||
dev = (atkbc_dev_t *) malloc(sizeof(atkbc_dev_t));
|
||||
memset(dev, 0x00, sizeof(atkbc_dev_t));
|
||||
|
||||
dev->port = kbc_at_ports[inst];
|
||||
|
||||
if (dev->port != NULL) {
|
||||
dev->port->priv = dev;
|
||||
dev->port->poll = kbc_at_dev_poll;
|
||||
}
|
||||
|
||||
/* Return our private data to the I/O layer. */
|
||||
return (dev);
|
||||
}
|
Reference in New Issue
Block a user