Committed the two missing files.

This commit is contained in:
OBattler
2023-04-19 23:46:33 +02:00
parent f16feb6e8c
commit 06fc5e9d0d
2 changed files with 2309 additions and 0 deletions

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
View 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);
}