From 070d5c419057bb919fd0871daecb5d9b89568a30 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Wed, 3 May 2023 01:12:19 -0400 Subject: [PATCH 01/34] Allow configuration of additional network adaptors in win32 ui --- src/win/languages/dialogs.rc | 66 ++++++++++-- src/win/win_settings.c | 197 ++++++++++++++++++++++------------- 2 files changed, 181 insertions(+), 82 deletions(-) diff --git a/src/win/languages/dialogs.rc b/src/win/languages/dialogs.rc index ef3b8ac62..83d81e074 100644 --- a/src/win/languages/dialogs.rc +++ b/src/win/languages/dialogs.rc @@ -402,23 +402,67 @@ FONT FONT_SIZE, FONT_NAME BEGIN LTEXT STR_NET_TYPE, IDT_NET_TYPE, CFG_HMARGIN, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_NET1_TYPE, - CFG_COMBO_BOX_LEFT, 7, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, - CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT STR_PCAP, IDT_PCAP, - CFG_HMARGIN, 28, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT - COMBOBOX IDC_COMBO_PCAP1, - CFG_COMBO_BOX_LEFT, 26, CFG_COMBO_NOBTN_WIDTH, CFG_COMBO_HEIGHT, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + LTEXT STR_NET, IDT_NET, + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 2) + 20, CFG_VMARGIN, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT + + COMBOBOX IDC_COMBO_NET1_TYPE, + CFG_HMARGIN, 28, 32, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_PCAP1, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 28, 110, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT STR_NET, IDT_NET, - CFG_HMARGIN, 47, CFG_PANE_LTEXT_PRI_WIDTH, CFG_PANE_LTEXT_HEIGHT COMBOBOX IDC_COMBO_NET1, - CFG_COMBO_BOX_LEFT, 45, CFG_COMBO_BTN_WIDTH, CFG_COMBO_HEIGHT, + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 2) + 20, 28, 110, CFG_COMBO_HEIGHT, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET1, - CFG_COMBO_BTN_LEFT, 44, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 3) + 50, 27, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + COMBOBOX IDC_COMBO_NET2_TYPE, + CFG_HMARGIN, 49, 32, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_PCAP2, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 49, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_NET2, + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 2) + 20, 49, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET2, + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 3) + 50, 48, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + COMBOBOX IDC_COMBO_NET3_TYPE, + CFG_HMARGIN, 70, 32, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_PCAP3, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 70, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_NET3, + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 2) + 20, 70, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET3, + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 3) + 50, 69, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + + COMBOBOX IDC_COMBO_NET4_TYPE, + CFG_HMARGIN, 91, 32, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_PCAP4, + CFG_HMARGIN + CFG_PANE_LTEXT_PRI_WIDTH - 10, 91, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + + COMBOBOX IDC_COMBO_NET4, + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 2) + 20, 91, 110, CFG_COMBO_HEIGHT, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON STR_CONFIGURE, IDC_CONFIGURE_NET4, + CFG_HMARGIN + (CFG_PANE_LTEXT_PRI_WIDTH * 3) + 50, 90, CFG_BTN_WIDTH, CFG_BTN_HEIGHT + END DLG_CFG_PORTS DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 104ae0078..ceee9fa37 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -2037,16 +2037,12 @@ network_recalc_combos(HWND hdlg) { ignore_change = 1; -#if 0 for (uint8_t i = 0; i < NET_CARD_MAX; i++) { -#endif - settings_enable_window(hdlg, IDC_COMBO_PCAP1, temp_net_type[0] == NET_TYPE_PCAP); - settings_enable_window(hdlg, IDC_COMBO_NET1, - (temp_net_type[0] == NET_TYPE_SLIRP) || ((temp_net_type[0] == NET_TYPE_PCAP) && (network_dev_to_id(temp_pcap_dev[0]) > 0))); - settings_enable_window(hdlg, IDC_CONFIGURE_NET1, network_card_has_config(temp_net_card[0]) && ((temp_net_type[0] == NET_TYPE_SLIRP) || ((temp_net_type[0] == NET_TYPE_PCAP) && (network_dev_to_id(temp_pcap_dev[0]) > 0)))); -#if 0 + settings_enable_window(hdlg, IDC_COMBO_PCAP1 + i, temp_net_type[i] == NET_TYPE_PCAP); + settings_enable_window(hdlg, IDC_COMBO_NET1 + i, + (temp_net_type[i] == NET_TYPE_SLIRP) || ((temp_net_type[i] == NET_TYPE_PCAP) && (network_dev_to_id(temp_pcap_dev[i]) > 0))); + settings_enable_window(hdlg, IDC_CONFIGURE_NET1 + i, network_card_has_config(temp_net_card[i]) && ((temp_net_type[i] == NET_TYPE_SLIRP) || ((temp_net_type[i] == NET_TYPE_PCAP) && (network_dev_to_id(temp_pcap_dev[i]) > 0)))); } -#endif ignore_change = 0; } @@ -2065,73 +2061,80 @@ win_settings_network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_INITDIALOG: lptsTemp = (LPTSTR) malloc(512 * sizeof(WCHAR)); -#if 0 for (uint8_t i = 0; i < NET_CARD_MAX; i++) { -#endif - settings_add_string(hdlg, IDC_COMBO_NET1_TYPE, (LPARAM) L"None"); - settings_add_string(hdlg, IDC_COMBO_NET1_TYPE, (LPARAM) L"SLiRP"); - settings_add_string(hdlg, IDC_COMBO_NET1_TYPE, (LPARAM) L"PCap"); - settings_set_cur_sel(hdlg, IDC_COMBO_NET1_TYPE, temp_net_type[0]); - settings_enable_window(hdlg, IDC_COMBO_PCAP1, temp_net_type[0] == NET_TYPE_PCAP); + settings_add_string(hdlg, IDC_COMBO_NET1_TYPE + i, (LPARAM) L"None"); + settings_add_string(hdlg, IDC_COMBO_NET1_TYPE + i, (LPARAM) L"SLiRP"); + settings_add_string(hdlg, IDC_COMBO_NET1_TYPE + i, (LPARAM) L"PCap"); + settings_set_cur_sel(hdlg, IDC_COMBO_NET1_TYPE + i, temp_net_type[i]); + settings_enable_window(hdlg, IDC_COMBO_PCAP1 + i, temp_net_type[i] == NET_TYPE_PCAP); - for (c = 0; c < network_ndev; c++) { - mbstowcs(lptsTemp, network_devs[c].description, strlen(network_devs[c].description) + 1); - settings_add_string(hdlg, IDC_COMBO_PCAP1, (LPARAM) lptsTemp); - } - settings_set_cur_sel(hdlg, IDC_COMBO_PCAP1, network_dev_to_id(temp_pcap_dev[0])); + for (c = 0; c < network_ndev; c++) { + mbstowcs(lptsTemp, network_devs[c].description, strlen(network_devs[c].description) + 1); + settings_add_string(hdlg, IDC_COMBO_PCAP1 + i, (LPARAM) lptsTemp); + } + settings_set_cur_sel(hdlg, IDC_COMBO_PCAP1 + i, network_dev_to_id(temp_pcap_dev[i])); - /* NIC config */ - c = d = 0; - settings_reset_content(hdlg, IDC_COMBO_NET1); - while (1) { - generate_device_name(network_card_getdevice(c), network_card_get_internal_name(c), 1); + /* NIC config */ + c = d = 0; + settings_reset_content(hdlg, IDC_COMBO_NET1 + i); + while (1) { + generate_device_name(network_card_getdevice(c), network_card_get_internal_name(c), 1); - if (device_name[0] == L'\0') - break; + if (device_name[0] == L'\0') + break; - if (network_card_available(c) && device_is_valid(network_card_getdevice(c), temp_machine)) { - if (c == 0) - settings_add_string(hdlg, IDC_COMBO_NET1, win_get_string(IDS_2104)); - else - settings_add_string(hdlg, IDC_COMBO_NET1, (LPARAM) device_name); - settings_list_to_device[0][d] = c; - if ((c == 0) || (c == temp_net_card[0])) - settings_set_cur_sel(hdlg, IDC_COMBO_NET1, d); - d++; + if (network_card_available(c) && device_is_valid(network_card_getdevice(c), temp_machine)) { + if (c == 0) + settings_add_string(hdlg, IDC_COMBO_NET1 + i, win_get_string(IDS_2104)); + else + settings_add_string(hdlg, IDC_COMBO_NET1 + i, (LPARAM) device_name); + settings_list_to_device[0][d] = c; + if ((c == 0) || (c == temp_net_card[i])) + settings_set_cur_sel(hdlg, IDC_COMBO_NET1 + i, d); + d++; + } + + c++; } - c++; + settings_enable_window(hdlg, IDC_COMBO_NET1 + i, d); + network_recalc_combos(hdlg); } - - settings_enable_window(hdlg, IDC_COMBO_NET1, d); - network_recalc_combos(hdlg); free(lptsTemp); -#if 0 - } -#endif return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_COMBO_NET1_TYPE: -#if 0 - case IDC_COMBO_NET2_TYPE: - case IDC_COMBO_NET3_TYPE: - case IDC_COMBO_NET4_TYPE: -#endif if (ignore_change) return FALSE; temp_net_type[0] = settings_get_cur_sel(hdlg, IDC_COMBO_NET1_TYPE); network_recalc_combos(hdlg); break; + case IDC_COMBO_NET2_TYPE: + if (ignore_change) + return FALSE; + + temp_net_type[1] = settings_get_cur_sel(hdlg, IDC_COMBO_NET2_TYPE); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET3_TYPE: + if (ignore_change) + return FALSE; + + temp_net_type[2] = settings_get_cur_sel(hdlg, IDC_COMBO_NET3_TYPE); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET4_TYPE: + if (ignore_change) + return FALSE; + + temp_net_type[3] = settings_get_cur_sel(hdlg, IDC_COMBO_NET4_TYPE); + network_recalc_combos(hdlg); + break; case IDC_COMBO_PCAP1: -#if 0 - case IDC_COMBO_PCAP2: - case IDC_COMBO_PCAP3: - case IDC_COMBO_PCAP4: -#endif if (ignore_change) return FALSE; @@ -2139,46 +2142,98 @@ win_settings_network_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) strcpy(temp_pcap_dev[0], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP1)].device); network_recalc_combos(hdlg); break; + case IDC_COMBO_PCAP2: + if (ignore_change) + return FALSE; + + memset(temp_pcap_dev[1], '\0', sizeof(temp_pcap_dev[1])); + strcpy(temp_pcap_dev[1], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP2)].device); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_PCAP3: + if (ignore_change) + return FALSE; + + memset(temp_pcap_dev[2], '\0', sizeof(temp_pcap_dev[2])); + strcpy(temp_pcap_dev[2], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP3)].device); + network_recalc_combos(hdlg); + break; + case IDC_COMBO_PCAP4: + if (ignore_change) + return FALSE; + + memset(temp_pcap_dev[3], '\0', sizeof(temp_pcap_dev[3])); + strcpy(temp_pcap_dev[3], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP4)].device); + network_recalc_combos(hdlg); + break; case IDC_COMBO_NET1: -#if 0 - case IDC_COMBO_NET2: - case IDC_COMBO_NET3: - case IDC_COMBO_NET4: -#endif if (ignore_change) return FALSE; temp_net_card[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET1)]; network_recalc_combos(hdlg); break; + case IDC_COMBO_NET2: + if (ignore_change) + return FALSE; + + temp_net_card[1] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET2)]; + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET3: + if (ignore_change) + return FALSE; + + temp_net_card[2] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET3)]; + network_recalc_combos(hdlg); + break; + case IDC_COMBO_NET4: + if (ignore_change) + return FALSE; + + temp_net_card[3] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET4)]; + network_recalc_combos(hdlg); + break; case IDC_CONFIGURE_NET1: -#if 0 - case IDC_CONFIGURE_NET2: - case IDC_CONFIGURE_NET3: - case IDC_CONFIGURE_NET4: -#endif if (ignore_change) return FALSE; temp_net_card[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET1)]; temp_deviceconfig |= deviceconfig_open(hdlg, (void *) network_card_getdevice(temp_net_card[0])); break; + case IDC_CONFIGURE_NET2: + if (ignore_change) + return FALSE; + + temp_net_card[1] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET2)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) network_card_getdevice(temp_net_card[1])); + break; + case IDC_CONFIGURE_NET3: + if (ignore_change) + return FALSE; + + temp_net_card[2] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET3)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) network_card_getdevice(temp_net_card[2])); + break; + case IDC_CONFIGURE_NET4: + if (ignore_change) + return FALSE; + + temp_net_card[3] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET4)]; + temp_deviceconfig |= deviceconfig_open(hdlg, (void *) network_card_getdevice(temp_net_card[3])); + break; } return FALSE; case WM_SAVESETTINGS: -#if 0 for (uint8_t i = 0; i < NET_CARD_MAX; i++) { -#endif - temp_net_type[0] = settings_get_cur_sel(hdlg, IDC_COMBO_NET1_TYPE); - memset(temp_pcap_dev[0], '\0', sizeof(temp_pcap_dev[0])); - strcpy(temp_pcap_dev[0], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP1)].device); - temp_net_card[0] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET1)]; -#if 0 + temp_net_type[i] = settings_get_cur_sel(hdlg, IDC_COMBO_NET1_TYPE + i); + memset(temp_pcap_dev[i], '\0', sizeof(temp_pcap_dev[i])); + strcpy(temp_pcap_dev[i], network_devs[settings_get_cur_sel(hdlg, IDC_COMBO_PCAP1 + i)].device); + temp_net_card[i] = settings_list_to_device[0][settings_get_cur_sel(hdlg, IDC_COMBO_NET1 + i)]; } -#endif default: return FALSE; } From 6a20e17ee9df0d12746b37f93584395a72ee7b74 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Wed, 3 May 2023 16:14:15 +0600 Subject: [PATCH 02/34] usb: Add infrastructure for interrupt descriptor polling --- src/include/86box/usb.h | 2 ++ src/usb.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index a20f1b2a2..53787158e 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -40,7 +40,9 @@ typedef struct usb_t uint32_t ohci_mem_base; mem_mapping_t ohci_mmio_mapping; pc_timer_t ohci_frame_timer; + pc_timer_t ohci_interrupt_desc_poll_timer; pc_timer_t ohci_port_reset_timer[2]; + uint8_t ohci_interrupt_counter : 5; usb_params_t* usb_params; } usb_t; diff --git a/src/usb.c b/src/usb.c index 8ac16edd1..7dd8341c3 100644 --- a/src/usb.c +++ b/src/usb.c @@ -195,6 +195,17 @@ ohci_update_frame_counter(void* priv) usb_t *dev = (usb_t *) priv; } +void +ohci_poll_interrupt_descriptors(void* priv) +{ + usb_t *dev = (usb_t *) priv; + + /* TODO: Actually poll the interrupt descriptors. */ + + dev->ohci_interrupt_counter++; + timer_on_auto(&dev->ohci_interrupt_desc_poll_timer, 1000.); +} + void ohci_port_reset_callback(void* priv) { @@ -470,6 +481,7 @@ usb_init_ext(const device_t *info, void* params) timer_add(&dev->ohci_frame_timer, ohci_update_frame_counter, dev, 0); /* Unused for now, to be used for frame counting. */ timer_add(&dev->ohci_port_reset_timer[0], ohci_port_reset_callback, dev, 0); timer_add(&dev->ohci_port_reset_timer[1], ohci_port_reset_callback_2, dev, 0); + timer_add(&dev->ohci_interrupt_desc_poll_timer, ohci_poll_interrupt_descriptors, dev, 0); usb_reset(dev); return dev; From 0554b8c7850c0e4326aed5ebebbd16997c3bfac3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 4 May 2023 02:20:50 +0200 Subject: [PATCH 03/34] Explicitly reset the latches to disabled before attempting to enable them, fixes the latches failing to enable after a hard reset. --- src/pic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pic.c b/src/pic.c index 62ceabd5d..e078cb94a 100644 --- a/src/pic.c +++ b/src/pic.c @@ -570,6 +570,9 @@ pic_reset_hard(void) { pic_reset(); + /* Explicitly reset the latches. */ + kbd_latch = mouse_latch = 0; + /* The situation is as follows: There is a giant mess when it comes to these latches on real hardware, to the point that there's even boards with board-level latched that get used in place of the latches on the chipset, therefore, I'm just doing this here for the sake of simplicity. */ From 5c0292ae41cc1f3a2021d8f0b85822b92d39d163 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 4 May 2023 02:35:46 -0400 Subject: [PATCH 04/34] Disable old early CDROM support --- src/include/86box/cdrom.h | 2 +- src/include/86box/resource.h | 2 +- src/win/languages/dialogs.rc | 2 ++ src/win/win_settings.c | 11 +++++++++-- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/include/86box/cdrom.h b/src/include/86box/cdrom.h index d2f032280..a32177b05 100644 --- a/src/include/86box/cdrom.h +++ b/src/include/86box/cdrom.h @@ -165,7 +165,7 @@ typedef struct cdrom { char *image_history[CD_IMAGE_HISTORY]; uint32_t sound_on, cdrom_capacity, - early, seek_pos, + seek_pos, seek_diff, cd_end, type; int host_drive, prev_host_drive, diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index 431f42134..c0867efef 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -302,7 +302,7 @@ #define IDC_COMBO_CD_ID 1157 #define IDC_COMBO_CD_LUN 1158 #define IDC_COMBO_CD_CHANNEL_IDE 1159 -#define IDC_CHECKEARLY 1160 +//#define IDC_CHECKEARLY 1160 #define IDC_LIST_ZIP_DRIVES 1170 /* other removable devices config */ #define IDC_COMBO_ZIP_BUS 1171 diff --git a/src/win/languages/dialogs.rc b/src/win/languages/dialogs.rc index 83d81e074..cd62722cd 100644 --- a/src/win/languages/dialogs.rc +++ b/src/win/languages/dialogs.rc @@ -834,9 +834,11 @@ BEGIN 33, 205, 140, 12, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +/* CONTROL STR_EARLY, IDC_CHECKEARLY, "Button", BS_AUTOCHECKBOX | WS_TABSTOP, 186, 206, 84, CFG_CHECKBOX_HEIGHT +*/ END DLG_CFG_OTHER_REMOVABLE_DEVICES DIALOG DISCARDABLE CFG_PANE_LEFT, CFG_PANE_TOP, CFG_PANE_WIDTH, CFG_PANE_HEIGHT diff --git a/src/win/win_settings.c b/src/win/win_settings.c index ceee9fa37..bc6218a81 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -4014,6 +4014,7 @@ win_settings_cdrom_drives_recalc_list(HWND hdlg) if (ListView_SetItem(hwndList, &lvI) == -1) return FALSE; +/* lvI.iSubItem = 2; lvI.pszText = plat_get_string(temp_cdrom[i].early ? IDS_2060 : IDS_2061); lvI.iItem = i; @@ -4021,6 +4022,7 @@ win_settings_cdrom_drives_recalc_list(HWND hdlg) if (ListView_SetItem(hwndList, &lvI) == -1) return FALSE; +*/ } return TRUE; @@ -4489,6 +4491,7 @@ win_settings_cdrom_drives_update_item(HWND hdlg, int i) if (ListView_SetItem(hwndList, &lvI) == -1) return; +/* lvI.iSubItem = 2; lvI.pszText = plat_get_string(temp_cdrom[i].early ? IDS_2060 : IDS_2061); lvI.iItem = i; @@ -4496,6 +4499,7 @@ win_settings_cdrom_drives_update_item(HWND hdlg, int i) if (ListView_SetItem(hwndList, &lvI) == -1) return; +*/ } static void @@ -4647,11 +4651,12 @@ cdrom_recalc_location_controls(HWND hdlg, int assign_id) settings_show_window(hdlg, IDC_COMBO_CD_CHANNEL_IDE, FALSE); settings_show_window(hdlg, IDC_COMBO_CD_SPEED, bus != CDROM_BUS_DISABLED); settings_show_window(hdlg, IDT_CD_SPEED, bus != CDROM_BUS_DISABLED); +/* settings_show_window(hdlg, IDC_CHECKEARLY, bus != CDROM_BUS_DISABLED); - +*/ if (bus != CDROM_BUS_DISABLED) { settings_set_cur_sel(hdlg, IDC_COMBO_CD_SPEED, temp_cdrom[lv2_current_sel].speed - 1); - settings_set_check(hdlg, IDC_CHECKEARLY, temp_cdrom[lv2_current_sel].early); +// settings_set_check(hdlg, IDC_CHECKEARLY, temp_cdrom[lv2_current_sel].early); } switch (bus) { @@ -5042,10 +5047,12 @@ win_settings_floppy_and_cdrom_drives_proc(HWND hdlg, UINT message, WPARAM wParam win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); break; +/* case IDC_CHECKEARLY: temp_cdrom[lv2_current_sel].early = settings_get_check(hdlg, IDC_CHECKEARLY); win_settings_cdrom_drives_update_item(hdlg, lv2_current_sel); break; +*/ } ignore_change = 0; From 1c3e1b4602a5b71fed797cf69e0526b12c383e79 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Thu, 4 May 2023 02:53:49 -0400 Subject: [PATCH 05/34] Correct win32 ui for cdrom model headings --- src/include/86box/resource.h | 33 +++++++++++++++++---------------- src/win/languages/cs-CZ.rc | 3 +-- src/win/languages/de-DE.rc | 3 +-- src/win/languages/dialogs.rc | 9 +++++---- src/win/languages/en-GB.rc | 3 +-- src/win/languages/en-US.rc | 3 +-- src/win/languages/es-ES.rc | 3 +-- src/win/languages/fi-FI.rc | 3 +-- src/win/languages/fr-FR.rc | 3 +-- src/win/languages/hr-HR.rc | 3 +-- src/win/languages/hu-HU.rc | 3 +-- src/win/languages/it-IT.rc | 3 +-- src/win/languages/ja-JP.rc | 3 +-- src/win/languages/ko-KR.rc | 3 +-- src/win/languages/pl-PL.rc | 3 +-- src/win/languages/pt-BR.rc | 3 +-- src/win/languages/pt-PT.rc | 3 +-- src/win/languages/ru-RU.rc | 3 +-- src/win/languages/sl-SI.rc | 3 +-- src/win/languages/tr-TR.rc | 3 +-- src/win/languages/uk-UA.rc | 3 +-- src/win/languages/zh-CN.rc | 3 +-- src/win/languages/zh-TW.rc | 3 +-- src/win/win_settings.c | 2 +- 24 files changed, 44 insertions(+), 63 deletions(-) diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index c0867efef..3a8a6b39c 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -142,26 +142,27 @@ #define IDT_CD_LUN 1766 /* LUN: */ #define IDT_CD_CHANNEL 1767 /* Channel: */ #define IDT_CD_SPEED 1768 /* Speed: */ +#define IDT_CD_TYPE 1769 /* Type: */ /* DLG_CFG_OTHER_REMOVABLE_DEVICES */ -#define IDT_MO_DRIVES 1769 /* MO drives: */ -#define IDT_MO_BUS 1770 /* Bus: */ -#define IDT_MO_ID 1771 /* ID: */ -#define IDT_MO_CHANNEL 1772 /* Channel */ -#define IDT_MO_TYPE 1773 /* Type: */ +#define IDT_MO_DRIVES 1770 /* MO drives: */ +#define IDT_MO_BUS 1771 /* Bus: */ +#define IDT_MO_ID 1772 /* ID: */ +#define IDT_MO_CHANNEL 1773 /* Channel */ +#define IDT_MO_TYPE 1774 /* Type: */ -#define IDT_ZIP_DRIVES 1774 /* ZIP drives: */ -#define IDT_ZIP_BUS 1775 /* Bus: */ -#define IDT_ZIP_ID 1776 /* ID: */ -#define IDT_ZIP_LUN 1777 /* LUN: */ -#define IDT_ZIP_CHANNEL 1778 /* Channel: */ +#define IDT_ZIP_DRIVES 1775 /* ZIP drives: */ +#define IDT_ZIP_BUS 1776 /* Bus: */ +#define IDT_ZIP_ID 1777 /* ID: */ +#define IDT_ZIP_LUN 1778 /* LUN: */ +#define IDT_ZIP_CHANNEL 1779 /* Channel: */ /* DLG_CFG_PERIPHERALS */ -#define IDT_ISARTC 1779 /* ISA RTC: */ -#define IDT_ISAMEM_1 1780 /* ISAMEM Board #1: */ -#define IDT_ISAMEM_2 1781 /* ISAMEM Board #2: */ -#define IDT_ISAMEM_3 1782 /* ISAMEM Board #3: */ -#define IDT_ISAMEM_4 1783 /* ISAMEM Board #4: */ +#define IDT_ISARTC 1780 /* ISA RTC: */ +#define IDT_ISAMEM_1 1781 /* ISAMEM Board #1: */ +#define IDT_ISAMEM_2 1782 /* ISAMEM Board #2: */ +#define IDT_ISAMEM_3 1783 /* ISAMEM Board #3: */ +#define IDT_ISAMEM_4 1784 /* ISAMEM Board #4: */ /* * To try to keep these organized, we now group the @@ -302,7 +303,7 @@ #define IDC_COMBO_CD_ID 1157 #define IDC_COMBO_CD_LUN 1158 #define IDC_COMBO_CD_CHANNEL_IDE 1159 -//#define IDC_CHECKEARLY 1160 +#define IDC_COMBO_CD_TYPE 1160 #define IDC_LIST_ZIP_DRIVES 1170 /* other removable devices config */ #define IDC_COMBO_ZIP_BUS 1171 diff --git a/src/win/languages/cs-CZ.rc b/src/win/languages/cs-CZ.rc index 262f059b0..238d31b07 100644 --- a/src/win/languages/cs-CZ.rc +++ b/src/win/languages/cs-CZ.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Kontrola BPB" #define STR_CDROM_DRIVES "Mechaniky CD-ROM:" #define STR_CD_SPEED "Rychlost:" -#define STR_EARLY "Časná mechanika" #define STR_MO_DRIVES "Magnetooptické mechaniky:" #define STR_ZIP_DRIVES "Mechaniky ZIP:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Resetovat" IDS_2160 "Vypnout skrze rozhraní ACPI" IDS_2161 "Nastavení" - IDS_2162 "Časná mechanika" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/de-DE.rc b/src/win/languages/de-DE.rc index b2e25e332..0af4a28b5 100644 --- a/src/win/languages/de-DE.rc +++ b/src/win/languages/de-DE.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "BPB überprüfen" #define STR_CDROM_DRIVES "CD-ROM-Laufwerke:" #define STR_CD_SPEED "Geschwindigkeit:" -#define STR_EARLY "Früheres Laufwerk" #define STR_MO_DRIVES "MO-Laufwerke:" #define STR_ZIP_DRIVES "ZIP-Laufwerke:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Hard-Reset" IDS_2160 "ACPI-basiertes Herunterfahren" IDS_2161 "Optionen" - IDS_2162 "Früheres Laufwerk" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/dialogs.rc b/src/win/languages/dialogs.rc index cd62722cd..3286ee2be 100644 --- a/src/win/languages/dialogs.rc +++ b/src/win/languages/dialogs.rc @@ -833,11 +833,12 @@ BEGIN COMBOBOX IDC_COMBO_CD_SPEED, 33, 205, 140, 12, CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - /* - CONTROL STR_EARLY, IDC_CHECKEARLY, - "Button", BS_AUTOCHECKBOX | WS_TABSTOP, - 186, 206, 84, CFG_CHECKBOX_HEIGHT + LTEXT STR_TYPE, IDT_CD_TYPE, + CFG_HMARGIN, 233, 34, CFG_PANE_LTEXT_HEIGHT + COMBOBOX IDC_COMBO_CD_SPEED, + 33, 231, 140, 12, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP */ END diff --git a/src/win/languages/en-GB.rc b/src/win/languages/en-GB.rc index a0ed1487e..f8dab3bd7 100644 --- a/src/win/languages/en-GB.rc +++ b/src/win/languages/en-GB.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Check BPB" #define STR_CDROM_DRIVES "CD-ROM drives:" #define STR_CD_SPEED "Speed:" -#define STR_EARLY "Earlier drive" #define STR_MO_DRIVES "MO drives:" #define STR_ZIP_DRIVES "ZIP drives:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Hard reset" IDS_2160 "ACPI shutdown" IDS_2161 "Settings" - IDS_2162 "Earlier drive" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/en-US.rc b/src/win/languages/en-US.rc index 9464c6d6b..66c9d60e2 100644 --- a/src/win/languages/en-US.rc +++ b/src/win/languages/en-US.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Check BPB" #define STR_CDROM_DRIVES "CD-ROM drives:" #define STR_CD_SPEED "Speed:" -#define STR_EARLY "Earlier drive" #define STR_MO_DRIVES "MO drives:" #define STR_ZIP_DRIVES "ZIP drives:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Hard reset" IDS_2160 "ACPI shutdown" IDS_2161 "Settings" - IDS_2162 "Earlier drive" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/es-ES.rc b/src/win/languages/es-ES.rc index 5f138c3c2..8ff91d891 100644 --- a/src/win/languages/es-ES.rc +++ b/src/win/languages/es-ES.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Chequear BPB" #define STR_CDROM_DRIVES "Unidades de CD-ROM:" #define STR_CD_SPEED "Velocidad:" -#define STR_EARLY "Unidad anterior" #define STR_MO_DRIVES "Unidades MO:" #define STR_ZIP_DRIVES "Unidades ZIP:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Hard reset" IDS_2160 "ACPI shutdown" IDS_2161 "Settings" - IDS_2162 "Unidad anterior" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/fi-FI.rc b/src/win/languages/fi-FI.rc index c32f94b41..31467afbf 100644 --- a/src/win/languages/fi-FI.rc +++ b/src/win/languages/fi-FI.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Tarkista BPB" #define STR_CDROM_DRIVES "CD-ROM-asemat:" #define STR_CD_SPEED "Nopeus:" -#define STR_EARLY "Aiemmat asemat" #define STR_MO_DRIVES "Magneettisoptiset asemat (MO):" #define STR_ZIP_DRIVES "ZIP-asemat:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Kylmä uudelleenkäynnistys" IDS_2160 "ACPI-sammutus" IDS_2161 "Asetukset" - IDS_2162 "Aiemmat asemat" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/fr-FR.rc b/src/win/languages/fr-FR.rc index bffedce44..73e36550d 100644 --- a/src/win/languages/fr-FR.rc +++ b/src/win/languages/fr-FR.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Vérifier BPB" #define STR_CDROM_DRIVES "Lecterus CD-ROM:" #define STR_CD_SPEED "Vitesse:" -#define STR_EARLY "Lecteur plus tôt" #define STR_MO_DRIVES "Lecteurs magnéto-optiques:" #define STR_ZIP_DRIVES "Lecteurs ZIP:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Hard reset" IDS_2160 "ACPI shutdown" IDS_2161 "Settings" - IDS_2162 "Lecteur plus tôt" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/hr-HR.rc b/src/win/languages/hr-HR.rc index b79defcbe..74e43ebb6 100644 --- a/src/win/languages/hr-HR.rc +++ b/src/win/languages/hr-HR.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Provjeraj BPB" #define STR_CDROM_DRIVES "CD-ROM pogoni:" #define STR_CD_SPEED "Brzina:" -#define STR_EARLY "Raniji pogon" #define STR_MO_DRIVES "MO pogoni:" #define STR_ZIP_DRIVES "ZIP pogoni:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Ponovno pokretanje" IDS_2160 "ACPI bazirano gašenje" IDS_2161 "Postavke" - IDS_2162 "Raniji pogon" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/hu-HU.rc b/src/win/languages/hu-HU.rc index 9486d8e61..bcebd91f0 100644 --- a/src/win/languages/hu-HU.rc +++ b/src/win/languages/hu-HU.rc @@ -373,7 +373,6 @@ END #define STR_CHECKBPB "BPB ellenőrzés" #define STR_CDROM_DRIVES "CD-ROM meghajtók:" #define STR_CD_SPEED "Seb.:" -#define STR_EARLY "Korábbi meghajtó" #define STR_MO_DRIVES "MO-meghajtók:" #define STR_ZIP_DRIVES "ZIP-meghajtók:" @@ -542,7 +541,7 @@ BEGIN IDS_2159 "Hard reset" IDS_2160 "ACPI shutdown" IDS_2161 "Settings" - IDS_2162 "Korábbi meghajtó" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/it-IT.rc b/src/win/languages/it-IT.rc index 02ca9bf9f..e81e07a6e 100644 --- a/src/win/languages/it-IT.rc +++ b/src/win/languages/it-IT.rc @@ -369,7 +369,6 @@ END #define STR_CHECKBPB "Verifica BPB" #define STR_CDROM_DRIVES "Unità CD-ROM:" #define STR_CD_SPEED "Veloc.:" -#define STR_EARLY "Unità anteriore" #define STR_MO_DRIVES "Unità magneto-ottiche:" #define STR_ZIP_DRIVES "Unità ZIP:" @@ -539,7 +538,7 @@ BEGIN IDS_2159 "Hard reset" IDS_2160 "ACPI shutdown" IDS_2161 "Settings" - IDS_2162 "Unità anteriore" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/ja-JP.rc b/src/win/languages/ja-JP.rc index 89cc42011..0b9efec12 100644 --- a/src/win/languages/ja-JP.rc +++ b/src/win/languages/ja-JP.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "BPBをチェック" #define STR_CDROM_DRIVES "CD-ROMドライブ:" #define STR_CD_SPEED "速度:" -#define STR_EARLY "アーリードライブ" #define STR_MO_DRIVES "光磁気ドライブ:" #define STR_ZIP_DRIVES "ZIPドライブ:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "ハードリセット" IDS_2160 "ACPIシャットダウン" IDS_2161 "設定" - IDS_2162 "アーリードライブ" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/ko-KR.rc b/src/win/languages/ko-KR.rc index cbe3e4752..1949eb6c9 100644 --- a/src/win/languages/ko-KR.rc +++ b/src/win/languages/ko-KR.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "BPB 확인" #define STR_CDROM_DRIVES "CD-ROM 드라이브:" #define STR_CD_SPEED "속도:" -#define STR_EARLY "이전 드라이브" #define STR_MO_DRIVES "광자기 드라이브:" #define STR_ZIP_DRIVES "ZIP 드라이브:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "재시작" IDS_2160 "ACPI 종료" IDS_2161 "설정" - IDS_2162 "이전 드라이브" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/pl-PL.rc b/src/win/languages/pl-PL.rc index 84fccb70d..98dc0c903 100644 --- a/src/win/languages/pl-PL.rc +++ b/src/win/languages/pl-PL.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Sprawdzaj BPB" #define STR_CDROM_DRIVES "Napędy CD-ROM:" #define STR_CD_SPEED "Szybkość:" -#define STR_EARLY "Wcześniejszy napęd" #define STR_MO_DRIVES "Napędy MO:" #define STR_ZIP_DRIVES "Napędy ZIP:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Twardy reset" IDS_2160 "Wyłączenie ACPI" IDS_2161 "Ustawienia" - IDS_2162 "Wcześniejszy napęd" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/pt-BR.rc b/src/win/languages/pt-BR.rc index b01a214ff..723e25685 100644 --- a/src/win/languages/pt-BR.rc +++ b/src/win/languages/pt-BR.rc @@ -371,7 +371,6 @@ END #define STR_CHECKBPB "Verificar BPB" #define STR_CDROM_DRIVES "Unidades de CD-ROM:" #define STR_CD_SPEED "Veloc.:" -#define STR_EARLY "Unidade anterior" #define STR_MO_DRIVES "Unidades magneto-ópticas:" #define STR_ZIP_DRIVES "Unidades ZIP:" @@ -541,7 +540,7 @@ BEGIN IDS_2159 "Reinicialização completa" IDS_2160 "Desligamento por ACPI" IDS_2161 "Configurações" - IDS_2162 "Unidade anterior" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/pt-PT.rc b/src/win/languages/pt-PT.rc index 6390453dd..b6a66a325 100644 --- a/src/win/languages/pt-PT.rc +++ b/src/win/languages/pt-PT.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Verificar BPB" #define STR_CDROM_DRIVES "Unidades CD-ROM:" #define STR_CD_SPEED "Velocidade:" -#define STR_EARLY "Unidade anterior" #define STR_MO_DRIVES "Unidades magneto-ópticas:" #define STR_ZIP_DRIVES "Unidades ZIP:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Reinicialização completa" IDS_2160 "Encerramento ACPI" IDS_2161 "Definições" - IDS_2162 "Unidade anterior" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/ru-RU.rc b/src/win/languages/ru-RU.rc index f49247894..552f8a0dc 100644 --- a/src/win/languages/ru-RU.rc +++ b/src/win/languages/ru-RU.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Проверять BPB" #define STR_CDROM_DRIVES "Дисководы CD-ROM:" #define STR_CD_SPEED "Скорость:" -#define STR_EARLY "Предыдущий дисковод" #define STR_MO_DRIVES "Магнитооптические дисководы:" #define STR_ZIP_DRIVES "ZIP дисководы:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Холодная перезагрузка" IDS_2160 "Сигнал завершения ACPI" IDS_2161 "Настройки машины" - IDS_2162 "Предыдущий дисковод" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/sl-SI.rc b/src/win/languages/sl-SI.rc index beeb9183b..ec080d7cb 100644 --- a/src/win/languages/sl-SI.rc +++ b/src/win/languages/sl-SI.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Preverjaj BPB" #define STR_CDROM_DRIVES "Pogoni CD-ROM:" #define STR_CD_SPEED "Hitrost:" -#define STR_EARLY "Zgodnejši pogon" #define STR_MO_DRIVES "Magnetno-optični pogoni:" #define STR_ZIP_DRIVES "Pogoni ZIP:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Ponovni zagon" IDS_2160 "Zaustavitev ACPI" IDS_2161 "Nastavitve" - IDS_2162 "Zgodnejši pogon" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/tr-TR.rc b/src/win/languages/tr-TR.rc index 04e00eb0d..cd6132ee0 100644 --- a/src/win/languages/tr-TR.rc +++ b/src/win/languages/tr-TR.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "BPB'yi denetle" #define STR_CDROM_DRIVES "CD-ROM sürücüleri:" #define STR_CD_SPEED "Hız:" -#define STR_EARLY "Daha erken sürüş" #define STR_MO_DRIVES "MO sürücüleri:" #define STR_ZIP_DRIVES "ZIP sürücüleri:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Makineyi yeniden başlat" IDS_2160 "ACPI kapatma" IDS_2161 "Ayarlar" - IDS_2162 "Daha erken sürüş" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/uk-UA.rc b/src/win/languages/uk-UA.rc index fc3b29c84..adc04e808 100644 --- a/src/win/languages/uk-UA.rc +++ b/src/win/languages/uk-UA.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "Перевіряти BPB" #define STR_CDROM_DRIVES "Дисководи CD-ROM:" #define STR_CD_SPEED "Швидкість:" -#define STR_EARLY "Більш ранній дисковод" #define STR_MO_DRIVES "Магнітооптичні дисководи:" #define STR_ZIP_DRIVES "ZIP дисководи:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "Холодне перезавантаження" IDS_2160 "Сигнал завершення ACPI" IDS_2161 "Налаштування машини" - IDS_2162 "Більш ранній дисковод" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/zh-CN.rc b/src/win/languages/zh-CN.rc index 40ed20210..cd47d64df 100644 --- a/src/win/languages/zh-CN.rc +++ b/src/win/languages/zh-CN.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "检查 BPB" #define STR_CDROM_DRIVES "光盘驱动器:" #define STR_CD_SPEED "速度:" -#define STR_EARLY "早先的驱动器" #define STR_MO_DRIVES "磁光盘驱动器:" #define STR_ZIP_DRIVES "ZIP 驱动器:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "硬重置" IDS_2160 "ACPI 关机" IDS_2161 "设置" - IDS_2162 "早先的驱动器" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/languages/zh-TW.rc b/src/win/languages/zh-TW.rc index d6922164b..8ed160f21 100644 --- a/src/win/languages/zh-TW.rc +++ b/src/win/languages/zh-TW.rc @@ -368,7 +368,6 @@ END #define STR_CHECKBPB "檢查 BPB" #define STR_CDROM_DRIVES "光碟機:" #define STR_CD_SPEED "速度:" -#define STR_EARLY "早先的光碟機" #define STR_MO_DRIVES "磁光碟機:" #define STR_ZIP_DRIVES "ZIP 磁碟機:" @@ -538,7 +537,7 @@ BEGIN IDS_2159 "硬重設" IDS_2160 "ACPI 關機" IDS_2161 "設定" - IDS_2162 "早先的光碟機" + IDS_2162 "Type" IDS_2163 "No Dynarec" IDS_2164 "Old Dynarec" IDS_2165 "New Dynarec" diff --git a/src/win/win_settings.c b/src/win/win_settings.c index bc6218a81..333888a65 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -4263,7 +4263,7 @@ win_settings_cdrom_drives_init_columns(HWND hdlg) if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) return FALSE; - /* Earlier drive */ + /* Type */ lvc.iSubItem = 2; lvc.pszText = plat_get_string(IDS_2162); From 6376980d9dc581ddfbec50781daa7c89005991f7 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Thu, 4 May 2023 16:25:46 +0600 Subject: [PATCH 06/34] usb: More USB endpoint device infrastructure work --- src/include/86box/usb.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index 53787158e..cf5938a3d 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -47,11 +47,29 @@ typedef struct usb_t usb_params_t* usb_params; } usb_t; +#pragma pack(push, 1) +/* Base USB descriptor struct. */ +typedef struct +{ + uint8_t bLength; + uint8_t bDescriptorType; +} usb_desc_base_t; +#pragma pack(pop) + /* USB endpoint device struct. Incomplete and unused. */ typedef struct { uint16_t vendor_id; uint16_t device_id; + + /* Reads from endpoint. Non-zero value indicates error. */ + uint8_t (*device_in)(void* priv, uint8_t* data, uint32_t len); + /* Writes to endpoint. Non-zero value indicates error. */ + uint8_t (*device_out)(void* priv, uint8_t* data, uint32_t len); + /* Process setup packets. */ + uint8_t (*device_setup)(void* priv, uint8_t* data); + + void* priv; } usb_device_t; /* Global variables. */ From 3f461afeeb25194c359a6ba764f1966d0bbd0662 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 May 2023 00:28:08 +0600 Subject: [PATCH 07/34] usb: start hooking up USB interrupts to chipsets --- src/chipset/sis_5571.c | 37 ++++++++++++++++++++++++++++++++++++- src/include/86box/usb.h | 2 ++ src/usb.c | 3 +++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index 0f77a1a07..aa8ea62f3 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -83,6 +83,8 @@ typedef struct sis_5571_t { smram_t *smram; usb_t *usb; + usb_params_t usb_params; + } sis_5571_t; static void @@ -638,6 +640,36 @@ pci_isa_bridge_read(int func, int addr, void *priv) } } +static void +sis_5571_usb_raise_interrupt(usb_t* usb, void* priv) +{ + sis_5571_t *dev = (sis_5571_t *) priv; + + if (dev->pci_conf_sb[0][0x68] & 0x80) { + /* TODO: Is the normal PCI interrupt inhibited when USB IRQ remapping is enabled? */ + switch (dev->pci_conf_sb[0][0x68] & 0x0F) { + case 0x00: + case 0x01: + case 0x02: + case 0x08: + case 0x0d: + break; + default: + picint(1 << dev->pci_conf_sb[0][0x68] & 0x0F); + break; + } + } else { + pci_set_irq(dev->sb_pci_slot, PCI_INTA); + } +} + +static uint8_t +sis_5571_usb_handle_smi(usb_t* usb, void* priv) +{ + /* Left unimplemented for now. */ + return 1; +} + static void sis_5571_reset(void *priv) { @@ -722,7 +754,10 @@ sis_5571_init(const device_t *info) dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2); /* USB */ - dev->usb = device_add(&usb_device); + dev->usb_params.parent_priv = dev; + dev->usb_params.raise_interrupt = sis_5571_usb_raise_interrupt; + dev->usb_params.smi_handle = sis_5571_usb_handle_smi; + dev->usb = device_add_parameters(&usb_device, &dev->usb_params); sis_5571_reset(dev); diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index cf5938a3d..7860ada3b 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -28,6 +28,8 @@ typedef struct usb_t usb_t; typedef struct { void (*raise_interrupt)(usb_t*, void*); + /* Handle (but do not raise) SMI. Returns 1 if SMI can be raised, 0 otherwise. */ + uint8_t (*smi_handle)(usb_t*, void*); void* parent_priv; } usb_params_t; diff --git a/src/usb.c b/src/usb.c index 7dd8341c3..03fe8a9a6 100644 --- a/src/usb.c +++ b/src/usb.c @@ -80,6 +80,9 @@ static void usb_interrupt_ohci(usb_t* usb) { if (usb->ohci_mmio[OHCI_HcControl + 1] & 1) { + if (usb->usb_params && usb->usb_params->smi_handle && !usb->usb_params->smi_handle(usb, usb->usb_params->parent_priv)) + return; + smi_raise(); } else if (usb->usb_params != NULL) { From 52b0e54fd71f611af2a2a442375f9b933dbcddcf Mon Sep 17 00:00:00 2001 From: Jordi Guillaumes i Pons Date: Thu, 4 May 2023 21:12:02 +0200 Subject: [PATCH 08/34] VDE networking support Adds VDE (https://github.com/virtualsquare/vde-2) support to 86Box. - Adds new networking type - Modifies networking configuration dialog - Adds CMake Presets to build and debug under MacOS --- .gitignore | 3 + CMakePresets.json | 66 +++++++ src/config.c | 52 ++++-- src/include/86box/network.h | 18 +- src/network/CMakeLists.txt | 14 +- src/network/net_vde.c | 310 +++++++++++++++++++++++++++++++ src/network/network.c | 35 +++- src/qt/qt_settingsnetwork.cpp | 46 +++-- src/qt/qt_settingsnetwork.ui | 338 +++++++++++++++++++--------------- 9 files changed, 701 insertions(+), 181 deletions(-) create mode 100644 src/network/net_vde.c diff --git a/.gitignore b/.gitignore index acb28baf7..48a5950b9 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ CMakeLists.txt.user /debian/debhelper-build-stamp /debian/files /obj-*-linux-gnu + +# MacOS Finder stuff +.DS_Store diff --git a/CMakePresets.json b/CMakePresets.json index d2980ed87..0dbaf1988 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -56,6 +56,72 @@ "NEW_DYNAREC": "ON" }, "inherits": "base" + }, + { + "name": "llvm-macos-aarch64.cmake", + "displayName": "MacOS clang regular", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/llvm-macos-aarch64.cmake", + "NEW_DYNAREC": "ON", + "QT": "ON", + "USE_QT6": "OFF", + "Qt5_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5", + "MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk", + "Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools", + "OpenAL_ROOT": "/opt/homebrew/opt/openal-soft" + }, + "inherits": "regular" + }, + { + "name": "llvm-macos-aarch64-debug", + "displayName": "MacOS clang debug", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "CMAKE_TOOLCHAIN_FILE": "cmake/llvm-macos-aarch64.cmake", + "NEW_DYNAREC": "ON", + "QT": "ON", + "USE_QT6": "OFF", + "Qt5_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5", + "MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk", + "Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools", + "OpenAL_ROOT": "/opt/homebrew/opt/openal-soft", + "CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG", + "CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG" + }, + "inherits": "debug" + }, + { + "name": "flags-gcc-aarch64-debug", + "displayName": "Linux ARM 64 - Debug", + "description": "Linux ARM64 - Debug build", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "NEW_DYNAREC": "ON", + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_TOOLCHAIN_FILE": "cmake/flags-gcc-aarch64.cmake", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}", + "CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG", + "CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG" + }, + "inherits": "debug" + }, + { + "name": "flags-gcc-aarch64-regular", + "displayName": "Linux ARM 64 - Regular", + "description": "Linux ARM64 - Release build", + "generator": "Ninja", + "binaryDir": "${sourceDir}/out/build/${presetName}", + "cacheVariables": { + "NEW_DYNAREC": "ON", + "CMAKE_BUILD_TYPE": "Release", + "CMAKE_TOOLCHAIN_FILE": "cmake/flags-gcc-aarch64.cmake", + "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}" + }, + "inherits": "regular" } ], "buildPresets": [], diff --git a/src/config.c b/src/config.c index 75a3973e4..f9570442b 100644 --- a/src/config.c +++ b/src/config.c @@ -783,6 +783,8 @@ load_network(void) net_cards_conf[c].net_type = NET_TYPE_PCAP; else if (!strcmp(p, "slirp") || !strcmp(p, "2")) net_cards_conf[c].net_type = NET_TYPE_SLIRP; + else if (!strcmp(p, "vde") || !strcmp(p, "2")) + net_cards_conf[c].net_type = NET_TYPE_VDE; else net_cards_conf[c].net_type = NET_TYPE_NONE; } else { @@ -791,13 +793,17 @@ load_network(void) p = ini_section_get_string(cat, "net_host_device", NULL); if (p != NULL) { - if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { - if (network_ndev == 1) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130); - } else if (network_dev_to_id(p) == -1) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130); + if (net_cards_conf[c].net_type == NET_TYPE_PCAP) { + if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { + if (network_ndev == 1) { + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130); + } else if (network_dev_to_id(p) == -1) { + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130); + } + strcpy(net_cards_conf[c].host_dev_name, "none"); + } else { + strncpy(net_cards_conf[c].host_dev_name, p, sizeof(net_cards_conf[c].host_dev_name) - 1); } - strcpy(net_cards_conf[c].host_dev_name, "none"); } else { strncpy(net_cards_conf[c].host_dev_name, p, sizeof(net_cards_conf[c].host_dev_name) - 1); } @@ -828,6 +834,8 @@ load_network(void) net_cards_conf[c].net_type = NET_TYPE_PCAP; } else if (!strcmp(p, "slirp") || !strcmp(p, "2")) { net_cards_conf[c].net_type = NET_TYPE_SLIRP; + } else if (!strcmp(p, "vde") || !strcmp(p, "2")) { + net_cards_conf[c].net_type = NET_TYPE_VDE; } else { net_cards_conf[c].net_type = NET_TYPE_NONE; } @@ -838,13 +846,15 @@ load_network(void) sprintf(temp, "net_%02i_host_device", c + 1); p = ini_section_get_string(cat, temp, NULL); if (p != NULL) { - if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { - if (network_ndev == 1) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130); - } else if (network_dev_to_id(p) == -1) { - ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130); + if (net_cards_conf[c].net_type == NET_TYPE_PCAP) { + if ((network_dev_to_id(p) == -1) || (network_ndev == 1)) { + if (network_ndev == 1) { + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2095, (wchar_t *) IDS_2130); + } else if (network_dev_to_id(p) == -1) { + ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2096, (wchar_t *) IDS_2130); + } + strcpy(net_cards_conf[c].host_dev_name, "none"); } - strcpy(net_cards_conf[c].host_dev_name, "none"); } else { strncpy(net_cards_conf[c].host_dev_name, p, sizeof(net_cards_conf[c].host_dev_name) - 1); } @@ -2469,11 +2479,19 @@ save_network(void) } sprintf(temp, "net_%02i_net_type", c + 1); - if (net_cards_conf[c].net_type == NET_TYPE_NONE) { - ini_section_delete_var(cat, temp); - } else { - ini_section_set_string(cat, temp, - (net_cards_conf[c].net_type == NET_TYPE_SLIRP) ? "slirp" : "pcap"); + switch(net_cards_conf[c].net_type) { + case NET_TYPE_NONE: + ini_section_delete_var(cat, temp); + break; + case NET_TYPE_SLIRP: + ini_section_set_string(cat, temp, "slirp"); + break; + case NET_TYPE_PCAP: + ini_section_set_string(cat, temp, "pcap"); + break; + case NET_TYPE_VDE: + ini_section_set_string(cat, temp, "vde"); + break; } sprintf(temp, "net_%02i_host_device", c + 1); diff --git a/src/include/86box/network.h b/src/include/86box/network.h index 0a396968f..4f514d1ac 100644 --- a/src/include/86box/network.h +++ b/src/include/86box/network.h @@ -51,6 +51,7 @@ #define NET_TYPE_NONE 0 /* networking disabled */ #define NET_TYPE_SLIRP 1 /* use the SLiRP port forwarder */ #define NET_TYPE_PCAP 2 /* use the (Win)Pcap API */ +#define NET_TYPE_VDE 3 /* use the VDE plug API */ #define NET_MAX_FRAME 1518 /* Queue size must be a power of 2 */ @@ -123,6 +124,7 @@ typedef struct netdrv_t { extern const netdrv_t net_pcap_drv; extern const netdrv_t net_slirp_drv; +extern const netdrv_t net_vde_drv; struct _netcard_t { const device_t *device; @@ -147,15 +149,27 @@ typedef struct { char description[128]; } netdev_t; +typedef struct { + int has_slirp: 1; + int has_pcap: 1; + int has_vde: 1; +} network_devmap_t; + + +#define HAS_NOSLIRP_NET(x) (x.has_pcap || x.has_vde) + #ifdef __cplusplus extern "C" { #endif /* Global variables. */ extern int nic_do_log; /* config */ -extern int network_ndev; +extern network_devmap_t network_devmap; +extern int network_ndev; // Number of pcap devices +extern network_devmap_t network_devmap; // Bitmap of available network types extern netdev_t network_devs[NET_HOST_INTF_MAX]; + /* Function prototypes. */ extern void network_init(void); extern netcard_t *network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_link_state); @@ -166,6 +180,8 @@ extern int network_available(void); extern void network_tx(netcard_t *card, uint8_t *, int); extern int net_pcap_prepare(netdev_t *); +extern int net_vde_prepare(void); + extern void network_connect(int id, int connect); extern int network_is_connected(int id); diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index e14f979d3..c6178a790 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt @@ -12,8 +12,8 @@ # # Copyright 2020-2021 David Hrdlička. # - -add_library(net OBJECT network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c +set(net_sources) +list(APPEND net_sources network.c net_pcap.c net_slirp.c net_dp8390.c net_3c501.c net_3c503.c net_ne2000.c net_pcnet.c net_wd8003.c net_plip.c net_event.c) option(SLIRP_EXTERNAL "Link against the system-provided libslirp library" OFF) @@ -39,3 +39,13 @@ endif() if(WIN32) target_link_libraries(86Box ws2_32) endif() + +if (UNIX) + find_path(HAS_VDE "libvdeplug.h" PATHS ${VDE_INCLUDE_DIR} "/usr/include /usr/local/include" "/opt/homebrew/include" ) + if(HAS_VDE) + add_compile_definitions(HAS_VDE) + list(APPEND net_sources net_vde.c) + endif() +endif() + +add_library(net OBJECT ${net_sources}) diff --git a/src/network/net_vde.c b/src/network/net_vde.c new file mode 100644 index 000000000..904b2789a --- /dev/null +++ b/src/network/net_vde.c @@ -0,0 +1,310 @@ + /* + * 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. + * + * VDE networking for 86box + * See https://wiki.virtualsquare.org/#!tutorials/vdebasics.md + * for basic information about VDE. You can browse the source + * code at https://github.com/virtualsquare/vde-2 + * + * VDE support is only available in Linux and MacOS. It _should_ + * be available in BSD*, and if someday there is a BSD version of + * 86box this _could_ work out of the box. + * + * Authors: jguillaumes + * Copyright 2023 jguillaumes. + * + * See the COPYING file at the top of the 86box for license details. + * TL;DR: GPL version 2. + */ +#include +#include +#include +#include +#include + +#if !defined(_WIN32) +#include +#include +#else +#error VDE is not supported under windows +#endif + +#include + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/plat.h> +#include <86box/plat_dynld.h> +#include <86box/thread.h> +#include <86box/timer.h> +#include <86box/network.h> +#include <86box/net_event.h> + +#define VDE_PKT_BATCH NET_QUEUE_LEN +#define VDE_DESCRIPTION "86Box virtual card" + +enum { + NET_EVENT_STOP = 0, + NET_EVENT_TX, + NET_EVENT_RX, + NET_EVENT_VDE, + NET_EVENT_MAX +}; + +static volatile void *libvde_handle = NULL; + +//+ +// VDE connection structure +//- +typedef struct { + void *vdeconn; // VDEPLUG Connection + netcard_t *card; // NIC linked to + thread_t *poll_tid; // Polling thread + net_evt_t tx_event; // Packets to transmit event + net_evt_t stop_event; // Stop thread event + netpkt_t pkt; // Packet read/sent + netpkt_t pktv[VDE_PKT_BATCH]; // Packet queue + uint8_t mac_addr[6]; // MAC Address +} net_vde_t; + +//+ +// VDE libvdeplug function pointers +//- +static VDECONN *(*f_vde_open)(char *, char *, int, struct vde_open_args *); // This is vde_open_real() +static void (*f_vde_close)(VDECONN *); +static int (*f_vde_datafd)(VDECONN *); // Get the data (read/write) handle +static int (*f_vde_ctlfd)(VDECONN *); // Get the control handle +static ssize_t (*f_vde_recv)(VDECONN *, void *, size_t, int); // Receive a packet +static ssize_t (*f_vde_send)(VDECONN *, const void *, size_t, int); // Send a packet + +//+ +// VDE libvdeplug function table (for import) +//- +static dllimp_t vde_imports[] = { + {"vde_open_real", &f_vde_open}, + {"vde_close", &f_vde_close}, + {"vde_datafd", &f_vde_datafd}, + {"vde_ctlfd", &f_vde_ctlfd}, + {"vde_recv", &f_vde_recv}, + {"vde_send", &f_vde_send}, + { NULL, NULL} +}; + +#ifdef ENABLE_VDE_LOG +#include +int vde_do_log = ENABLE_VDE_LOG; + +static void +vde_log(const char *fmt, ...) { + va_list ap; + + if (vde_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define vde_log(fmt, ...) +#endif + +#ifdef _WIN32 +#error VDE networking is not supported under windows +#else + +//+ +// VDE thread +//- +static void net_vde_thread(void *priv) { + net_vde_t *vde = (net_vde_t *) priv; + vde_log("VDE: Polling started.\n"); + + struct pollfd pfd[NET_EVENT_MAX]; + pfd[NET_EVENT_STOP].fd = net_event_get_fd(&vde->stop_event); + pfd[NET_EVENT_STOP].events = POLLIN | POLLPRI; + + pfd[NET_EVENT_TX].fd = net_event_get_fd(&vde->tx_event); + pfd[NET_EVENT_TX].events = POLLIN | POLLPRI; + + pfd[NET_EVENT_RX].fd = f_vde_datafd(vde->vdeconn); + pfd[NET_EVENT_RX].events = POLLIN; + + pfd[NET_EVENT_VDE].fd = f_vde_ctlfd(vde->vdeconn); + pfd[NET_EVENT_VDE].events = POLLIN; + + while(1) { + poll(pfd, NET_EVENT_MAX, -1); + + // Acvity in the control handle means the link is closed + // We send ourselves a STOP event + if (pfd[NET_EVENT_VDE].revents & POLLIN) { + net_event_set(&vde->stop_event); + } + + // There are packets queued to transmit + if (pfd[NET_EVENT_TX].revents & POLLIN) { + net_event_clear(&vde->tx_event); + int packets = network_tx_popv(vde->card, vde->pktv, VDE_PKT_BATCH); + for (int i=0; ivdeconn, vde->pktv[i].data,vde->pktv[i].len, 0 ); + if (nc == 0) { + vde_log("VDE: Problem, no bytes sent.\n"); + } + } + } + + // Packets are available for reading. Read packet and queue it + if (pfd[NET_EVENT_RX].revents & POLLIN) { + int nc = f_vde_recv(vde->vdeconn, vde->pkt.data, NET_MAX_FRAME, 0); + vde->pkt.len = nc; + network_rx_put_pkt(vde->card, &vde->pkt); + } + + // We have been told to close + if (pfd[NET_EVENT_STOP].revents & POLLIN) { + net_event_clear(&vde->stop_event); + break; + } + } + vde_log("VDE: Polling stopped.\n"); +} +#endif + + +//+ +// Prepare the VDE libvdeplug interface. +// Load the dynamic library libvdeplug. +// Returns zero if the library has been loaded, -1 in case of error. +//- +int net_vde_prepare(void) { + +#if defined(_WIN32) + #error VDE is not supported in Windows +#elif defined(__APPLE__) + libvde_handle = dynld_module("libvdeplug.dylib", vde_imports); +#else + libvde_handle = dynld_module("libvdeplug.so", vde_imports); +#endif + + if (libvde_handle == NULL) { + vde_log("VDE: error loading VDEPLUG module\n"); + return -1; + } else { + network_devmap.has_vde = 1; + } + return 0; +} + +//+ +// Close a VDE socket connection +//- +void net_vde_close(void *priv) { + int i; + + if (!priv) return; + + net_vde_t *vde = (net_vde_t *) priv; + vde_log("VDE: closing.\n"); + net_event_set(&vde->stop_event); // Tell the thread to finish + vde_log("VDE: Waiting for the thread to finish...\n"); + thread_wait(vde->poll_tid); + vde_log("VDE: Thread finished.\n"); + + // Free all the mallocs! + for(i=0;ipktv[i].data); + } + free(vde->pkt.data); + f_vde_close((void *) vde->vdeconn); + net_event_close(&vde->tx_event); + net_event_close(&vde->stop_event); + free(vde); +} + +//+ +// Signal packets are available to be transmitted +//- +void net_vde_in_available(void *priv) { + net_vde_t *vde = (net_vde_t *) priv; + net_event_set(&vde->tx_event); +} + +//+ +// Initialize VDE for use +// At this point the vdeplug library is already loaded +// card: network card we are attaching +// mac_addr: MAC address we are using +// priv: Name of the VDE contol socket directory +//- +void *net_vde_init(const netcard_t *card, const uint8_t *mac_addr, void *priv) { + struct vde_open_args vde_args; + int i; + + char *socket_name = (char *) priv; + + if (libvde_handle == NULL) { + vde_log("VDE: net_vde_init without library handle!\n"); + return NULL; + } + + if ((socket_name[0] == '\0') || !strcmp(socket_name, "none")) { + vde_log("VDE: No socket name configured!\n"); + return NULL; + } + + vde_log("VDE: Attaching to virtual switch at %s\n", socket_name); + + net_vde_t *vde = calloc(1, sizeof(net_vde_t)); + vde->card = (netcard_t *) card; + memcpy(vde->mac_addr, mac_addr, sizeof(vde->mac_addr)); + + vde_args.group = 0; + vde_args.port = 0; + vde_args.mode = 0; + + // We are calling vde_open_real(), not the vde_open() macro... + if ((vde->vdeconn = f_vde_open(socket_name, VDE_DESCRIPTION, + LIBVDEPLUG_INTERFACE_VERSION, &vde_args)) == NULL) { + vde_log("VDE: Unable to open socket %s (%s)!\n", socket_name, strerror(errno)); + free(vde); + //+ + // There is a bug upstream that causes an uncontrolled crash if the network is not + // properly initialized. + // To avoid that crash, we tell the user we cannot continue and exit the program. + // TODO: Once there is a solution for the mentioned crash, this should be removed + // and/or replaced by proper error handling code. + //- + fatal("Could not open the specified VDE socket (%s). Please fix your networking configuration.", socket_name); + // It makes no sense to issue this warning since the program will crash anyway... + // ui_msgbox_header(MBX_WARNING, (wchar_t *) IDS_2167, (wchar_t *) IDS_2168); + return NULL; + } + vde_log("VDE: Socket opened (%s).\n", socket_name); + + for(i=0; i < VDE_PKT_BATCH; i++) { + vde->pktv[i].data = calloc(1, NET_MAX_FRAME); + } + vde->pkt.data = calloc(1,NET_MAX_FRAME); + net_event_init(&vde->tx_event); + net_event_init(&vde->stop_event); + vde->poll_tid = thread_create(net_vde_thread, vde); // Fire up the read-write thread! + + return vde; +} + +//+ +// VDE Driver structure +//- +const netdrv_t net_vde_drv = { + &net_vde_in_available, + &net_vde_init, + &net_vde_close, + NULL +}; + diff --git a/src/network/network.c b/src/network/network.c index f6e9eb565..ce81fcc93 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -123,7 +123,8 @@ netcard_conf_t net_cards_conf[NET_CARD_MAX]; uint16_t net_card_current = 0; /* Global variables. */ -int network_ndev; +network_devmap_t network_devmap; +int network_ndev; netdev_t network_devs[NET_HOST_INTF_MAX]; /* Local variables. */ @@ -214,9 +215,20 @@ network_init(void) network_ndev = 1; /* Initialize the Pcap system module, if present. */ + + network_devmap.has_slirp = 1; i = net_pcap_prepare(&network_devs[network_ndev]); - if (i > 0) + if (i > 0) { + network_devmap.has_pcap = 1; network_ndev += i; + } + +#ifdef HAS_VDE + // Try to load the VDE plug library + if(net_vde_prepare()==0) { + network_devmap.has_vde = 1; + } +#endif #if defined ENABLE_NETWORK_LOG && !defined(_WIN32) /* Start packet dump. */ @@ -286,6 +298,17 @@ int network_queue_put_swap(netqueue_t *queue, netpkt_t *src_pkt) { if (src_pkt->len == 0 || src_pkt->len > NET_MAX_FRAME || network_queue_full(queue)) { +#ifdef DEBUG + if (src_pkt->len == 0) { + network_log("Discarded zero length packet.\n"); + } else if (src_pkt->len > NET_MAX_FRAME) { + network_log("Discarded oversized packet of len=%d.\n", src_pkt->len); + network_dump_packet(src_pkt); + } else { + network_log("Discarded %d bytes packet because the queue is full.\n", src_pkt->len); + network_dump_packet(src_pkt); + } +#endif return 0; } @@ -434,6 +457,12 @@ network_attach(void *card_drv, uint8_t *mac, NETRXCB rx, NETSETLINKSTATE set_lin card->host_drv = net_pcap_drv; card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name); break; +#ifdef HAS_VDE + case NET_TYPE_VDE: + card->host_drv = net_vde_drv; + card->host_drv.priv = card->host_drv.init(card, mac, net_cards_conf[net_card_current].host_dev_name); + break; +#endif } if (!card->host_drv.priv) { @@ -617,6 +646,8 @@ network_dev_available(int id) if ((net_cards_conf[id].net_type == NET_TYPE_PCAP && (network_dev_to_id(net_cards_conf[id].host_dev_name) <= 0))) available = 0; + // TODO: Handle VDE device + return available; } diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 014e82ab3..7134e3381 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -37,13 +37,17 @@ SettingsNetwork::enableElements(Ui::SettingsNetwork *ui) auto *net_type_cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); auto *intf_cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); auto *conf_btn = findChild(QString("pushButtonConf%1").arg(i + 1)); + auto *socket_line = findChild(QString("socketVDENIC%1").arg(i + 1)); int netType = net_type_cbox->currentData().toInt(); - bool adaptersEnabled = netType == NET_TYPE_SLIRP || (netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0); + bool adaptersEnabled = netType == NET_TYPE_SLIRP + || NET_TYPE_VDE + || (netType == NET_TYPE_PCAP && intf_cbox->currentData().toInt() > 0); intf_cbox->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_PCAP); nic_cbox->setEnabled(adaptersEnabled); conf_btn->setEnabled(adaptersEnabled && network_card_has_config(nic_cbox->currentData().toInt())); + socket_line->setEnabled(net_type_cbox->currentData().toInt() == NET_TYPE_VDE); } } @@ -59,6 +63,7 @@ SettingsNetwork::SettingsNetwork(QWidget *parent) auto *nic_cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); auto *net_type_cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); auto *intf_cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); + auto *socket_line = findChild(QString("socketVDENIC%1").arg(i + 1)); connect(nic_cbox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged); connect(net_type_cbox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged); connect(intf_cbox, QOverload::of(&QComboBox::currentIndexChanged), this, &SettingsNetwork::on_comboIndexChanged); @@ -75,12 +80,18 @@ SettingsNetwork::save() { for (int i = 0; i < NET_CARD_MAX; ++i) { auto *cbox = findChild(QString("comboBoxNIC%1").arg(i + 1)); + auto *socket_line = findChild(QString("socketVDENIC%1").arg(i + 1)); net_cards_conf[i].device_num = cbox->currentData().toInt(); cbox = findChild(QString("comboBoxNet%1").arg(i + 1)); net_cards_conf[i].net_type = cbox->currentData().toInt(); cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); memset(net_cards_conf[i].host_dev_name, '\0', sizeof(net_cards_conf[i].host_dev_name)); - strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1); + if (net_cards_conf[i].net_type == NET_TYPE_PCAP) { + strncpy(net_cards_conf[i].host_dev_name, network_devs[cbox->currentData().toInt()].device, sizeof(net_cards_conf[i].host_dev_name) - 1); + } else if (net_cards_conf[i].net_type == NET_TYPE_VDE) { + const char *str_socket = socket_line->text().toStdString().c_str(); + strncpy(net_cards_conf[i].host_dev_name, str_socket, strlen(str_socket)); + } } } @@ -124,26 +135,37 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) removeRows = model->rowCount(); Models::AddEntry(model, tr("None"), NET_TYPE_NONE); Models::AddEntry(model, "SLiRP", NET_TYPE_SLIRP); + if (network_ndev > 1) { Models::AddEntry(model, "PCap", NET_TYPE_PCAP); } + if (network_devmap.has_vde) { + Models::AddEntry(model, "VDE", NET_TYPE_VDE); + } + model->removeRows(0, removeRows); cbox->setCurrentIndex(net_cards_conf[i].net_type); selectedRow = 0; - QString currentPcapDevice = net_cards_conf[i].host_dev_name; - cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); - model = cbox->model(); - removeRows = model->rowCount(); - for (int c = 0; c < network_ndev; c++) { - Models::AddEntry(model, tr(network_devs[c].description), c); - if (QString(network_devs[c].device) == currentPcapDevice) { - selectedRow = c; + if (net_cards_conf[i].net_type == NET_TYPE_PCAP) { + QString currentPcapDevice = net_cards_conf[i].host_dev_name; + cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); + model = cbox->model(); + removeRows = model->rowCount(); + for (int c = 0; c < network_ndev; c++) { + Models::AddEntry(model, tr(network_devs[c].description), c); + if (QString(network_devs[c].device) == currentPcapDevice) { + selectedRow = c; + } } + model->removeRows(0, removeRows); + cbox->setCurrentIndex(selectedRow); + } else if (net_cards_conf[i].net_type == NET_TYPE_VDE) { + QString currentVdeSocket = net_cards_conf[i].host_dev_name; + auto editline = findChild(QString("socketVDENIC%1").arg(i+1)); + editline->setText(currentVdeSocket); } - model->removeRows(0, removeRows); - cbox->setCurrentIndex(selectedRow); } } diff --git a/src/qt/qt_settingsnetwork.ui b/src/qt/qt_settingsnetwork.ui index d781a1beb..d6f77a0a2 100644 --- a/src/qt/qt_settingsnetwork.ui +++ b/src/qt/qt_settingsnetwork.ui @@ -36,19 +36,6 @@ Network Card #1 - - - - - 0 - 0 - - - - QComboBox::AdjustToContents - - - @@ -62,14 +49,17 @@ - - + + 0 0 + + QComboBox::AdjustToContents + @@ -98,17 +88,14 @@ - - + + - + 0 0 - - Mode - @@ -121,7 +108,7 @@ - + Qt::Vertical @@ -134,6 +121,33 @@ + + + + + 0 + 0 + + + + Mode + + + + + + + 127 + + + + + + + VDE Socket + + + @@ -141,6 +155,36 @@ Network Card #2 + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + + + + Configure + + + @@ -154,19 +198,6 @@ - - - - - 0 - 0 - - - - Mode - - - @@ -193,6 +224,19 @@ + + + + + 0 + 0 + + + + Mode + + + @@ -203,25 +247,28 @@ - - - - - 0 - 0 - - - - - - + + - Configure + VDE Socket - - + + + + + + + + Network Card #3 + + + + + + + Qt::Vertical @@ -233,23 +280,6 @@ - - - - - Network Card #3 - - - - - - - 0 - 0 - - - - @@ -263,17 +293,14 @@ - - + + - + 0 0 - - Mode - @@ -299,19 +326,6 @@ - - - - - 0 - 0 - - - - Configure - - - @@ -325,41 +339,8 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - Network Card #4 - - - - - - - 0 - 0 - - - - QComboBox::AdjustToContents - - - - + 0 @@ -371,14 +352,44 @@ - - + + + + VDE Socket + + + + + - + 0 0 + + Mode + + + + + + + + Network Card #4 + + + + + + + 0 + 0 + + + + Adapter + @@ -394,29 +405,6 @@ - - - - - 0 - 0 - - - - Adapter - - - - - - - - 0 - 0 - - - - @@ -430,7 +418,43 @@ - + + + + + 0 + 0 + + + + QComboBox::AdjustToContents + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Configure + + + + Qt::Vertical @@ -443,6 +467,26 @@ + + + + + 0 + 0 + + + + + + + + + + + VDE Socket + + + From 4b0384e1b2e5f8fd451ff9b696058b770b00596f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 May 2023 01:20:32 +0600 Subject: [PATCH 09/34] usb: USB device configuration descriptor infrastructure --- src/include/86box/usb.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index 7860ada3b..10b27fd30 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -56,6 +56,18 @@ typedef struct uint8_t bLength; uint8_t bDescriptorType; } usb_desc_base_t; + +typedef struct +{ + usb_desc_base_t base; + + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} usb_desc_conf_t; #pragma pack(pop) /* USB endpoint device struct. Incomplete and unused. */ From af3bc0412c7d2d70f55f38357aaf9ba74129993d Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 May 2023 22:09:08 +0600 Subject: [PATCH 10/34] usb: fix port reset logic --- src/usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/usb.c b/src/usb.c index 03fe8a9a6..883e9b67a 100644 --- a/src/usb.c +++ b/src/usb.c @@ -215,6 +215,7 @@ ohci_port_reset_callback(void* priv) usb_t *dev = (usb_t *) priv; dev->ohci_mmio[OHCI_HcRhPortStatus1] &= ~0x10; + dev->ohci_mmio[OHCI_HcRhPortStatus1 + 2] |= 0x10; } void @@ -223,6 +224,7 @@ ohci_port_reset_callback_2(void* priv) usb_t *dev = (usb_t *) priv; dev->ohci_mmio[OHCI_HcRhPortStatus2] &= ~0x10; + dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] |= 0x10; } static void @@ -368,7 +370,6 @@ ohci_mmio_write(uint32_t addr, uint8_t val, void *p) if (old & 0x01) { dev->ohci_mmio[addr] |= 0x10; timer_on_auto(&dev->ohci_port_reset_timer[(addr - OHCI_HcRhPortStatus1) / 4], 10000.); - dev->ohci_mmio[addr + 2] |= 0x10; } else dev->ohci_mmio[addr + 2] |= 0x01; } @@ -449,6 +450,7 @@ usb_reset(void *priv) dev->ohci_mmio[OHCI_HcRevision] = 0x10; dev->ohci_mmio[OHCI_HcRevision + 1] = 0x01; dev->ohci_mmio[OHCI_HcRhDescriptorA] = 0x02; + dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] = 0x02; io_removehandler(dev->uhci_io_base, 0x20, uhci_reg_read, NULL, NULL, uhci_reg_write, uhci_reg_writew, NULL, dev); dev->uhci_enable = 0; From 331b579d44b0a4d720677ffa7c6aec339ae1075f Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 May 2023 22:19:04 +0600 Subject: [PATCH 11/34] usb: Make ports appear always powered on --- src/usb.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/usb.c b/src/usb.c index 883e9b67a..addc4b57e 100644 --- a/src/usb.c +++ b/src/usb.c @@ -186,6 +186,19 @@ ohci_mmio_read(uint32_t addr, void *p) ret = dev->ohci_mmio[addr]; + switch (addr) { + case 0x101: + ret = (ret & 0xfe) | (!!mem_a20_key); + break; + case OHCI_HcRhPortStatus1 + 1: + case OHCI_HcRhPortStatus2 + 1: + case OHCI_HcRhPortStatus3 + 1: + ret |= 0x1; + break; + default: + break; + } + if (addr == 0x101) ret = (ret & 0xfe) | (!!mem_a20_key); From b8fb1754d9021de270a377f965709c44f8676dee Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 May 2023 22:32:20 +0600 Subject: [PATCH 12/34] usb: OHCI HcInterruptDisable reads return HcInterruptEnable registers --- src/usb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/usb.c b/src/usb.c index addc4b57e..19c17f865 100644 --- a/src/usb.c +++ b/src/usb.c @@ -195,6 +195,12 @@ ohci_mmio_read(uint32_t addr, void *p) case OHCI_HcRhPortStatus3 + 1: ret |= 0x1; break; + case OHCI_HcInterruptDisable: + case OHCI_HcInterruptDisable + 1: + case OHCI_HcInterruptDisable + 2: + case OHCI_HcInterruptDisable + 3: + ret = dev->ohci_mmio[OHCI_HcInterruptEnable + (addr - OHCI_HcInterruptDisable)]; + break; default: break; } @@ -433,6 +439,14 @@ ohci_mmio_write(uint32_t addr, uint8_t val, void *p) case OHCI_HcRhPortStatus1 + 3: case OHCI_HcRhPortStatus2 + 3: return; + case OHCI_HcDoneHead: + case OHCI_HcBulkCurrentED: + case OHCI_HcBulkHeadED: + case OHCI_HcControlCurrentED: + case OHCI_HcControlHeadED: + case OHCI_HcPeriodCurrentED: + dev->ohci_mmio[addr] = (val & 0xf0); + return; } dev->ohci_mmio[addr] = val; From 1d0c18c3a9a85afd48da9547a483c559e3919f88 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 May 2023 22:46:18 +0600 Subject: [PATCH 13/34] usb: USB device attach/detach infrastructure --- src/include/86box/usb.h | 10 ++++++++++ src/usb.c | 12 ++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index 10b27fd30..ecb5c0f86 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -86,12 +86,22 @@ typedef struct void* priv; } usb_device_t; +enum usb_bus_types +{ + USB_BUS_OHCI = 0, + USB_BUS_UHCI = 1 +}; + /* Global variables. */ extern const device_t usb_device; /* Functions. */ extern void uhci_update_io_mapping(usb_t *dev, uint8_t base_l, uint8_t base_h, int enable); extern void ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, int enable); +/* Attach USB device to a port of a USB bus. Returns the port to which it got attached to. */ +extern uint8_t usb_attach_device(usb_t *dev, usb_device_t* device, uint8_t bus_type); +/* Detach USB device from a port. */ +extern void usb_detach_device(usb_t *dev, uint8_t port, uint8_t bus_type); #ifdef __cplusplus } diff --git a/src/usb.c b/src/usb.c index 19c17f865..d0703b5d7 100644 --- a/src/usb.c +++ b/src/usb.c @@ -464,6 +464,18 @@ ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, mem_mapping_set_addr(&dev->ohci_mmio_mapping, dev->ohci_mem_base, 0x1000); } +uint8_t +usb_attach_device(usb_t *dev, usb_device_t* device, uint8_t bus_type) +{ + return 255; +} + +void +usb_detach_device(usb_t *dev, uint8_t port, uint8_t bus_type) +{ + /* Unused. */ +} + static void usb_reset(void *priv) { From a77271cfa6c82b2b510693fbbbdae7f0ad0bac10 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 5 May 2023 19:08:49 +0200 Subject: [PATCH 14/34] Accelerator fixes part 1: XGA: Fix crash when (S)VGA cards not selected as the primary display (e.g.: EGA, CGA. etc). Better handling of the VGA on/off passthrough (vga_on variable). MCA side: to avoid lfb issues, bit 0 of POS4 will be always enabled regardless of the ram size (most software uses the >16MB memory method). Better handling of the BIOS ROM mapping and Memory Mapped I/O during the MCA PS/2 POST and resets, fixes 40 25 hang (once and for all). Re-organized the ROM loading in ISA mode. --- src/include/86box/vid_svga.h | 7 ++ src/video/vid_svga.c | 64 +++++++----- src/video/vid_xga.c | 190 ++++++++++++++++++----------------- 3 files changed, 143 insertions(+), 118 deletions(-) diff --git a/src/include/86box/vid_svga.h b/src/include/86box/vid_svga.h index 31eabc064..a18e136dd 100644 --- a/src/include/86box/vid_svga.h +++ b/src/include/86box/vid_svga.h @@ -184,6 +184,13 @@ extern int vga_on, ibm8514_on; extern void ibm8514_poll(ibm8514_t *dev, svga_t *svga); extern void ibm8514_recalctimings(svga_t *svga); +extern uint8_t ibm8514_ramdac_in(uint16_t port, void *p); +extern void ibm8514_ramdac_out(uint16_t port, uint8_t val, void *p); +extern int ibm8514_cpu_src(svga_t *svga); +extern int ibm8514_cpu_dest(svga_t *svga); +extern void ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint16_t val, int len); +extern void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len); +extern void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len); extern void xga_poll(xga_t *xga, svga_t *svga); extern void xga_recalctimings(svga_t *svga); diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 6f8cc0448..ceeb9cf65 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -199,15 +199,19 @@ svga_out(uint16_t addr, uint8_t val, void *p) break; } break; + case 0x2ea: case 0x3c6: svga->dac_mask = val; break; + case 0x2eb: + case 0x2ec: case 0x3c7: case 0x3c8: svga->dac_pos = 0; svga->dac_status = addr & 0x03; svga->dac_addr = (val + (addr & 0x01)) & 255; break; + case 0x2ed: case 0x3c9: if (svga->adv_flags & FLAG_RAMDAC_SHIFT) val <<= 2; @@ -311,15 +315,19 @@ svga_in(uint16_t addr, void *p) case 0x3c5: ret = svga->seqregs[svga->seqaddr & 0x0f]; break; + case 0x2ea: case 0x3c6: ret = svga->dac_mask; break; + case 0x2eb: case 0x3c7: ret = svga->dac_status; break; + case 0x2ec: case 0x3c8: ret = svga->dac_addr; break; + case 0x2ed: case 0x3c9: index = (svga->dac_addr - 1) & 255; switch (svga->dac_pos) { @@ -572,7 +580,7 @@ svga_recalctimings(svga_t *svga) svga->recalctimings_ex(svga); } } else { - if (ibm8514_on && ibm8514_enabled) + if (ibm8514_enabled) ibm8514_recalctimings(svga); if (xga_enabled) xga_recalctimings(svga); @@ -872,7 +880,7 @@ svga_poll(void *p) svga->oddeven ^= 1; svga->monitor->mon_changeframecount = svga->interlace ? 3 : 2; - svga->vslines = 0; + svga->vslines = 0; if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5); @@ -893,22 +901,24 @@ svga_poll(void *p) svga->dispon = 1; svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; - svga->scrollcache = (svga->attrregs[0x13] & 0x0f); - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 1) + if (!ibm8514_on) { + svga->scrollcache = (svga->attrregs[0x13] & 0x0f); + if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ + if (svga->seqregs[1] & 1) + svga->scrollcache &= 0x07; + else { + svga->scrollcache++; + if (svga->scrollcache > 8) + svga->scrollcache = 0; + } + } else if ((svga->render == svga_render_2bpp_lowres) || (svga->render == svga_render_2bpp_highres) || (svga->render == svga_render_4bpp_lowres) || (svga->render == svga_render_4bpp_highres)) svga->scrollcache &= 0x07; - else { - svga->scrollcache++; - if (svga->scrollcache > 8) - svga->scrollcache = 0; - } - } else if ((svga->render == svga_render_2bpp_lowres) || (svga->render == svga_render_2bpp_highres) || (svga->render == svga_render_4bpp_lowres) || (svga->render == svga_render_4bpp_highres)) - svga->scrollcache &= 0x07; - else - svga->scrollcache = (svga->scrollcache & 0x06) >> 1; + else + svga->scrollcache = (svga->scrollcache & 0x06) >> 1; - if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres)) - svga->scrollcache <<= 1; + if ((svga->seqregs[1] & 8) || (svga->render == svga_render_8bpp_lowres)) + svga->scrollcache <<= 1; + } svga->x_add = (svga->monitor->mon_overscan_x >> 1) - svga->scrollcache; @@ -938,9 +948,9 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, { int c, d, e; - svga->p = p; + svga->p = p; svga->monitor_index = monitor_index_global; - svga->monitor = &monitors[svga->monitor_index]; + svga->monitor = &monitors[svga->monitor_index]; for (c = 0; c < 256; c++) { e = c; @@ -954,10 +964,10 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize, svga->attrregs[0x11] = 0; svga->overscan_color = 0x000000; - svga->monitor->mon_overscan_x = 16; - svga->monitor->mon_overscan_y = 32; - svga->x_add = 8; - svga->y_add = 16; + svga->monitor->mon_overscan_x = 16; + svga->monitor->mon_overscan_y = 32; + svga->x_add = 8; + svga->y_add = 16; svga->crtc[0] = 63; svga->crtc[6] = 255; @@ -1096,8 +1106,10 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) svga->xga.linear_endian_reverse = 1; return; } - } else + } else { svga->xga.on = 0; + vga_on = !svga->xga.on; + } } addr = svga_decode_addr(svga, addr, 1); @@ -1286,16 +1298,20 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p) if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl == 1)) { if (svga->xga.test == 0xa5) { /*Memory size test of XGA*/ svga->xga.on = 1; + vga_on = !svga->xga.on; return svga->xga.test; } else if (svga->xga.test == 0x5a) { svga->xga.on = 1; + vga_on = !svga->xga.on; return svga->xga.test; } else if (addr == 0xa0000 || addr == 0xa0010) { addr += svga->xga.read_bank; return svga->xga.vram[addr & svga->xga.vram_mask]; } - } else + } else { svga->xga.on = 0; + vga_on = !svga->xga.on; + } } addr = svga_decode_addr(svga, addr, 0); diff --git a/src/video/vid_xga.c b/src/video/vid_xga.c index 84c1805ff..11e94f531 100644 --- a/src/video/vid_xga.c +++ b/src/video/vid_xga.c @@ -1,18 +1,18 @@ /* - * 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. + * 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. + * This file is part of the 86Box distribution. * - * IBM XGA emulation. + * IBM XGA emulation. * * * - * Authors: TheCollector1995. + * Authors: TheCollector1995. * - * Copyright 2022 TheCollector1995. + * Copyright 2022 TheCollector1995. */ #include #include @@ -38,16 +38,19 @@ #define XGA_BIOS_PATH "roms/video/xga/XGA_37F9576_Ver200.BIN" #define XGA2_BIOS_PATH "roms/video/xga/xga2_v300.bin" +static video_timings_t timing_xga_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 }; +static video_timings_t timing_xga_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 }; + static void xga_ext_outb(uint16_t addr, uint8_t val, void *p); static uint8_t xga_ext_inb(uint16_t addr, void *p); -static void +void xga_updatemapping(svga_t *svga) { xga_t *xga = &svga->xga; - // pclog("OpMode = %x, linear base = %08x, aperture cntl = %d, opmodereset1 = %d, access mode = %x, map = %x.\n", xga->op_mode, xga->linear_base, xga->aperture_cntl, xga->op_mode_reset, xga->access_mode, svga->gdcreg[6] & 0x0c); - if ((xga->op_mode & 7) >= 4) { + //pclog("OpMode = %x, linear base = %08x, aperture cntl = %d, opmodereset1 = %d, access mode = %x, map = %x.\n", xga->op_mode, xga->linear_base, xga->aperture_cntl, xga->op_mode_reset, xga->access_mode, svga->gdcreg[6] & 0x0c); + if (((xga->op_mode & 7) >= 4) || ((xga->op_mode & 7) == 0)) { if (xga->aperture_cntl == 1) { mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); @@ -56,25 +59,22 @@ xga_updatemapping(svga_t *svga) if (!xga->linear_endian_reverse) mem_mapping_disable(&xga->linear_mapping); } else if (xga->aperture_cntl == 0) { -linear: mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); mem_mapping_enable(&xga->video_mapping); xga->banked_mask = 0xffff; - if ((xga->pos_regs[4] & 1) && !xga->base_addr_1mb) { - xga->linear_size = 0x400000; - mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, xga->linear_size); - } else { - if (xga->base_addr_1mb) { - xga->linear_size = 0x100000; - mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, xga->linear_size); - } else - mem_mapping_disable(&xga->linear_mapping); - } - xga->on = 0; - vga_on = 1; - if (((xga->op_mode & 7) == 4) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test) + if (xga->pos_regs[4] & 1) + mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); + else if (xga->base_addr_1mb) + mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000); + else + mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000); + if (((xga->op_mode & 7) == 4) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test && xga->on) xga->linear_endian_reverse = 1; + else if (((xga->op_mode & 7) == 0) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test && !xga->on) + xga->linear_endian_reverse = 1; + xga->on = 0; + vga_on = !xga->on; } else { mem_mapping_disable(&svga->mapping); mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000); @@ -83,23 +83,17 @@ linear: mem_mapping_disable(&xga->linear_mapping); } } else { - if (!(xga->op_mode & 7)) { - goto linear; - } - if (xga->aperture_cntl == 2) { - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000); - mem_mapping_enable(&xga->video_mapping); - xga->banked_mask = 0xffff; - } else { - mem_mapping_disable(&svga->mapping); - mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); - mem_mapping_enable(&xga->video_mapping); - xga->banked_mask = 0xffff; - } - mem_mapping_disable(&xga->linear_mapping); xga->on = 0; - vga_on = 1; + vga_on = !xga->on; + mem_mapping_disable(&svga->mapping); + if (xga->aperture_cntl == 2) + mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000); + else + mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000); + mem_mapping_enable(&xga->video_mapping); + xga->banked_mask = 0xffff; + mem_mapping_disable(&xga->linear_mapping); + //pclog("XGA opmode (not extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, xga->disp_cntl_2 & 7, xga->aperture_cntl); } } @@ -147,8 +141,6 @@ xga_recalctimings(svga_t *svga) svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0; break; } - } else { - vga_on = 1; } } @@ -292,6 +284,8 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) case 0x51: xga->disp_cntl_2 = val; + xga->on = ((val & 7) >= 3); + vga_on = !xga->on; svga_recalctimings(svga); break; @@ -318,7 +312,7 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) else if (xga->sprite_pos >= 1) xga->cursor_data_on = 1; else if (xga->aperture_cntl == 0) { - if (xga->linear_endian_reverse) + if (xga->linear_endian_reverse && !(xga->access_mode & 8)) xga->cursor_data_on = 0; } } @@ -351,7 +345,7 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val) break; case 0x65: - svga->fullchange = changeframecount; + svga->fullchange = svga->monitor->mon_changeframecount; switch (svga->dac_pos) { case 0: svga->dac_r = val; @@ -406,7 +400,7 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *p) svga_t *svga = (svga_t *) p; xga_t *xga = &svga->xga; - // pclog("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); + //pclog("[%04X:%08X]: EXT OUTB = %02x, val = %02x\n", CS, cpu_state.pc, addr, val); switch (addr & 0x0f) { case 0: xga->op_mode = val; @@ -421,12 +415,10 @@ xga_ext_outb(uint16_t addr, uint8_t val, void *p) xga->aperture_cntl = 0; break; case 6: - vga_on = 0; - xga->on = 1; break; case 8: xga->ap_idx = val; - // pclog("Aperture CNTL = %d, val = %02x, up to bit6 = %02x\n", xga->aperture_cntl, val, val & 0x3f); + //pclog("Aperture CNTL = %d, val = %02x, up to bit6 = %02x\n", xga->aperture_cntl, val, val & 0x3f); if ((xga->op_mode & 7) < 4) { xga->write_bank = xga->read_bank = 0; } else { @@ -586,10 +578,10 @@ xga_ext_inb(uint16_t addr, void *p) ret = xga->disp_cntl_2; break; case 0x52: - ret = 0x0b; + ret = xga->type ? 0xfa : 0xea; break; case 0x53: - ret = 0x70; + ret = xga->type ? 0x53 : 0x30; break; case 0x54: ret = xga->clk_sel_1; @@ -667,7 +659,7 @@ xga_ext_inb(uint16_t addr, void *p) break; } - // pclog("[%04X:%08X]: EXT INB = %02x, ret = %02x\n", CS, cpu_state.pc, addr, ret); + //pclog("[%04X:%08X]: EXT INB = %02x, ret = %02x\n", CS, cpu_state.pc, addr, ret); return ret; } @@ -676,7 +668,7 @@ xga_ext_inb(uint16_t addr, void *p) #define WRITE(addr, dat) \ xga->vram[((addr)) & (xga->vram_mask)] = dat; \ - xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = changeframecount; + xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; #define READW(addr, dat) \ dat = *(uint16_t *) &xga->vram[(addr) & (xga->vram_mask)]; @@ -687,12 +679,12 @@ xga_ext_inb(uint16_t addr, void *p) #define WRITEW(addr, dat) \ *(uint16_t *) &xga->vram[((addr)) & (xga->vram_mask)] = dat; \ - xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = changeframecount; + xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; #define WRITEW_REVERSE(addr, dat) \ xga->vram[((addr + 1)) & (xga->vram_mask - 1)] = dat & 0xff; \ xga->vram[((addr)) & (xga->vram_mask - 1)] = dat >> 8; \ - xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = changeframecount; + xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; #define ROP(mix, d, s) \ { \ @@ -908,12 +900,12 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui if (pixel & 1) { if (!skip) { xga->vram[((addr)) & (xga->vram_mask)] |= mask; - xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = changeframecount; + xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; } } else { if (!skip) { xga->vram[((addr)) & (xga->vram_mask)] &= ~mask; - xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = changeframecount; + xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount; } } mem_writeb_phys(addr, byte); @@ -2198,7 +2190,7 @@ xga_write(uint32_t addr, uint8_t val, void *p) cycles -= video_timing_write_b; - xga->changedvram[(addr & xga->vram_mask) >> 12] = changeframecount; + xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; xga->vram[addr & xga->vram_mask] = val; } @@ -2245,7 +2237,7 @@ xga_write_linear(uint32_t addr, uint8_t val, void *p) cycles -= video_timing_write_b; - xga->changedvram[(addr & xga->vram_mask) >> 12] = changeframecount; + xga->changedvram[(addr & xga->vram_mask) >> 12] = svga->monitor->mon_changeframecount; xga->vram[addr & xga->vram_mask] = val; } @@ -2559,7 +2551,7 @@ xga_poll(xga_t *xga, svga_t *svga) xga->oddeven ^= 1; - changeframecount = xga->interlace ? 3 : 2; + svga->monitor->mon_changeframecount = xga->interlace ? 3 : 2; if (xga->interlace && xga->oddeven) xga->ma = xga->maback = xga->ma_latch + (xga->rowoffset << 1); @@ -2588,9 +2580,13 @@ xga_mca_read(int port, void *priv) { svga_t *svga = (svga_t *) priv; xga_t *xga = &svga->xga; + uint8_t ret = xga->pos_regs[port & 7]; - // pclog("[%04X:%08X]: POS Read Port = %x, val = %02x\n", CS, cpu_state.pc, port & 7, xga->pos_regs[port & 7]); - return (xga->pos_regs[port & 7]); + if (((port & 7) == 3) && !(ret & 1)) /*Always enable the mapping.*/ + ret |= 1; + + //pclog("[%04X:%08X]: POS Read Port = %x, val = %02x\n", CS, cpu_state.pc, port & 7, xga->pos_regs[port & 7]); + return (ret); } static void @@ -2607,11 +2603,13 @@ xga_mca_write(int port, uint8_t val, void *priv) mem_mapping_disable(&xga->bios_rom.mapping); mem_mapping_disable(&xga->memio_mapping); xga->on = 0; - vga_on = 1; + vga_on = !xga->on; + xga->linear_endian_reverse = 0; + xga->a5_test = 0; /* Save the MCA register value. */ xga->pos_regs[port & 7] = val; - if (!(xga->pos_regs[4] & 1)) /*MCA 4MB addressing on systems with more than 16MB of memory*/ + if (!(xga->pos_regs[4] & 1) && (mem_size >= 16384)) /*MCA 4MB addressing on systems with more than 16MB of memory*/ xga->pos_regs[4] |= 1; if (xga->pos_regs[2] & 1) { @@ -2622,13 +2620,12 @@ xga_mca_write(int port, uint8_t val, void *priv) io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga); - if (xga->pos_regs[3] & 1) { + if (xga->pos_regs[3] & 1) mem_mapping_set_addr(&xga->bios_rom.mapping, xga->rom_addr, 0x2000); - } else { + else mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr + 0x1c00 + (xga->instance * 0x80), 0x80); - } } - // pclog("[%04X:%08X]: POS Write Port = %x, val = %02x, linear base = %08x, instance = %d, rom addr = %05x\n", CS, cpu_state.pc, port & 7, val, xga->linear_base, xga->instance, xga->rom_addr); + //pclog("[%04X:%08X]: POS Write Port = %x, val = %02x, linear base = %08x, instance = %d, rom addr = %05x\n", CS, cpu_state.pc, port & 7, val, xga->linear_base, xga->instance, xga->rom_addr); } static uint8_t @@ -2644,10 +2641,27 @@ static void xga_mca_reset(void *p) { svga_t *svga = (svga_t *) p; + xga_t *xga = &svga->xga; + xga->on = 0; + vga_on = !xga->on; xga_mca_write(0x102, 0, svga); } +static void +xga_reset(void *p) +{ + svga_t *svga = (svga_t *) p; + xga_t *xga = &svga->xga; + + mem_mapping_disable(&xga->bios_rom.mapping); + mem_mapping_disable(&xga->memio_mapping); + xga->on = 0; + vga_on = !xga->on; + xga->linear_endian_reverse = 0; + xga->a5_test = 0; +} + static uint8_t xga_pos_in(uint16_t addr, void *priv) { @@ -2660,10 +2674,13 @@ static void * xga_init(const device_t *info) { + if (svga_get_pri() == NULL) + return NULL; + svga_t *svga = svga_get_pri(); xga_t *xga = &svga->xga; FILE *f; - uint32_t initial_bios_addr = device_get_config_hex20("init_bios_addr"); + uint32_t temp; uint8_t *rom = NULL; xga->type = device_get_config_int("type"); @@ -2682,11 +2699,13 @@ static void f = rom_fopen(xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, "rb"); (void) fseek(f, 0L, SEEK_END); + temp = ftell(f); (void) fseek(f, 0L, SEEK_SET); rom = malloc(xga->bios_rom.sz); memset(rom, 0xff, xga->bios_rom.sz); - (void) !fread(rom, xga->bios_rom.sz, 1, f); + (void) fread(rom, xga->bios_rom.sz, 1, f); + temp -= xga->bios_rom.sz; (void) fclose(f); xga->bios_rom.rom = rom; @@ -2697,11 +2716,13 @@ static void xga->base_addr_1mb = 0; if (info->flags & DEVICE_MCA) { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_mca); xga->linear_base = 0; xga->instance = 0; xga->rom_addr = 0; - rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, initial_bios_addr, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); + rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, 0xc0000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL); } else { + video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_isa); xga->pos_regs[2] = 1 | 0x0c | 0xf0; xga->instance = (xga->pos_regs[2] & 0x0e) >> 1; xga->pos_regs[4] = 1 | 2; @@ -2768,30 +2789,11 @@ xga_force_redraw(void *p) { svga_t *svga = (svga_t *) p; - svga->fullchange = changeframecount; + svga->fullchange = svga->monitor->mon_changeframecount; } static const device_config_t xga_configuration[] = { // clang-format off - { - .name = "init_bios_addr", - .description = "Initial MCA BIOS Address (before POS configuration)", - .type = CONFIG_HEX20, - .default_string = "", - .default_int = 0xc0000, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "C000H", .value = 0xc0000 }, - { .description = "C800H", .value = 0xc8000 }, - { .description = "CC00H", .value = 0xcc000 }, - { .description = "D000H", .value = 0xd0000 }, - { .description = "D400H", .value = 0xd4000 }, - { .description = "D800H", .value = 0xd8000 }, - { .description = "DC00H", .value = 0xdc000 }, - { .description = "" } - }, - }, { .name = "type", .description = "XGA type", @@ -2813,7 +2815,7 @@ static const device_config_t xga_configuration[] = { } }, { .name = "", .description = "", .type = CONFIG_END } - // clang-format on +// clang-format on }; const device_t xga_device = { @@ -2823,7 +2825,7 @@ const device_t xga_device = { .local = 0, .init = xga_init, .close = xga_close, - .reset = NULL, + .reset = xga_reset, { .available = xga_available }, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, @@ -2837,7 +2839,7 @@ const device_t xga_isa_device = { .local = 0, .init = xga_init, .close = xga_close, - .reset = NULL, + .reset = xga_reset, { .available = xga_available }, .speed_changed = xga_speed_changed, .force_redraw = xga_force_redraw, From 6ec563984c73f239ea49a8eff2ff25c2bda41bfd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 May 2023 23:26:41 +0600 Subject: [PATCH 15/34] usb: OHCI HcInterruptEnable bits --- src/usb.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/usb.c b/src/usb.c index d0703b5d7..090e35bd1 100644 --- a/src/usb.c +++ b/src/usb.c @@ -76,6 +76,18 @@ enum OHCI_HcRhPortStatus3 = 0x5C }; +/* OHCI HcInterruptEnable/Disable bits */ +enum +{ + OHCI_HcInterruptEnable_SO = 1 << 0, + OHCI_HcInterruptEnable_WDH = 1 << 1, + OHCI_HcInterruptEnable_SF = 1 << 2, + OHCI_HcInterruptEnable_RD = 1 << 3, + OHCI_HcInterruptEnable_UE = 1 << 4, + OHCI_HcInterruptEnable_HNO = 1 << 5, + OHCI_HcInterruptEnable_RHSC = 1 << 6, +}; + static void usb_interrupt_ohci(usb_t* usb) { From b987e7dacbc39744496835485c8b1e5c83521168 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 5 May 2023 23:50:50 +0600 Subject: [PATCH 16/34] usb: Partially implement HcInterruptEnable/Disable registers --- src/usb.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/usb.c b/src/usb.c index 090e35bd1..12385c808 100644 --- a/src/usb.c +++ b/src/usb.c @@ -292,6 +292,36 @@ ohci_mmio_write(uint32_t addr, uint8_t val, void *p) break; case OHCI_HcHCCA: return; + case OHCI_HcInterruptEnable: + dev->ohci_mmio[addr] = (val & 0x7f); + dev->ohci_mmio[OHCI_HcInterruptDisable] &= ~(val & 0x7f); + return; + case OHCI_HcInterruptEnable + 1: + case OHCI_HcInterruptEnable + 2: + return; + case OHCI_HcInterruptEnable + 3: + dev->ohci_mmio[addr] = (val & 0x40); + dev->ohci_mmio[addr] |= (val & 0x80); + if (val & 0x80) + dev->ohci_mmio[OHCI_HcInterruptDisable + 3] &= ~0x80; + if (val & 0x40) + dev->ohci_mmio[OHCI_HcInterruptDisable + 3] &= ~0x40; + return; + case OHCI_HcInterruptDisable: + dev->ohci_mmio[addr] = (val & 0x7f); + dev->ohci_mmio[OHCI_HcInterruptEnable] &= ~(val & 0x7f); + return; + case OHCI_HcInterruptDisable + 1: + case OHCI_HcInterruptDisable + 2: + return; + case OHCI_HcInterruptDisable + 3: + dev->ohci_mmio[addr] = (val & 0x40); + dev->ohci_mmio[addr] |= (val & 0x80); + if (val & 0x80) + dev->ohci_mmio[OHCI_HcInterruptEnable + 3] &= ~0x80; + if (val & 0x40) + dev->ohci_mmio[OHCI_HcInterruptEnable + 3] &= ~0x40; + return; case OHCI_HcInterruptStatus: dev->ohci_mmio[addr] &= ~(val & 0x7f); return; From cf4968695742a530c455bd6b34c0872c7b296f91 Mon Sep 17 00:00:00 2001 From: TC1995 Date: Fri, 5 May 2023 19:55:27 +0200 Subject: [PATCH 17/34] Accelerator fixes part 2: 8514/A. Mix patterns are drawn at the correct position now instead of backwards. Better handling of subsys/subcntl side. As usual, better handling of the VGA on/off passthrough. Better handling of the accelerator pitch (TODO: need a way to properly identify 640x480x256 in the pitch side). --- src/include/86box/vid_8514a.h | 2 + src/video/vid_8514a.c | 689 ++++++++++++++++++++-------------- 2 files changed, 403 insertions(+), 288 deletions(-) diff --git a/src/include/86box/vid_8514a.h b/src/include/86box/vid_8514a.h index 6463d0214..e6510e3f1 100644 --- a/src/include/86box/vid_8514a.h +++ b/src/include/86box/vid_8514a.h @@ -83,6 +83,7 @@ typedef struct ibm8514_t { } accel; uint16_t test; + int ibm_mode; int v_total, dispend, v_syncstart, split, h_disp, h_disp_old, h_total, h_disp_time, rowoffset, @@ -107,5 +108,6 @@ typedef struct ibm8514_t { int blitter_busy; uint64_t blitter_time; uint64_t status_time; + int pitch; } ibm8514_t; #endif /*VIDEO_8514A_H*/ diff --git a/src/video/vid_8514a.c b/src/video/vid_8514a.c index f7f3ce607..b82b116c6 100644 --- a/src/video/vid_8514a.c +++ b/src/video/vid_8514a.c @@ -37,19 +37,15 @@ #include <86box/vid_svga_render.h> #include "cpu.h" -static void ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len); static void ibm8514_accel_outb(uint16_t port, uint8_t val, void *p); static void ibm8514_accel_outw(uint16_t port, uint16_t val, void *p); static uint8_t ibm8514_accel_inb(uint16_t port, void *p); static uint16_t ibm8514_accel_inw(uint16_t port, void *p); -static void ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, uint8_t ssv, int len); -static void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, int len); - #define READ_PIXTRANS_WORD(cx, n) \ - if (cmd <= 1 || (cmd == 5)) { \ - temp = dev->vram[((dev->accel.cy * dev->h_disp) + (cx) + (n)) & dev->vram_mask]; \ - temp |= (dev->vram[((dev->accel.cy * dev->h_disp) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ + if ((cmd <= 1) || (cmd == 5)) { \ + temp = dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n)) & dev->vram_mask]; \ + temp |= (dev->vram[((dev->accel.cy * dev->pitch) + (cx) + (n + 1)) & dev->vram_mask] << 8); \ } else { \ temp = dev->vram[(dev->accel.dest + (cx) + (n)) & dev->vram_mask]; \ temp |= (dev->vram[(dev->accel.dest + (cx) + (n + 1)) & dev->vram_mask] << 8); \ @@ -164,9 +160,11 @@ static void ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint dev->vram[((addr)) & (dev->vram_mask)] = dat; \ dev->changedvram[(((addr)) & (dev->vram_mask)) >> 12] = changeframecount; -static int -ibm8514_cpu_src(ibm8514_t *dev) +int +ibm8514_cpu_src(svga_t *svga) { + ibm8514_t *dev = &svga->dev8514; + if (!(dev->accel.cmd & 0x100)) return 0; @@ -176,9 +174,11 @@ ibm8514_cpu_src(ibm8514_t *dev) return 0; } -static int -ibm8514_cpu_dest(ibm8514_t *dev) +int +ibm8514_cpu_dest(svga_t *svga) { + ibm8514_t *dev = &svga->dev8514; + if (!(dev->accel.cmd & 0x100)) return 0; @@ -188,9 +188,10 @@ ibm8514_cpu_dest(ibm8514_t *dev) return 1; } -static void -ibm8514_accel_out_pixtrans(ibm8514_t *dev, uint16_t port, uint16_t val, int len) +void +ibm8514_accel_out_pixtrans(svga_t *svga, uint16_t port, uint16_t val, int len) { + ibm8514_t *dev = &svga->dev8514; uint8_t nibble = 0; uint32_t pixelxfer = 0, monoxfer = 0xffffffff; int pixcnt = 0; @@ -295,12 +296,12 @@ regular_nibble: nibble |= 0x01; } - if ((and3 == 0) || (dev->accel.cmd & 0x1000) || ((dev->accel.cmd & 8) && ibm8514_cpu_src(dev))) { - if ((dev->accel.cmd & 8) && ibm8514_cpu_src(dev)) { + if ((and3 == 0) || (dev->accel.cmd & 0x1000) || ((dev->accel.cmd & 8) && ibm8514_cpu_src(svga))) { + if ((dev->accel.cmd & 8) && ibm8514_cpu_src(svga)) { monoxfer = val; } else monoxfer = nibble; - ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, dev, len); + ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, svga, len); if (dev->accel.nibbleset != NULL) { free(dev->accel.nibbleset); dev->accel.nibbleset = NULL; @@ -383,7 +384,7 @@ regular_nibble: for (int i = 0; i < dev->accel.x_count; i++) { dev->accel.writemono[i] &= ~dev->accel.nibbleset[i]; dev->accel.writemono[i] |= dev->accel.nibbleset[i + 1]; - ibm8514_accel_start(pixcnt, 1, dev->accel.writemono[i], pixelxfer, dev, len); + ibm8514_accel_start(pixcnt, 1, dev->accel.writemono[i], pixelxfer, svga, len); } dev->accel.x_count = 0; @@ -403,14 +404,16 @@ regular_nibble: } else { pixelxfer = val; } - ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, dev, len); + ibm8514_accel_start(pixcnt, 1, monoxfer, pixelxfer, svga, len); } } } static void -ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) +ibm8514_accel_out_fifo(svga_t *svga, uint16_t port, uint32_t val, int len) { + ibm8514_t *dev = &svga->dev8514; + switch (port) { case 0x82e8: case 0xc2e8: @@ -527,7 +530,7 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) dev->accel.cmd = val; if (dev->accel.cmd & 0x100) dev->accel.cmd_back = 0; - ibm8514_accel_start(-1, 0, -1, 0, dev, len); + ibm8514_accel_start(-1, 0, -1, 0, svga, len); } break; case 0x9ae9: @@ -540,7 +543,7 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) if (dev->accel.cmd & 0x100) dev->accel.cmd_back = 0; } - ibm8514_accel_start(-1, 0, -1, 0, dev, len); + ibm8514_accel_start(-1, 0, -1, 0, svga, len); } break; @@ -557,12 +560,13 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) dev->accel.cx |= ~0x3ff; if (dev->accel.cur_y & 0x400) dev->accel.cy |= ~0x3ff; + if (dev->accel.cmd & 0x1000) { - ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke & 0xff, len); - ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke >> 8, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); } else { - ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke >> 8, len); - ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke & 0xff, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); } } break; @@ -578,11 +582,11 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) dev->accel.cy |= ~0x3ff; if (dev->accel.cmd & 0x1000) { - ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke & 0xff, len); - ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke >> 8, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); } else { - ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke >> 8, len); - ibm8514_short_stroke_start(-1, 0, -1, 0, dev, dev->accel.short_stroke & 0xff, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke >> 8, len); + ibm8514_short_stroke_start(-1, 0, -1, 0, svga, dev->accel.short_stroke & 0xff, len); } } break; @@ -596,9 +600,9 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) else dev->accel.bkgd_color = val; } else { - if (ibm8514_cpu_dest(dev)) + if (ibm8514_cpu_dest(svga)) break; - ibm8514_accel_out_pixtrans(dev, port, val, len); + ibm8514_accel_out_pixtrans(svga, port, val, len); } } else { if (len == 1) @@ -622,9 +626,9 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) else dev->accel.frgd_color = val; } else { - if (ibm8514_cpu_dest(dev)) + if (ibm8514_cpu_dest(svga)) break; - ibm8514_accel_out_pixtrans(dev, port, val, len); + ibm8514_accel_out_pixtrans(svga, port, val, len); } } else { if (len == 1) @@ -721,47 +725,21 @@ ibm8514_accel_out_fifo(ibm8514_t *dev, uint16_t port, uint32_t val, int len) } } -static void +void ibm8514_ramdac_out(uint16_t port, uint8_t val, void *p) { svga_t *svga = (svga_t *) p; - switch (port) { - case 0x2ea: - svga_out(0x3c6, val, svga); - break; - case 0x2eb: - svga_out(0x3c7, val, svga); - break; - case 0x2ec: - svga_out(0x3c8, val, svga); - break; - case 0x2ed: - svga_out(0x3c9, val, svga); - break; - } + svga_out(port, val, svga); } -static uint8_t +uint8_t ibm8514_ramdac_in(uint16_t port, void *p) { svga_t *svga = (svga_t *) p; - uint8_t ret = 0xff; + uint8_t ret; - switch (port) { - case 0x2ea: - ret = svga_in(0x3c6, svga); - break; - case 0x2eb: - ret = svga_in(0x3c7, svga); - break; - case 0x2ec: - ret = svga_in(0x3c8, svga); - break; - case 0x2ed: - ret = svga_in(0x3c9, svga); - break; - } + ret = svga_in(port, svga); return ret; } @@ -827,7 +805,7 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) ibm8514_t *dev = &svga->dev8514; if (port & 0x8000) { - ibm8514_accel_out_fifo(dev, port, val, len); + ibm8514_accel_out_fifo(svga, port, val, len); } else { switch (port) { case 0x2e8: @@ -938,10 +916,12 @@ ibm8514_accel_out(uint16_t port, uint32_t val, svga_t *svga, int len) break; case 0x4ae8: + if (!val) + break; dev->accel.advfunc_cntl = val & 7; - vga_on = ((dev->accel.advfunc_cntl & 1) == 0) ? 1 : 0; - ibm8514_on = !vga_on; - // pclog("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); + ibm8514_on = (dev->accel.advfunc_cntl & 1); + vga_on = !ibm8514_on; + //pclog("IBM 8514/A: VGA ON = %i, val = %02x\n", vga_on, val); svga_recalctimings(svga); break; } @@ -968,8 +948,22 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) ibm8514_t *dev = &svga->dev8514; uint32_t temp = 0; int cmd; + int vpos = dev->displine + svga->y_add; + int vblankend = svga->vblankstart + svga->crtc[0x16]; switch (port) { + case 0x2e8: + vpos = dev->displine + svga->y_add; + if (vblankend > dev->vtotal) { + vblankend -= dev->vtotal; + if (vpos >= svga->vblankstart || vpos <= vblankend) + temp |= 2; + } else { + if (vpos >= svga->vblankstart && vpos <= vblankend) + temp |= 2; + } + break; + case 0x6e8: temp = dev->hdisp; break; @@ -994,6 +988,15 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) break; case 0x42e8: + vpos = dev->displine + svga->y_add; + if (vblankend > dev->vtotal) { + vblankend -= dev->vtotal; + if (vpos >= svga->vblankstart || vpos <= vblankend) + dev->subsys_stat |= 1; + } else { + if (vpos >= svga->vblankstart && vpos <= vblankend) + dev->subsys_stat |= 1; + } if (len != 1) { temp = dev->subsys_stat | 0xa0 | 0x8000; } else @@ -1013,7 +1016,6 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) case 0x9ae8: case 0xdae8: - temp = 0; if (len != 1) { if (dev->force_busy) temp |= 0x200; /*Hardware busy*/ @@ -1026,7 +1028,6 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) break; case 0x9ae9: case 0xdae9: - temp = 0; if (len == 1) { if (dev->force_busy2) temp |= 2; /*Hardware busy*/ @@ -1040,7 +1041,7 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) case 0xe2e8: case 0xe6e8: - if (ibm8514_cpu_dest(dev)) { + if (ibm8514_cpu_dest(svga)) { if (len == 1) { ; // READ_PIXTRANS_BYTE_IO(0) } else { @@ -1051,15 +1052,15 @@ ibm8514_accel_in(uint16_t port, svga_t *svga, int len) temp |= (dev->vram[(dev->accel.newdest_in + dev->accel.cur_x) & dev->vram_mask] << 8); } } - ibm8514_accel_out_pixtrans(dev, port, temp, len); + ibm8514_accel_out_pixtrans(svga, port, temp, len); } break; case 0xe2e9: case 0xe6e9: - if (ibm8514_cpu_dest(dev)) { + if (ibm8514_cpu_dest(svga)) { if (len == 1) { ; // READ_PIXTRANS_BYTE_IO(1) - ibm8514_accel_out_pixtrans(dev, port, temp, len); + ibm8514_accel_out_pixtrans(svga, port, temp, len); } } break; @@ -1081,25 +1082,28 @@ ibm8514_accel_inw(uint16_t port, void *p) return ibm8514_accel_in(port, svga, 2); } -static void -ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, uint8_t ssv, int len) +void +ibm8514_short_stroke_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, uint8_t ssv, int len) { + ibm8514_t *dev = &svga->dev8514; + if (!cpu_input) { dev->accel.ssv_len = ssv & 0x0f; dev->accel.ssv_dir = ssv & 0xe0; dev->accel.ssv_draw = ssv & 0x10; - if (ibm8514_cpu_src(dev)) { + if (ibm8514_cpu_src(svga)) { return; /*Wait for data from CPU*/ } } - ibm8514_accel_start(count, cpu_input, mix_dat, cpu_dat, dev, len); + ibm8514_accel_start(count, cpu_input, mix_dat, cpu_dat, svga, len); } -static void -ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, ibm8514_t *dev, int len) +void +ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, svga_t *svga, int len) { + ibm8514_t *dev = &svga->dev8514; uint8_t src_dat = 0, dest_dat, old_dest_dat; int frgd_mix, bkgd_mix; uint16_t clip_b = dev->accel.multifunc[3] & 0x7ff; @@ -1145,75 +1149,75 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat mix_dat = 0; if (and3 == 3) { if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x10; - if (dev->accel.multifunc[8] & 0x04) mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x10; if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x04; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x02; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x01; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x80; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x40; - if (dev->accel.multifunc[9] & 0x10) mix_dat |= 0x20; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x02; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x04; } if (and3 == 2) { if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x20; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x10; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x08; - if (dev->accel.multifunc[8] & 0x10) mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x10; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x20; if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x02; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x01; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x80; - if (dev->accel.multifunc[9] & 0x10) mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x01; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x02; } if (and3 == 1) { if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x40; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x20; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x10; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x08; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x04; - if (dev->accel.multifunc[9] & 0x04) mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x08; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x40; if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x01; - if (dev->accel.multifunc[9] & 0x10) mix_dat |= 0x80; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x01; } if (and3 == 0) { if (dev->accel.multifunc[8] & 0x02) - mix_dat |= 0x80; - if (dev->accel.multifunc[8] & 0x04) - mix_dat |= 0x40; - if (dev->accel.multifunc[8] & 0x08) - mix_dat |= 0x20; - if (dev->accel.multifunc[8] & 0x10) - mix_dat |= 0x10; - if (dev->accel.multifunc[9] & 0x02) - mix_dat |= 0x08; - if (dev->accel.multifunc[9] & 0x04) - mix_dat |= 0x04; - if (dev->accel.multifunc[9] & 0x08) - mix_dat |= 0x02; - if (dev->accel.multifunc[9] & 0x10) mix_dat |= 0x01; + if (dev->accel.multifunc[8] & 0x04) + mix_dat |= 0x02; + if (dev->accel.multifunc[8] & 0x08) + mix_dat |= 0x04; + if (dev->accel.multifunc[8] & 0x10) + mix_dat |= 0x08; + if (dev->accel.multifunc[9] & 0x02) + mix_dat |= 0x10; + if (dev->accel.multifunc[9] & 0x04) + mix_dat |= 0x20; + if (dev->accel.multifunc[9] & 0x08) + mix_dat |= 0x40; + if (dev->accel.multifunc[9] & 0x10) + mix_dat |= 0x80; } } @@ -1244,13 +1248,13 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat src_dat = 0; break; } - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { MIX(mix_dat & mix_mask, dest_dat, src_dat); if (dev->accel.ssv_draw) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } @@ -1316,7 +1320,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->accel.sy = dev->accel.maj_axis_pcnt; - if (ibm8514_cpu_src(dev)) { + if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 2) { if (dev->accel.cmd & 8) { if (and3 == 1) { @@ -1349,7 +1353,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ - } else if (ibm8514_cpu_dest(dev)) { + } else if (ibm8514_cpu_dest(svga)) { dev->data_available = 1; dev->data_available2 = 1; return; @@ -1357,22 +1361,22 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } if (dev->accel.cmd & 8) { /*Vector Line*/ - if (ibm8514_cpu_dest(dev) && cpu_input && (dev->accel.cmd & 2)) + if (ibm8514_cpu_dest(svga) && cpu_input && (dev->accel.cmd & 2)) count >>= 1; dev->accel.xx_count++; while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { - if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { /* Mix data = current video memory value. */ - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, mix_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); mix_dat = mix_dat ? mix_mask : 0; } - if (ibm8514_cpu_dest(dev)) { - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, src_dat); + if (ibm8514_cpu_dest(svga)) { + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); if (pixcntl == 3) src_dat = ((src_dat & rd_mask) == rd_mask); } else @@ -1391,76 +1395,76 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat break; } - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); - if ((dev->accel.cmd & 2) && ibm8514_cpu_src(dev)) { + if ((dev->accel.cmd & 2) && ibm8514_cpu_src(svga)) { if (and3 == 1) { if (dev->accel.xx_count >= 2) { if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } else if (and3 == 2) { if (dev->accel.xx_count == 2) { if (count <= 2) { if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } else if (dev->accel.xx_count >= 3) { if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } else if (and3 == 3) { if (dev->accel.xx_count == 2) { if (count <= 1) { if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } else if (dev->accel.xx_count >= 3) { if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } else { if (dev->accel.xx_count == 1) { if (!count) { if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } else if (dev->accel.xx_count >= 2) { if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } } else { - if (ibm8514_cpu_src(dev) || !cpu_input) { + if (ibm8514_cpu_src(svga) || !cpu_input) { if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } @@ -1519,8 +1523,8 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat mix_dat = old_mix_dat; } if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { - if (ibm8514_cpu_dest(dev)) { - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, src_dat); + if (ibm8514_cpu_dest(svga)) { + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); } else switch ((mix_dat & 1) ? frgd_mix : bkgd_mix) { case 0: @@ -1537,16 +1541,16 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat break; } - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; MIX(mix_dat & 1, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } @@ -1624,17 +1628,17 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat } else { while (count-- && (dev->accel.sy >= 0)) { if (((dev->accel.cx) >= dev->accel.clip_left && (dev->accel.cx) <= clip_r && (dev->accel.cy) >= dev->accel.clip_top && (dev->accel.cy) <= clip_b)) { - if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { /* Mix data = current video memory value. */ - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, mix_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); mix_dat = mix_dat ? mix_mask : 0; } - if (ibm8514_cpu_dest(dev)) { - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, src_dat); + if (ibm8514_cpu_dest(svga)) { + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, src_dat); if (pixcntl == 3) src_dat = ((src_dat & rd_mask) == rd_mask); } else @@ -1653,16 +1657,16 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat break; } - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; MIX(mix_dat & mix_mask, dest_dat, src_dat); dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); if ((dev->accel.cmd & 4) && dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } else if (!(dev->accel.cmd & 4)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); } } } @@ -1766,7 +1770,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.cur_y & 0x400) dev->accel.cy |= ~0x3ff; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.fill_state = 0; if (cmd == 4) @@ -1774,7 +1778,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat else if (cmd == 3) dev->accel.cmd &= ~2; - if (ibm8514_cpu_src(dev)) { + if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 2) { if (!(dev->accel.cmd & 0x1000)) { if (!(dev->accel.cmd & 8)) { @@ -1814,18 +1818,18 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (!(dev->accel.cmd & 0x40) && (frgd_mix == 2) && (bkgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { if (!(dev->accel.sx & 1)) { dev->accel.output = 1; - dev->accel.newdest_out = (dev->accel.cy + 1) * dev->h_disp; + dev->accel.newdest_out = (dev->accel.cy + 1) * dev->pitch; } } } dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ - } else if (ibm8514_cpu_dest(dev)) { + } else if (ibm8514_cpu_dest(svga)) { if (!(dev->accel.cmd & 2) && (frgd_mix == 2) && (pixcntl == 0) && (cmd == 2)) { if (!(dev->accel.sx & 1)) { dev->accel.input = 1; - dev->accel.newdest_in = (dev->accel.cy + 1) * dev->h_disp; + dev->accel.newdest_in = (dev->accel.cy + 1) * dev->pitch; } } else if (dev->accel.cmd & 2) { if (dev->accel.cmd & 8) { @@ -1844,7 +1848,7 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat if (dev->accel.cmd & 2) { if (cpu_input) { rect_fill_pix: - if ((dev->accel.cmd & 8) && ibm8514_cpu_src(dev)) { + if ((dev->accel.cmd & 8) && ibm8514_cpu_src(svga)) { dev->accel.xx_count++; while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { @@ -1993,7 +1997,7 @@ rect_fill_pix: break; } - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; return; } @@ -2003,16 +2007,16 @@ rect_fill_pix: if (count < 8) { while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { - if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { /* Mix data = current video memory value. */ READ(dev->accel.dest + dev->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); mix_dat = mix_dat ? mix_mask : 0; } - if (ibm8514_cpu_dest(dev)) { + if (ibm8514_cpu_dest(svga)) { READ(dev->accel.dest + dev->accel.cx, src_dat); if (pixcntl == 3) src_dat = ((src_dat & rd_mask) == rd_mask); @@ -2069,7 +2073,7 @@ rect_fill_pix: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; return; } @@ -2077,16 +2081,16 @@ rect_fill_pix: } else { while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { - if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = 1; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { /* Mix data = current video memory value. */ READ(dev->accel.dest + dev->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); mix_dat = mix_dat ? 1 : 0; } - if (ibm8514_cpu_dest(dev)) { + if (ibm8514_cpu_dest(svga)) { READ(dev->accel.dest + dev->accel.cx, src_dat); if (pixcntl == 3) src_dat = ((src_dat & rd_mask) == rd_mask); @@ -2151,7 +2155,7 @@ rect_fill_pix: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; return; } @@ -2205,8 +2209,8 @@ rect_fill_pix: dev->accel.cy++; else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; - dev->accel.newdest_in = (dev->accel.cy + 1) * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.newdest_in = (dev->accel.cy + 1) * dev->pitch; dev->accel.sy--; return; } @@ -2224,8 +2228,8 @@ rect_fill_pix: dev->accel.cy++; else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; - dev->accel.newdest_in = (dev->accel.cy + 1) * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.newdest_in = (dev->accel.cy + 1) * dev->pitch; dev->accel.sy--; return; } @@ -2272,8 +2276,8 @@ rect_fill_pix: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; - dev->accel.newdest_out = (dev->accel.cy + 1) * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.newdest_out = (dev->accel.cy + 1) * dev->pitch; dev->accel.sy--; return; } @@ -2292,8 +2296,8 @@ rect_fill_pix: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; - dev->accel.newdest_out = (dev->accel.cy + 1) * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; + dev->accel.newdest_out = (dev->accel.cy + 1) * dev->pitch; dev->accel.sy--; return; } @@ -2302,16 +2306,16 @@ rect_fill_pix: } else { while (count-- && (dev->accel.sy >= 0)) { if ((dev->accel.cx >= dev->accel.clip_left && dev->accel.cx <= clip_r && dev->accel.cy >= dev->accel.clip_top && dev->accel.cy <= clip_b)) { - if (ibm8514_cpu_dest(dev) && (pixcntl == 0)) { + if (ibm8514_cpu_dest(svga) && (pixcntl == 0)) { mix_dat = mix_mask; /* Mix data = forced to foreground register. */ - } else if (ibm8514_cpu_dest(dev) && (pixcntl == 3)) { + } else if (ibm8514_cpu_dest(svga) && (pixcntl == 3)) { /* Mix data = current video memory value. */ READ(dev->accel.dest + dev->accel.cx, mix_dat); mix_dat = ((mix_dat & rd_mask) == rd_mask); mix_dat = mix_dat ? mix_mask : 0; } - if (ibm8514_cpu_dest(dev)) { + if (ibm8514_cpu_dest(svga)) { READ(dev->accel.dest + dev->accel.cx, src_dat); if (pixcntl == 3) { src_dat = ((src_dat & rd_mask) == rd_mask); @@ -2336,7 +2340,7 @@ rect_fill_pix: if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; - if (ibm8514_cpu_dest(dev)) { + if (ibm8514_cpu_dest(svga)) { if (pixcntl == 3) { MIX(mix_dat & mix_mask, dest_dat, src_dat); } @@ -2371,7 +2375,7 @@ rect_fill_pix: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; return; } @@ -2441,7 +2445,7 @@ rect_fill: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; dev->accel.cur_x = dev->accel.cx; @@ -2505,7 +2509,7 @@ rect_fill: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; if (dev->accel.sy < 0) { @@ -2583,7 +2587,7 @@ rect_fill: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; if (dev->accel.sy < 0) { @@ -2643,7 +2647,7 @@ rect_fill: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; if (dev->accel.sy < 0) { @@ -2665,16 +2669,13 @@ rect_fill: dev->accel.cy = dev->accel.cur_y; dev->accel.oldcy = dev->accel.cy; - dev->accel.xdir = (dev->accel.cmd & 0x20) ? 1 : -1; - dev->accel.ydir = (dev->accel.cmd & 0x80) ? 1 : -1; - dev->accel.sy = 0; - if (ibm8514_cpu_src(dev)) { + if (ibm8514_cpu_src(svga)) { dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ - } else if (ibm8514_cpu_dest(dev)) { + } else if (ibm8514_cpu_dest(svga)) { dev->data_available = 1; dev->data_available2 = 1; return; @@ -2682,7 +2683,10 @@ rect_fill: } while (count-- && (dev->accel.sy >= 0)) { - if (((dev->accel.cx) >= dev->accel.clip_left && (dev->accel.cx <= clip_r) && (dev->accel.cy) >= dev->accel.clip_top && (dev->accel.cy) <= clip_b)) { + if (dev->accel.cur_x > 1023) + dev->accel.cx = 0; + + if (((dev->accel.cx) >= dev->accel.clip_left && ((dev->accel.cx) <= clip_r) && (dev->accel.cy) >= dev->accel.clip_top && (dev->accel.cy) <= clip_b)) { switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix) { case 0: src_dat = bkgd_color; @@ -2698,7 +2702,7 @@ rect_fill: break; } - READ((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + READ((dev->accel.cy * dev->pitch) + dev->accel.cx, dest_dat); if ((compare_mode == 0) || ((compare_mode == 0x10) && (dest_dat >= compare)) || ((compare_mode == 0x18) && (dest_dat < compare)) || ((compare_mode == 0x20) && (dest_dat != compare)) || ((compare_mode == 0x28) && (dest_dat == compare)) || ((compare_mode == 0x30) && (dest_dat <= compare)) || ((compare_mode == 0x38) && (dest_dat > compare))) { old_dest_dat = dest_dat; @@ -2706,11 +2710,11 @@ rect_fill: dest_dat = (dest_dat & wrt_mask) | (old_dest_dat & ~wrt_mask); if ((dev->accel.cmd & 4) && (dev->accel.sy < dev->accel.maj_axis_pcnt)) { if (!dev->accel.sy) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); - } else if ((dev->accel.cmd & 0x40) && dev->accel.sy && (dev->accel.cy == dev->accel.oldcy + 1)) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); + } else if ((dev->accel.cmd & 0x40) && dev->accel.sy && (dev->accel.cy == (dev->accel.oldcy + 1))) { + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); } else if (!(dev->accel.cmd & 0x40) && dev->accel.sy && (dev->accel.err_term >= 0) && (dev->accel.cy == (dev->accel.oldcy + 1))) { - WRITE((dev->accel.cy * dev->h_disp) + dev->accel.cx, dest_dat); + WRITE((dev->accel.cy * dev->pitch) + (dev->accel.cx), dest_dat); } } } @@ -2721,27 +2725,75 @@ rect_fill: cpu_dat >>= 8; if (dev->accel.sy == dev->accel.maj_axis_pcnt) { - return; + break; } - if (dev->accel.cmd & 0x40) { - dev->accel.oldcy = dev->accel.cy; - dev->accel.cy += dev->accel.ydir; - if (dev->accel.err_term >= 0) { - dev->accel.err_term += dev->accel.destx_distp; - dev->accel.cx += dev->accel.xdir; - } else { - dev->accel.err_term += dev->accel.desty_axstp; + if (dev->accel.err_term >= dev->accel.maj_axis_pcnt) { + dev->accel.err_term += dev->accel.destx_distp; + /*Step minor axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x20: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x40: + dev->accel.cx--; + break; + case 0x60: + dev->accel.cx++; + break; + case 0x80: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xa0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xc0: + dev->accel.cx--; + break; + case 0xe0: + dev->accel.cx++; + break; } - } else { - dev->accel.cx += dev->accel.xdir; - if (dev->accel.err_term >= 0) { - dev->accel.err_term += dev->accel.destx_distp; + } else + dev->accel.err_term += dev->accel.desty_axstp; + + /*Step major axis*/ + switch (dev->accel.cmd & 0xe0) { + case 0x00: + dev->accel.cx--; + break; + case 0x20: + dev->accel.cx++; + break; + case 0x40: dev->accel.oldcy = dev->accel.cy; - dev->accel.cy += dev->accel.ydir; - } else { - dev->accel.err_term += dev->accel.desty_axstp; - } + dev->accel.cy--; + break; + case 0x60: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy--; + break; + case 0x80: + dev->accel.cx--; + break; + case 0xa0: + dev->accel.cx++; + break; + case 0xc0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; + case 0xe0: + dev->accel.oldcy = dev->accel.cy; + dev->accel.cy++; + break; } dev->accel.sy++; @@ -2773,10 +2825,10 @@ rect_fill: if (dev->accel.cur_y & 0x400) dev->accel.cy |= ~0x3ff; - dev->accel.src = dev->accel.cy * dev->h_disp; - dev->accel.dest = dev->accel.dy * dev->h_disp; + dev->accel.src = dev->accel.cy * dev->pitch; + dev->accel.dest = dev->accel.dy * dev->pitch; - if (ibm8514_cpu_src(dev)) { + if (ibm8514_cpu_src(svga)) { if (dev->accel.cmd & 2) { if (!(dev->accel.cmd & 0x1000)) { dev->accel.sx += (dev->accel.cur_x & 3); @@ -2788,7 +2840,7 @@ rect_fill: dev->data_available = 0; dev->data_available2 = 0; return; /*Wait for data from CPU*/ - } else if (ibm8514_cpu_dest(dev)) { + } else if (ibm8514_cpu_dest(svga)) { dev->data_available = 1; dev->data_available2 = 1; return; /*Wait for data from CPU*/ @@ -2869,7 +2921,7 @@ bitblt_pix: else dev->accel.cy--; - dev->accel.dest = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.cy * dev->pitch; dev->accel.sy--; return; } @@ -2964,8 +3016,8 @@ bitblt_pix: dev->accel.cy--; } - dev->accel.dest = dev->accel.dy * dev->h_disp; - dev->accel.src = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.sy--; return; } @@ -3053,8 +3105,8 @@ bitblt_pix: dev->accel.cy--; } - dev->accel.dest = dev->accel.dy * dev->h_disp; - dev->accel.src = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.sy--; return; } @@ -3132,8 +3184,8 @@ bitblt: dev->accel.cy--; } - dev->accel.dest = dev->accel.dy * dev->h_disp; - dev->accel.src = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.sy--; return; } @@ -3202,8 +3254,8 @@ bitblt: dev->accel.cy--; } - dev->accel.dest = dev->accel.dy * dev->h_disp; - dev->accel.src = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.sy--; if (dev->accel.sy < 0) { @@ -3287,8 +3339,8 @@ bitblt: dev->accel.cy--; } - dev->accel.dest = dev->accel.dy * dev->h_disp; - dev->accel.src = dev->accel.cy * dev->h_disp; + dev->accel.dest = dev->accel.dy * dev->pitch; + dev->accel.src = dev->accel.cy * dev->pitch; dev->accel.sy--; if (dev->accel.sy < 0) { @@ -3393,7 +3445,7 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) video_wait_for_buffer(); } - ibm8514_render_8bpp(svga); + svga->render(svga); svga->x_add = (overscan_x >> 1); ibm8514_render_overscan_left(dev, svga); @@ -3416,16 +3468,13 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) dev->linepos = 0; if (dev->dispon) { if (dev->sc == dev->rowcount) { - dev->linecountff = 0; dev->sc = 0; - dev->maback += (dev->rowoffset << 3); if (dev->interlace) dev->maback += (dev->rowoffset << 3); dev->maback &= dev->vram_mask; dev->ma = dev->maback; } else { - dev->linecountff = 0; dev->sc++; dev->sc &= 31; dev->ma = dev->maback; @@ -3471,7 +3520,7 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) changeframecount = dev->interlace ? 3 : 2; if (dev->interlace && dev->oddeven) - dev->ma = dev->maback = 0 + (dev->rowoffset << 1); + dev->ma = dev->maback = (dev->rowoffset << 1); else dev->ma = dev->maback = 0; @@ -3485,8 +3534,6 @@ ibm8514_poll(ibm8514_t *dev, svga_t *svga) dev->displine = (dev->interlace && dev->oddeven) ? 1 : 0; svga->x_add = (overscan_x >> 1); - - dev->linecountff = 0; } } } @@ -3496,42 +3543,104 @@ ibm8514_recalctimings(svga_t *svga) { ibm8514_t *dev = &svga->dev8514; - dev->h_disp_time = dev->h_disp = (dev->hdisp + 1) << 3; - dev->rowoffset = (dev->hdisp + 1); - dev->h_total = (dev->htotal + 1); - dev->v_total = (dev->vtotal + 1); - dev->v_syncstart = (dev->vsyncstart + 1); - dev->rowcount = !!(dev->disp_cntl & 0x08); - - if (dev->accel.advfunc_cntl & 4) { - if (dev->hdisp == 0) { - dev->rowoffset = 128; - dev->h_disp = 1024; - } - - if (dev->vtotal == 0) - dev->v_total = 1632; - - if (dev->vsyncstart == 0) - dev->v_syncstart = 1536; - - if (dev->interlace) { - dev->dispend = 384; /*Interlaced*/ - dev->v_total >>= 2; - dev->v_syncstart >>= 2; - } else { + if (ibm8514_on) { + dev->h_disp = (dev->hdisp + 1) << 3; + dev->pitch = dev->h_disp; + dev->h_total = (dev->htotal + 1); + dev->v_total = (dev->vtotal + 1); + dev->v_syncstart = (dev->vsyncstart + 1); + dev->rowcount = !!(dev->disp_cntl & 0x08); + dev->dispend = ((dev->vdisp >> 1) + 1); + if (dev->dispend == 766) dev->dispend = 768; - dev->v_total >>= 1; - dev->v_syncstart >>= 1; + //pclog("HDISP = %d, VTOTAL = %d, DISPEND = %d, hires = %02x\n", dev->h_disp, dev->v_total, dev->dispend, dev->accel.advfunc_cntl & 4); + { +#if 0 + if (dev->dispend == 480) { + dev->h_disp = 640; + dev->rowoffset = 128; + dev->pitch = 1024; + } else if ((dev->dispend == 600) || (dev->dispend == 598)) { + dev->h_disp = 800; + dev->rowoffset = 128; + dev->dispend = 600; + dev->pitch = 1024; + if (!dev->vtotal) + dev->v_total = 816; + if (!dev->vsyncstart) + dev->v_syncstart = dev->dispend; + } else { + if (dev->accel.advfunc_cntl & 4) { + if (!dev->hdisp) { + dev->rowoffset = 128; + dev->h_disp = 1024; + dev->pitch = dev->h_disp; + } + if (!dev->vtotal) + dev->v_total = 816; + if (!dev->vsyncstart) + dev->v_syncstart = dev->dispend; + } else { + dev->rowoffset = 128; + dev->h_disp = 640; + dev->dispend = 480; + dev->pitch = 1024; + if (!dev->vtotal) + dev->v_total = 816; + if (!dev->vsyncstart) + dev->v_syncstart = dev->dispend; + } + } +#endif } - // pclog("1024x768 clock mode, hdisp = %d, htotal = %d, vtotal = %d, vsyncstart = %d, interlace = %02x\n", dev->h_disp, dev->h_total, dev->v_total, dev->v_syncstart, dev->interlace); - svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0; - } else { - // pclog("640x480 clock mode\n"); - dev->dispend = 480; - dev->v_total >>= 1; - dev->v_syncstart >>= 1; - svga->clock = (cpuclock * (double) (1ull << 32)) / 25175000.0; + + if (dev->accel.advfunc_cntl & 4) { + if (!vga_on && dev->ibm_mode) { + if (dev->h_disp == 8) { + dev->h_disp = 1024; + dev->dispend = 768; + dev->v_total = 1536; + dev->v_syncstart = 1536; + } + } + + if (dev->dispend == 598) + dev->dispend = 600; + + if (dev->interlace) { + dev->dispend >>= 1; + dev->v_syncstart >>= 2; + dev->v_total >>= 2; + } else { + dev->v_syncstart >>= 1; + dev->v_total >>= 1; + } + dev->rowoffset = 0x80; + dev->pitch = 1024; + + // pclog("1024x768 clock mode, hdisp = %d, htotal = %d, vtotal = %d, vsyncstart = %d, interlace = %02x\n", dev->h_disp, dev->h_total, dev->v_total, dev->v_syncstart, dev->interlace); + svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0; + } else { + if (!vga_on && dev->ibm_mode) { + dev->h_disp = 640; + dev->dispend = 480; + } + + if (dev->interlace) { + dev->dispend >>= 1; + dev->v_syncstart >>= 2; + dev->v_total >>= 2; + } else { + dev->v_syncstart >>= 1; + dev->v_total >>= 1; + } + dev->rowoffset = 0x80; + dev->pitch = 1024; + + svga->clock = (cpuclock * (double) (1ull << 32)) / 25175000.0; + } + svga->render = ibm8514_render_8bpp; + //pclog("Pitch = %d, mode = %d.\n", dev->pitch, dev->ibm_mode); } // pclog("8514 enabled, hdisp=%d, vtotal=%d, htotal=%d, dispend=%d, rowoffset=%d, split=%d, vsyncstart=%d, split=%08x\n", dev->hdisp, dev->vtotal, dev->htotal, dev->dispend, dev->rowoffset, dev->split, dev->vsyncstart, dev->split); } @@ -3572,6 +3681,9 @@ static void * ibm8514_init(const device_t *info) { + if (svga_get_pri() == NULL) + return NULL; + svga_t *svga = svga_get_pri(); ibm8514_t *dev = &svga->dev8514; @@ -3582,6 +3694,7 @@ static void dev->map8 = svga->pallook; dev->type = info->flags; + dev->ibm_mode = 1; ibm8514_io_set(svga); From 3ed7c4da7661620b5b1e312be835f1509aeb15e3 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 6 May 2023 00:08:21 +0600 Subject: [PATCH 18/34] usb: interrupt setting function (OHCI) --- src/usb.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/usb.c b/src/usb.c index 12385c808..0951412d6 100644 --- a/src/usb.c +++ b/src/usb.c @@ -258,6 +258,22 @@ ohci_port_reset_callback_2(void* priv) dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] |= 0x10; } +void +ohci_set_interrupt(usb_t* usb, uint8_t bit) +{ + if (!(usb->ohci_mmio[OHCI_HcInterruptEnable + 3] & 0x80)) + return; + + if (!(usb->ohci_mmio[OHCI_HcInterruptEnable] & bit)) + return; + + if (usb->ohci_mmio[OHCI_HcInterruptDisable] & bit) + return; + + usb->ohci_mmio[OHCI_HcInterruptStatus] |= bit; + usb_interrupt_ohci(usb); +} + static void ohci_mmio_write(uint32_t addr, uint8_t val, void *p) { From d6ff34208ce71e1eda7111dee56a3655d3e095da Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 6 May 2023 15:35:03 +0600 Subject: [PATCH 19/34] usb: Hook up USB interrupts to rest of the chipsets --- src/chipset/ali1543.c | 21 ++++++++++++++++++++- src/chipset/intel_piix.c | 17 +++++++++++++++-- src/chipset/stpc.c | 20 ++++++++++++++++++-- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index b587f91b5..6d03b3a12 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -59,6 +59,7 @@ typedef struct ali1543_t { sff8038i_t *ide_controller[2]; smbus_ali7101_t *smbus; usb_t *usb; + usb_params_t usb_params; } ali1543_t; @@ -905,7 +906,11 @@ ali5237_write(int func, int addr, uint8_t val, void *priv) case 0x0c: /* Cache Line Size */ case 0x0d: /* Latency Timer */ + break; + case 0x3c: /* Interrupt Line Register */ + dev->usb_conf[addr] = val; + break; case 0x42: /* Test Mode Register */ dev->usb_conf[addr] = val & 0x10; @@ -1424,6 +1429,17 @@ ali7101_read(int func, int addr, void *priv) return ret; } +static void +ali5237_usb_raise_interrupt(void *priv) +{ + ali1543_t *dev = (ali1543_t *) priv; + + if (!dev->usb_dev_enable) + return; + + pci_set_irq(dev->usb_slot, PCI_INTA); +} + static void ali1543_reset(void *priv) { @@ -1574,7 +1590,10 @@ ali1543_init(const device_t *info) dev->smbus = device_add(&ali7101_smbus_device); /* USB */ - dev->usb = device_add(&usb_device); + dev->usb_params.parent_priv = dev; + dev->usb_params.smi_handle = NULL; + dev->usb_params.raise_interrupt = ali5237_usb_raise_interrupt; + dev->usb = device_add_parameters(&usb_device, &dev->usb_params); dev->type = info->local & 0xff; dev->offset = (info->local >> 8) & 0x7f; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index 718df8344..c6cfe8c9f 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -77,6 +77,7 @@ typedef struct _piix_ { piix_io_trap_t io_traps[26]; port_92_t *port_92; pc_timer_t fast_off_timer; + usb_params_t usb_params; } piix_t; #ifdef ENABLE_PIIX_LOG @@ -1425,6 +1426,14 @@ piix_fast_off_count(void *priv) dev->regs[0][0xaa] |= 0x20; } +static void +piix_usb_raise_interrupt(usb_t* usb, void *priv) +{ + piix_t *dev = (piix_t *) priv; + + pci_set_irq(dev->pci_slot, PCI_INTD); +} + static void piix_reset(void *p) { @@ -1569,8 +1578,12 @@ piix_init(const device_t *info) sff_set_irq_mode(dev->bm[1], 1, 2); } - if (dev->type >= 3) - dev->usb = device_add(&usb_device); + if (dev->type >= 3) { + dev->usb_params.parent_priv = dev; + dev->usb_params.smi_handle = NULL; + dev->usb_params.raise_interrupt = piix_usb_raise_interrupt; + dev->usb = device_add_parameters(&usb_device, &dev->usb_params); + } if (dev->type > 3) { dev->nvr = device_add(&piix4_nvr_device); diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index cd13af3f0..84720f802 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -65,7 +65,11 @@ typedef struct stpc_t { smram_t *smram; usb_t *usb; int ide_slot; + int usb_slot; sff8038i_t *bm[2]; + + /* Miscellaneous */ + usb_params_t usb_params; } stpc_t; typedef struct stpc_serial_t { @@ -870,6 +874,14 @@ stpc_setup(stpc_t *dev) pci_set_irq_routing(PCI_INTD, PCI_IRQ_DISABLED); } +static void +stpc_usb_raise_interrupt(usb_t* usb, void* priv) +{ + stpc_t *dev = (stpc_t *) priv; + + pci_set_irq(dev->usb_slot, PCI_INTA); +} + static void stpc_close(void *priv) { @@ -895,9 +907,13 @@ stpc_init(const device_t *info) pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev); dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev); if (dev->local == STPC_ATLAS) { + dev->usb_params.smi_handle = NULL; + dev->usb_params.raise_interrupt = stpc_usb_raise_interrupt; + dev->usb_params.parent_priv = dev; + dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_ide_read, stpc_ide_write, dev); - dev->usb = device_add(&usb_device); - pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_usb_read, stpc_usb_write, dev); + dev->usb = device_add_parameters(&usb_device, &dev->usb_params); + dev->usb_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_usb_read, stpc_usb_write, dev); } dev->bm[0] = device_add_inst(&sff8038i_device, 1); From aa02968c46bd9ed405e89a0d2351f3cb88e796aa Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 6 May 2023 16:08:33 +0600 Subject: [PATCH 20/34] usb: Device reset pointer member --- src/include/86box/usb.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index ecb5c0f86..39ddf9cf6 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -82,6 +82,8 @@ typedef struct uint8_t (*device_out)(void* priv, uint8_t* data, uint32_t len); /* Process setup packets. */ uint8_t (*device_setup)(void* priv, uint8_t* data); + /* Device reset */ + void (*device_reset)(void* priv); void* priv; } usb_device_t; From 41f26b57c2409a9827300a7d064f218309d46582 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sat, 6 May 2023 23:19:55 +0600 Subject: [PATCH 21/34] usb: Start work on SOF generation and frame counting --- src/include/86box/usb.h | 8 +++++++- src/usb.c | 44 ++++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index 39ddf9cf6..af1922570 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -36,7 +36,13 @@ typedef struct /* USB Host Controller device struct */ typedef struct usb_t { - uint8_t uhci_io[32], ohci_mmio[4096]; + union + { + uint8_t ohci_mmio[4096]; + uint16_t ohci_mmio_w[2048]; + uint32_t ohci_mmio_l[1024]; + }; + uint8_t uhci_io[32]; uint16_t uhci_io_base; int uhci_enable, ohci_enable; uint32_t ohci_mem_base; diff --git a/src/usb.c b/src/usb.c index 0951412d6..3310c0786 100644 --- a/src/usb.c +++ b/src/usb.c @@ -63,7 +63,7 @@ enum OHCI_HcBulkHeadED = 0x28, OHCI_HcBulkCurrentED = 0x2C, OHCI_HcDoneHead = 0x30, - OHCI_HcFMInterval = 0x34, + OHCI_HcFmInterval = 0x34, OHCI_HcFmRemaining = 0x38, OHCI_HcFmNumber = 0x3C, OHCI_HcPeriodicStart = 0x40, @@ -223,10 +223,35 @@ ohci_mmio_read(uint32_t addr, void *p) return ret; } +void +ohci_set_interrupt(usb_t* usb, uint8_t bit) +{ + if (!(usb->ohci_mmio[OHCI_HcInterruptEnable + 3] & 0x80)) + return; + + if (!(usb->ohci_mmio[OHCI_HcInterruptEnable] & bit)) + return; + + if (usb->ohci_mmio[OHCI_HcInterruptDisable] & bit) + return; + + usb->ohci_mmio[OHCI_HcInterruptStatus] |= bit; + usb_interrupt_ohci(usb); +} + void ohci_update_frame_counter(void* priv) { usb_t *dev = (usb_t *) priv; + + dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] &= 0x3fff; + if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] == 0) { + dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] = dev->ohci_mmio_w[OHCI_HcFmInterval / 2] & 0x3fff; + dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] &= ~(1 << 31); + dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] |= dev->ohci_mmio_l[OHCI_HcFmInterval / 4] & (1 << 31); + ohci_set_interrupt(dev, OHCI_HcInterruptEnable_SO); + } + if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]) dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]--; } void @@ -257,23 +282,6 @@ ohci_port_reset_callback_2(void* priv) dev->ohci_mmio[OHCI_HcRhPortStatus2] &= ~0x10; dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] |= 0x10; } - -void -ohci_set_interrupt(usb_t* usb, uint8_t bit) -{ - if (!(usb->ohci_mmio[OHCI_HcInterruptEnable + 3] & 0x80)) - return; - - if (!(usb->ohci_mmio[OHCI_HcInterruptEnable] & bit)) - return; - - if (usb->ohci_mmio[OHCI_HcInterruptDisable] & bit) - return; - - usb->ohci_mmio[OHCI_HcInterruptStatus] |= bit; - usb_interrupt_ohci(usb); -} - static void ohci_mmio_write(uint32_t addr, uint8_t val, void *p) { From 04e440e608865dfb10c5061cd979ef81153fd5eb Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 7 May 2023 00:33:15 +0600 Subject: [PATCH 22/34] usb: Start implementing end-of-frame and start-of-frame signals --- src/usb.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/usb.c b/src/usb.c index 3310c0786..cde3ee4a9 100644 --- a/src/usb.c +++ b/src/usb.c @@ -239,6 +239,18 @@ ohci_set_interrupt(usb_t* usb, uint8_t bit) usb_interrupt_ohci(usb); } +void +ohci_end_of_frame(usb_t* dev) +{ + /* TODO: Put endpoint and transfer descriptor processing here. */ +} + +void +ohci_start_of_frame(usb_t* dev) +{ + ohci_set_interrupt(dev, OHCI_HcInterruptEnable_SO); +} + void ohci_update_frame_counter(void* priv) { @@ -246,12 +258,15 @@ ohci_update_frame_counter(void* priv) dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] &= 0x3fff; if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] == 0) { + ohci_end_of_frame(dev); dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] = dev->ohci_mmio_w[OHCI_HcFmInterval / 2] & 0x3fff; dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] &= ~(1 << 31); dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] |= dev->ohci_mmio_l[OHCI_HcFmInterval / 4] & (1 << 31); - ohci_set_interrupt(dev, OHCI_HcInterruptEnable_SO); + dev->ohci_mmio_w[OHCI_HcFmNumber / 2]++; + ohci_start_of_frame(dev); } if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]) dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]--; + timer_on_auto(&dev->ohci_frame_timer, 1. / (12. * 1000. * 1000.)); } void From 9e3f11d62e9d1ec5f920da3ae9ff0795c043b399 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 7 May 2023 00:35:38 +0600 Subject: [PATCH 23/34] ali1543: Fix wrong function signature --- src/chipset/ali1543.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 6d03b3a12..00146c90e 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -1430,7 +1430,7 @@ ali7101_read(int func, int addr, void *priv) } static void -ali5237_usb_raise_interrupt(void *priv) +ali5237_usb_raise_interrupt(usb_t* usb, void *priv) { ali1543_t *dev = (ali1543_t *) priv; From 81114030bddfeb9e4bc1745f6a91730387a193da Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 7 May 2023 01:05:35 +0600 Subject: [PATCH 24/34] usb: Increment HcFmNumber in EOF function --- src/usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/usb.c b/src/usb.c index cde3ee4a9..897f07bdc 100644 --- a/src/usb.c +++ b/src/usb.c @@ -243,6 +243,7 @@ void ohci_end_of_frame(usb_t* dev) { /* TODO: Put endpoint and transfer descriptor processing here. */ + dev->ohci_mmio_w[OHCI_HcFmNumber / 2]++; } void @@ -262,8 +263,9 @@ ohci_update_frame_counter(void* priv) dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] = dev->ohci_mmio_w[OHCI_HcFmInterval / 2] & 0x3fff; dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] &= ~(1 << 31); dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] |= dev->ohci_mmio_l[OHCI_HcFmInterval / 4] & (1 << 31); - dev->ohci_mmio_w[OHCI_HcFmNumber / 2]++; ohci_start_of_frame(dev); + timer_on_auto(&dev->ohci_frame_timer, 1. / (12. * 1000. * 1000.)); + return; } if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]) dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]--; timer_on_auto(&dev->ohci_frame_timer, 1. / (12. * 1000. * 1000.)); From 610db29480d59cd96ead69ca2cb72b7aa11c3f66 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 7 May 2023 01:11:38 +0600 Subject: [PATCH 25/34] usb: HCCA structure --- src/include/86box/usb.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index af1922570..ab9ae53a7 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -76,6 +76,15 @@ typedef struct } usb_desc_conf_t; #pragma pack(pop) +typedef struct +{ + uint32_t HccaInterrruptTable[32]; + uint16_t HccaFrameNumber; + uint16_t HccaPad1; + uint32_t HccaDoneHead; + uint32_t Reserved[29]; +} usb_hcca_t; + /* USB endpoint device struct. Incomplete and unused. */ typedef struct { From d0efb0079fb1f48d1fda83c772f410893f22916a Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 7 May 2023 01:16:18 +0600 Subject: [PATCH 26/34] usb: include dma.h header for future busmastering usage --- src/usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/usb.c b/src/usb.c index 897f07bdc..f0c7113b7 100644 --- a/src/usb.c +++ b/src/usb.c @@ -28,6 +28,7 @@ #include <86box/mem.h> #include <86box/timer.h> #include <86box/usb.h> +#include <86box/dma.h> #ifdef ENABLE_USB_LOG int usb_do_log = ENABLE_USB_LOG; From df6897640d7540c88d330ee9bf607e1acacfd972 Mon Sep 17 00:00:00 2001 From: Jordi Guillaumes i Pons Date: Sat, 6 May 2023 23:23:00 +0200 Subject: [PATCH 27/34] Fix: Load the interface list even if PCAP is not selected Fix: Show "VDE" when hovering over the status icon for a VDE connected NIC --- src/qt/qt_mediamenu.cpp | 3 +++ src/qt/qt_settingsnetwork.cpp | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_mediamenu.cpp b/src/qt/qt_mediamenu.cpp index 3ab5f9b60..841cd3053 100644 --- a/src/qt/qt_mediamenu.cpp +++ b/src/qt/qt_mediamenu.cpp @@ -857,6 +857,9 @@ MediaMenu::nicUpdateMenu(int i) case NET_TYPE_PCAP: netType = "PCAP"; break; + case NET_TYPE_VDE: + netType = "VDE"; + break; } QString devName = DeviceConfig::DeviceName(network_card_getdevice(net_cards_conf[i].device_num), network_card_get_internal_name(net_cards_conf[i].device_num), 1); diff --git a/src/qt/qt_settingsnetwork.cpp b/src/qt/qt_settingsnetwork.cpp index 7134e3381..ceb4810bc 100644 --- a/src/qt/qt_settingsnetwork.cpp +++ b/src/qt/qt_settingsnetwork.cpp @@ -148,7 +148,7 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) selectedRow = 0; - if (net_cards_conf[i].net_type == NET_TYPE_PCAP) { + if (network_ndev > 0) { QString currentPcapDevice = net_cards_conf[i].host_dev_name; cbox = findChild(QString("comboBoxIntf%1").arg(i + 1)); model = cbox->model(); @@ -161,7 +161,8 @@ SettingsNetwork::onCurrentMachineChanged(int machineId) } model->removeRows(0, removeRows); cbox->setCurrentIndex(selectedRow); - } else if (net_cards_conf[i].net_type == NET_TYPE_VDE) { + } + if (net_cards_conf[i].net_type == NET_TYPE_VDE) { QString currentVdeSocket = net_cards_conf[i].host_dev_name; auto editline = findChild(QString("socketVDENIC%1").arg(i+1)); editline->setText(currentVdeSocket); From a9cc8cf8981f8aa81910a179d98ee15c58debed3 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 7 May 2023 00:24:57 +0200 Subject: [PATCH 28/34] Made softfloat work on the dynamic recompiler (not yet enabled in the Settings dialog, needs MMX and FXSAVE/FXRSTOR for softfloat first). --- src/codegen/codegen_ops.c | 48 +++++++++ src/codegen/codegen_ops.h | 1 + src/codegen/codegen_x86-64.c | 16 +-- src/codegen/codegen_x86.c | 16 +-- src/codegen_new/codegen.c | 32 +++--- src/codegen_new/codegen_ops.c | 49 +++++++++ src/codegen_new/codegen_ops.h | 1 + src/cpu/cpu.c | 188 +++++++++++++++++++++++----------- src/cpu/x86_ops.h | 39 +++++++ src/cpu/x86_ops_fpu.h | 3 +- 10 files changed, 302 insertions(+), 91 deletions(-) diff --git a/src/codegen/codegen_ops.c b/src/codegen/codegen_ops.c index 46a49f118..b5991c985 100644 --- a/src/codegen/codegen_ops.c +++ b/src/codegen/codegen_ops.c @@ -607,3 +607,51 @@ RecompOpFn recomp_opcodes_REPNE[512] = { /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // clang-format on }; + +RecompOpFn recomp_opcodes_NULL[512] = { + // clang-format off + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // clang-format on +}; diff --git a/src/codegen/codegen_ops.h b/src/codegen/codegen_ops.h index f92ba4f6d..937105f9e 100644 --- a/src/codegen/codegen_ops.h +++ b/src/codegen/codegen_ops.h @@ -17,6 +17,7 @@ extern RecompOpFn recomp_opcodes_de[512]; extern RecompOpFn recomp_opcodes_df[512]; extern RecompOpFn recomp_opcodes_REPE[512]; extern RecompOpFn recomp_opcodes_REPNE[512]; +extern RecompOpFn recomp_opcodes_NULL[512]; #define REG_EAX 0 #define REG_ECX 1 diff --git a/src/codegen/codegen_x86-64.c b/src/codegen/codegen_x86-64.c index 4a184b981..fc3618d91 100644 --- a/src/codegen/codegen_x86-64.c +++ b/src/codegen/codegen_x86-64.c @@ -883,7 +883,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p case 0xd8: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_d8; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -893,7 +893,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xd9: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_d9; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -902,7 +902,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xda: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_da; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -911,7 +911,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xdb: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_db; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -920,7 +920,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xdc: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_dc; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -930,7 +930,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xdd: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_dd; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -939,7 +939,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xde: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_de; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -948,7 +948,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xdf: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_df; opcode_mask = 0xff; over = 1; pc_off = -1; diff --git a/src/codegen/codegen_x86.c b/src/codegen/codegen_x86.c index dbf76c2e4..f9d1d1ba5 100644 --- a/src/codegen/codegen_x86.c +++ b/src/codegen/codegen_x86.c @@ -1921,7 +1921,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p case 0xd8: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_d8; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -1931,7 +1931,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xd9: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_d9; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -1940,7 +1940,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xda: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_da; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -1949,7 +1949,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xdb: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_db; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -1958,7 +1958,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xdc: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_dc; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -1968,7 +1968,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xdd: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_dd; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -1977,7 +1977,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xde: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_de; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -1986,7 +1986,7 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p break; case 0xdf: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_df; opcode_mask = 0xff; over = 1; pc_off = -1; diff --git a/src/codegen_new/codegen.c b/src/codegen_new/codegen.c index bf6ad123c..58e5d8a06 100644 --- a/src/codegen_new/codegen.c +++ b/src/codegen_new/codegen.c @@ -439,8 +439,8 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xd8; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d8_a32 : (OpFn *) x86_dynarec_opcodes_d8_a16; - recomp_op_table = recomp_opcodes_d8; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_d8; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -452,8 +452,8 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xd9; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_d9_a32 : (OpFn *) x86_dynarec_opcodes_d9_a16; - recomp_op_table = recomp_opcodes_d9; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_d9; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -464,8 +464,8 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xda; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_da_a32 : (OpFn *) x86_dynarec_opcodes_da_a16; - recomp_op_table = recomp_opcodes_da; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_da; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -476,8 +476,8 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xdb; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_db_a32 : (OpFn *) x86_dynarec_opcodes_db_a16; - recomp_op_table = recomp_opcodes_db; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_db; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -488,8 +488,8 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xdc; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dc_a32 : (OpFn *) x86_dynarec_opcodes_dc_a16; - recomp_op_table = recomp_opcodes_dc; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_dc; opcode_shift = 3; opcode_mask = 0x1f; over = 1; @@ -501,8 +501,8 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xdd; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_dd_a32 : (OpFn *) x86_dynarec_opcodes_dd_a16; - recomp_op_table = recomp_opcodes_dd; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_dd; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -513,8 +513,8 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xde; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_de_a32 : (OpFn *) x86_dynarec_opcodes_de_a16; - recomp_op_table = recomp_opcodes_de; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_de; opcode_mask = 0xff; over = 1; pc_off = -1; @@ -525,8 +525,8 @@ codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_p #ifdef DEBUG_EXTRA last_prefix = 0xdf; #endif - op_table = (op_32 & 0x200) ? (OpFn *) x86_dynarec_opcodes_df_a32 : (OpFn *) x86_dynarec_opcodes_df_a16; - recomp_op_table = recomp_opcodes_df; + op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; + recomp_op_table = fpu_softfloat ? recomp_opcodes_NULL : recomp_opcodes_df; opcode_mask = 0xff; over = 1; pc_off = -1; diff --git a/src/codegen_new/codegen_ops.c b/src/codegen_new/codegen_ops.c index 3fadd4a13..e611e6b29 100644 --- a/src/codegen_new/codegen_ops.c +++ b/src/codegen_new/codegen_ops.c @@ -556,3 +556,52 @@ RecompOpFn recomp_opcodes_df[512] = { /*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // clang-format on }; + +RecompOpFn recomp_opcodes_NULL[512] = { + // clang-format off + /*16-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /*32-bit data*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + +/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + // clang-format on +}; + diff --git a/src/codegen_new/codegen_ops.h b/src/codegen_new/codegen_ops.h index 9cef07e15..43bcf1b3f 100644 --- a/src/codegen_new/codegen_ops.h +++ b/src/codegen_new/codegen_ops.h @@ -20,6 +20,7 @@ extern RecompOpFn recomp_opcodes_de[512]; extern RecompOpFn recomp_opcodes_df[512]; /*extern RecompOpFn recomp_opcodes_REPE[512]; extern RecompOpFn recomp_opcodes_REPNE[512];*/ +extern RecompOpFn recomp_opcodes_NULL[512]; #define REG_EAX 0 #define REG_ECX 1 diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index f70c2155a..694ee1155 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -202,7 +202,7 @@ void cpu_set_edx(void) { EDX = cpu_s->edx_reset; - if (!cpu_use_dynarec && fpu_softfloat) + if (fpu_softfloat) SF_FPU_reset(); } @@ -457,22 +457,41 @@ cpu_set(void) if (hasfpu) { #ifdef USE_DYNAREC - x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16; - x86_dynarec_opcodes_d8_a32 = dynarec_ops_fpu_d8_a32; - x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_d9_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_d9_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_db_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_dc_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_dc_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_dd_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_dd_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_de_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_de_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_df_a32; + if (fpu_softfloat) { + x86_dynarec_opcodes_d8_a16 = dynarec_ops_sf_fpu_d8_a16; + x86_dynarec_opcodes_d8_a32 = dynarec_ops_sf_fpu_d8_a32; + x86_dynarec_opcodes_d9_a16 = dynarec_ops_sf_fpu_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_sf_fpu_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_sf_fpu_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_sf_fpu_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_sf_fpu_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_sf_fpu_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_sf_fpu_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_sf_fpu_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_df_a32; + } else { + x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16; + x86_dynarec_opcodes_d8_a32 = dynarec_ops_fpu_d8_a32; + x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_df_a32; + } #endif if (fpu_softfloat) { x86_opcodes_d8_a16 = ops_sf_fpu_d8_a16; @@ -581,20 +600,37 @@ cpu_set(void) if (fpu_type == FPU_287) { #ifdef USE_DYNAREC - x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; + if (fpu_softfloat) { + x86_dynarec_opcodes_d9_a16 = dynarec_ops_sf_fpu_287_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_sf_fpu_287_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_287_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_287_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_287_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_287_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_sf_fpu_287_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_sf_fpu_287_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_sf_fpu_287_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_sf_fpu_287_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_sf_fpu_287_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_sf_fpu_287_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_287_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_287_df_a32; + } else { + x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; + } #endif if (fpu_softfloat) { x86_opcodes_d9_a16 = ops_sf_fpu_287_d9_a16; @@ -674,20 +710,37 @@ cpu_set(void) case CPU_386DX: if (fpu_type == FPU_287) { /* In case we get Deskpro 386 emulation */ #ifdef USE_DYNAREC - x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; - x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; - x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; - x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; - x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; - x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; - x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; - x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; + if (fpu_softfloat) { + x86_dynarec_opcodes_d9_a16 = dynarec_ops_sf_fpu_287_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_sf_fpu_287_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_287_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_287_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_287_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_287_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_sf_fpu_287_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_sf_fpu_287_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_sf_fpu_287_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_sf_fpu_287_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_sf_fpu_287_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_sf_fpu_287_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_287_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_287_df_a32; + } else { + x86_dynarec_opcodes_d9_a16 = dynarec_ops_fpu_287_d9_a16; + x86_dynarec_opcodes_d9_a32 = dynarec_ops_fpu_287_d9_a32; + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_287_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_287_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_287_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_287_db_a32; + x86_dynarec_opcodes_dc_a16 = dynarec_ops_fpu_287_dc_a16; + x86_dynarec_opcodes_dc_a32 = dynarec_ops_fpu_287_dc_a32; + x86_dynarec_opcodes_dd_a16 = dynarec_ops_fpu_287_dd_a16; + x86_dynarec_opcodes_dd_a32 = dynarec_ops_fpu_287_dd_a32; + x86_dynarec_opcodes_de_a16 = dynarec_ops_fpu_287_de_a16; + x86_dynarec_opcodes_de_a32 = dynarec_ops_fpu_287_de_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_287_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_287_df_a32; + } #endif if (fpu_softfloat) { x86_opcodes_d9_a16 = ops_sf_fpu_287_d9_a16; @@ -1114,12 +1167,21 @@ cpu_set(void) case CPU_Cx6x86MX: if (cpu_s->cpu_type == CPU_Cx6x86MX) { # ifdef USE_DYNAREC - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; + if (fpu_softfloat) { + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_686_df_a32; + } else { + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; + } # endif if (fpu_softfloat) { x86_opcodes_da_a16 = ops_sf_fpu_686_da_a16; @@ -1152,7 +1214,8 @@ cpu_set(void) else if (cpu_s->cpu_type == CPU_Cx6x86L) x86_setopcodes(ops_386, ops_pentium_0f); else - x86_setopcodes(ops_386, ops_c6x86_0f); + x86_setopcodes(ops_386, ops_c6x86mx_0f); + // x86_setopcodes(ops_386, ops_c6x86_0f); # endif timing_rr = 1; /* register dest - register src */ @@ -1326,12 +1389,21 @@ cpu_set(void) x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f); else x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f); - x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; - x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; - x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; - x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; - x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; - x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; + if (fpu_softfloat) { + x86_dynarec_opcodes_da_a16 = dynarec_ops_sf_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_sf_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_sf_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_sf_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_sf_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_sf_fpu_686_df_a32; + } else { + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; + } #else if (cpu_s->cpu_type == CPU_PENTIUM2D) x86_setopcodes(ops_386, ops_pentium2d_0f); diff --git a/src/cpu/x86_ops.h b/src/cpu/x86_ops.h index 9d34c71ec..0cd449236 100644 --- a/src/cpu/x86_ops.h +++ b/src/cpu/x86_ops.h @@ -102,6 +102,38 @@ extern const OpFn dynarec_ops_pentiumpro_0f[1024]; extern const OpFn dynarec_ops_pentium2_0f[1024]; extern const OpFn dynarec_ops_pentium2d_0f[1024]; +extern const OpFn dynarec_ops_sf_fpu_287_d9_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_d9_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_da_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_da_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_db_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_db_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_dc_a16[32]; +extern const OpFn dynarec_ops_sf_fpu_287_dc_a32[32]; +extern const OpFn dynarec_ops_sf_fpu_287_dd_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_dd_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_de_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_de_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_287_df_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_287_df_a32[256]; + +extern const OpFn dynarec_ops_sf_fpu_d8_a16[32]; +extern const OpFn dynarec_ops_sf_fpu_d8_a32[32]; +extern const OpFn dynarec_ops_sf_fpu_d9_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_d9_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_da_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_da_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_db_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_db_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_dc_a16[32]; +extern const OpFn dynarec_ops_sf_fpu_dc_a32[32]; +extern const OpFn dynarec_ops_sf_fpu_dd_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_dd_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_de_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_de_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_df_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_df_a32[256]; + extern const OpFn dynarec_ops_fpu_287_d9_a16[256]; extern const OpFn dynarec_ops_fpu_287_d9_a32[256]; extern const OpFn dynarec_ops_fpu_287_da_a16[256]; @@ -136,6 +168,13 @@ extern const OpFn dynarec_ops_fpu_df_a32[256]; extern const OpFn dynarec_ops_nofpu_a16[256]; extern const OpFn dynarec_ops_nofpu_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_686_da_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_686_da_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_686_db_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_686_db_a32[256]; +extern const OpFn dynarec_ops_sf_fpu_686_df_a16[256]; +extern const OpFn dynarec_ops_sf_fpu_686_df_a32[256]; + extern const OpFn dynarec_ops_fpu_686_da_a16[256]; extern const OpFn dynarec_ops_fpu_686_da_a32[256]; extern const OpFn dynarec_ops_fpu_686_db_a16[256]; diff --git a/src/cpu/x86_ops_fpu.h b/src/cpu/x86_ops_fpu.h index 502218be5..29e999941 100644 --- a/src/cpu/x86_ops_fpu.h +++ b/src/cpu/x86_ops_fpu.h @@ -97,7 +97,8 @@ opWAIT(uint32_t fetchdat) return 1; } - if (!cpu_use_dynarec && fpu_softfloat) { + // if (!cpu_use_dynarec && fpu_softfloat) { + if (fpu_softfloat) { if (fpu_state.swd & FPU_SW_Summary) { if (cr0 & 0x20) { x86_int(16); From ecb8091d41f6841b2a34c79195d3e3e672719deb Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 7 May 2023 02:53:04 +0200 Subject: [PATCH 29/34] Fixed Cacodemon345's OHCI mess and implemented proper OHCI IRQ updating, fixes the Gigabyte GA-5AX POST. --- src/chipset/ali1543.c | 19 +- src/chipset/intel_piix.c | 15 +- src/chipset/sis_5571.c | 20 +- src/chipset/stpc.c | 13 +- src/device/keyboard_at - Cópia.c | 3258 ++++++++++++++++++++++++++++++ src/device/mouse_ps2 - Cópia.c | 404 ++++ src/include/86box/usb.h | 18 +- src/mem/mem - Cópia.c | 3092 ++++++++++++++++++++++++++++ src/mouse.patch | 69 + src/pic - Cópia.c | 838 ++++++++ src/usb.c | 523 +++-- 11 files changed, 8015 insertions(+), 254 deletions(-) create mode 100644 src/device/keyboard_at - Cópia.c create mode 100644 src/device/mouse_ps2 - Cópia.c create mode 100644 src/mem/mem - Cópia.c create mode 100644 src/mouse.patch create mode 100644 src/pic - Cópia.c diff --git a/src/chipset/ali1543.c b/src/chipset/ali1543.c index 00146c90e..2e2f74305 100644 --- a/src/chipset/ali1543.c +++ b/src/chipset/ali1543.c @@ -906,6 +906,7 @@ ali5237_write(int func, int addr, uint8_t val, void *priv) case 0x0c: /* Cache Line Size */ case 0x0d: /* Latency Timer */ + dev->usb_conf[addr] = val; break; case 0x3c: /* Interrupt Line Register */ @@ -1430,14 +1431,14 @@ ali7101_read(int func, int addr, void *priv) } static void -ali5237_usb_raise_interrupt(usb_t* usb, void *priv) +ali5237_usb_update_interrupt(usb_t* usb, void *priv) { ali1543_t *dev = (ali1543_t *) priv; - if (!dev->usb_dev_enable) - return; - - pci_set_irq(dev->usb_slot, PCI_INTA); + if (usb->irq_level) + pci_set_mirq(4, !!(dev->pci_conf[0x74] & 0x10)); + else + pci_clear_mirq(4, !!(dev->pci_conf[0x74] & 0x10)); } static void @@ -1590,10 +1591,10 @@ ali1543_init(const device_t *info) dev->smbus = device_add(&ali7101_smbus_device); /* USB */ - dev->usb_params.parent_priv = dev; - dev->usb_params.smi_handle = NULL; - dev->usb_params.raise_interrupt = ali5237_usb_raise_interrupt; - dev->usb = device_add_parameters(&usb_device, &dev->usb_params); + dev->usb_params.parent_priv = dev; + dev->usb_params.smi_handle = NULL; + dev->usb_params.update_interrupt = ali5237_usb_update_interrupt; + dev->usb = device_add_parameters(&usb_device, &dev->usb_params); dev->type = info->local & 0xff; dev->offset = (info->local >> 8) & 0x7f; diff --git a/src/chipset/intel_piix.c b/src/chipset/intel_piix.c index c6cfe8c9f..470978611 100644 --- a/src/chipset/intel_piix.c +++ b/src/chipset/intel_piix.c @@ -1427,11 +1427,14 @@ piix_fast_off_count(void *priv) } static void -piix_usb_raise_interrupt(usb_t* usb, void *priv) +piix_usb_update_interrupt(usb_t* usb, void *priv) { piix_t *dev = (piix_t *) priv; - pci_set_irq(dev->pci_slot, PCI_INTD); + if (usb->irq_level) + pci_set_irq(dev->pci_slot, PCI_INTD); + else + pci_clear_irq(dev->pci_slot, PCI_INTD); } static void @@ -1579,10 +1582,10 @@ piix_init(const device_t *info) } if (dev->type >= 3) { - dev->usb_params.parent_priv = dev; - dev->usb_params.smi_handle = NULL; - dev->usb_params.raise_interrupt = piix_usb_raise_interrupt; - dev->usb = device_add_parameters(&usb_device, &dev->usb_params); + dev->usb_params.parent_priv = dev; + dev->usb_params.smi_handle = NULL; + dev->usb_params.update_interrupt = piix_usb_update_interrupt; + dev->usb = device_add_parameters(&usb_device, &dev->usb_params); } if (dev->type > 3) { diff --git a/src/chipset/sis_5571.c b/src/chipset/sis_5571.c index aa8ea62f3..c158e2d63 100644 --- a/src/chipset/sis_5571.c +++ b/src/chipset/sis_5571.c @@ -641,7 +641,7 @@ pci_isa_bridge_read(int func, int addr, void *priv) } static void -sis_5571_usb_raise_interrupt(usb_t* usb, void* priv) +sis_5571_usb_update_interrupt(usb_t* usb, void* priv) { sis_5571_t *dev = (sis_5571_t *) priv; @@ -655,11 +655,17 @@ sis_5571_usb_raise_interrupt(usb_t* usb, void* priv) case 0x0d: break; default: - picint(1 << dev->pci_conf_sb[0][0x68] & 0x0F); + if (usb->irq_level) + picint(1 << dev->pci_conf_sb[0][0x68] & 0x0f); + else + picintc(1 << dev->pci_conf_sb[0][0x68] & 0x0f); break; } } else { - pci_set_irq(dev->sb_pci_slot, PCI_INTA); + if (usb->irq_level) + pci_set_irq(dev->sb_pci_slot, PCI_INTA); + else + pci_clear_irq(dev->sb_pci_slot, PCI_INTA); } } @@ -754,10 +760,10 @@ sis_5571_init(const device_t *info) dev->ide_drive[1] = device_add_inst(&sff8038i_device, 2); /* USB */ - dev->usb_params.parent_priv = dev; - dev->usb_params.raise_interrupt = sis_5571_usb_raise_interrupt; - dev->usb_params.smi_handle = sis_5571_usb_handle_smi; - dev->usb = device_add_parameters(&usb_device, &dev->usb_params); + dev->usb_params.parent_priv = dev; + dev->usb_params.update_interrupt = sis_5571_usb_update_interrupt; + dev->usb_params.smi_handle = sis_5571_usb_handle_smi; + dev->usb = device_add_parameters(&usb_device, &dev->usb_params); sis_5571_reset(dev); diff --git a/src/chipset/stpc.c b/src/chipset/stpc.c index 84720f802..2e4b045f2 100644 --- a/src/chipset/stpc.c +++ b/src/chipset/stpc.c @@ -875,11 +875,14 @@ stpc_setup(stpc_t *dev) } static void -stpc_usb_raise_interrupt(usb_t* usb, void* priv) +stpc_usb_update_interrupt(usb_t* usb, void* priv) { stpc_t *dev = (stpc_t *) priv; - pci_set_irq(dev->usb_slot, PCI_INTA); + if (usb->irq_level) + pci_set_irq(dev->usb_slot, PCI_INTA); + else + pci_clear_irq(dev->usb_slot, PCI_INTA); } static void @@ -907,9 +910,9 @@ stpc_init(const device_t *info) pci_add_card(PCI_ADD_NORTHBRIDGE, stpc_nb_read, stpc_nb_write, dev); dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_isab_read, stpc_isab_write, dev); if (dev->local == STPC_ATLAS) { - dev->usb_params.smi_handle = NULL; - dev->usb_params.raise_interrupt = stpc_usb_raise_interrupt; - dev->usb_params.parent_priv = dev; + dev->usb_params.smi_handle = NULL; + dev->usb_params.update_interrupt = stpc_usb_update_interrupt; + dev->usb_params.parent_priv = dev; dev->ide_slot = pci_add_card(PCI_ADD_SOUTHBRIDGE, stpc_ide_read, stpc_ide_write, dev); dev->usb = device_add_parameters(&usb_device, &dev->usb_params); diff --git a/src/device/keyboard_at - Cópia.c b/src/device/keyboard_at - Cópia.c new file mode 100644 index 000000000..3a841ad91 --- /dev/null +++ b/src/device/keyboard_at - Cópia.c @@ -0,0 +1,3258 @@ +/* + * 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. + * + * Intel 8042 (AT keyboard controller) emulation. + * + * + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * EngiNerd, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2020 EngiNerd. + */ +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include +#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> + +#define STAT_PARITY 0x80 +#define STAT_RTIMEOUT 0x40 +#define STAT_TTIMEOUT 0x20 +#define STAT_MFULL 0x20 +#define STAT_UNLOCKED 0x10 +#define STAT_CD 0x08 +#define STAT_SYSFLAG 0x04 +#define STAT_IFULL 0x02 +#define STAT_OFULL 0x01 + +#define CCB_UNUSED 0x80 +#define CCB_TRANSLATE 0x40 +#define CCB_PCMODE 0x20 +#define CCB_ENABLEKBD 0x10 +#define CCB_IGNORELOCK 0x08 +#define CCB_SYSTEM 0x04 +#define CCB_ENABLEMINT 0x02 +#define CCB_ENABLEKINT 0x01 + +#define CCB_MASK 0x68 +#define MODE_MASK 0x6c + +#define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ +#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ +#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ +#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ +#define KBC_TYPE_MASK 0x03 + +#define KBC_VEN_GENERIC 0x00 +#define KBC_VEN_AMI 0x04 +#define KBC_VEN_IBM_MCA 0x08 +#define KBC_VEN_QUADTEL 0x0c +#define KBC_VEN_TOSHIBA 0x10 +#define KBC_VEN_IBM_PS1 0x14 +#define KBC_VEN_ACER 0x18 +#define KBC_VEN_INTEL_AMI 0x1c +#define KBC_VEN_OLIVETTI 0x20 +#define KBC_VEN_NCR 0x24 +#define KBC_VEN_PHOENIX 0x28 +#define KBC_VEN_ALI 0x2c +#define KBC_VEN_TG 0x30 +#define KBC_VEN_TG_GREEN 0x34 +#define KBC_VEN_MASK 0x3c + +enum { + KBC_STATE_RESET = 0, + KBC_STATE_MAIN_IBF, + KBC_STATE_MAIN_KBD, + KBC_STATE_MAIN_MOUSE, + KBC_STATE_MAIN_BOTH, + KBC_STATE_KBC_OUT, + KBC_STATE_KBC_PARAM, + KBC_STATE_SEND_KBD, + KBC_STATE_KBD, + KBC_STATE_SEND_MOUSE, + KBC_STATE_MOUSE +}; +#define KBC_STATE_SCAN_KBD KBC_STATE_KBD +#define KBC_STATE_SCAN_MOUSE KBC_STATE_MOUSE + +enum { + DEV_STATE_MAIN_1 = 0, + DEV_STATE_MAIN_2, + DEV_STATE_MAIN_CMD, + DEV_STATE_MAIN_OUT, + DEV_STATE_MAIN_WANT_IN, + DEV_STATE_MAIN_IN +}; + +typedef struct { + /* Controller. */ + uint8_t pci, kbc_state, command, want60, + status, ib, out, old_out, + sc_or, secr_phase, mem_addr, input_port, + output_port, old_output_port, output_locked, ami_stat, + ami_flags, key_ctrl_queue_start, key_ctrl_queue_end; + + /* Keyboard. */ + uint8_t key_command, key_wantdata, kbd_last_scan_code, + kbd_state, key_wantcmd, key_dat, key_cmd_queue_start, + key_cmd_queue_end, key_queue_start, key_queue_end; + + /* Mouse. */ + uint8_t mouse_state, mouse_wantcmd, mouse_dat, mouse_cmd_queue_start, + mouse_cmd_queue_end, mouse_queue_start, mouse_queue_end; + + /* Controller. */ + uint8_t mem[0x100]; + + /* Controller - internal FIFO for the purpose of commands with multi-byte output. */ + uint8_t key_ctrl_queue[64]; + + /* Keyboard - command response FIFO. */ + uint8_t key_cmd_queue[16]; + + /* Keyboard - scan FIFO. */ + uint8_t key_queue[16]; + + /* Mouse - command response FIFO. */ + uint8_t mouse_cmd_queue[16]; + + /* Mouse - scan FIFO. */ + uint8_t mouse_queue[16]; + + /* Keyboard. */ + int out_new; + + /* Mouse. */ + int out_new_mouse; + + /* Controller. */ + uint32_t flags; + + /* Controller (main timer). */ + pc_timer_t send_delay_timer; + + /* Controller (P2 pulse callback timer). */ + pc_timer_t pulse_cb; + + uint8_t (*write60_ven)(void *p, uint8_t val); + uint8_t (*write64_ven)(void *p, uint8_t val); +} atkbd_t; + +/* Global keyboard flags for scan code set 3: + bit 0 = repeat, bit 1 = makes break code? */ +uint8_t keyboard_set3_flags[512]; +uint8_t keyboard_set3_all_repeat; +uint8_t keyboard_set3_all_break; + +/* Global keyboard mode: + Bits 0 - 1 = scan code set. */ +uint8_t keyboard_mode = 0x02; + +/* Keyboard controller ports. */ +kbc_port_t *kbc_ports[2] = { NULL, NULL }; + +static void (*mouse_write)(uint8_t val, void *priv) = NULL; +static void *mouse_p = NULL; +static atkbd_t *SavedKbd = NULL; // FIXME: remove!!! --FvK + +/* Non-translated to translated scan codes. */ +static const uint8_t nont_to_t[256] = { + 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, + 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, + 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, + 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, + 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, + 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, + 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, + 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, + 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, + 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, + 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, + 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, + 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, + 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, + 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, + 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, + 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +static const scancode scancode_set1[512] = { + // clang-format off + { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ + { { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/ + { { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/ + { { 0x0c,0},{ 0x8c,0} }, { { 0x0d,0},{ 0x8d,0} }, { { 0x0e,0},{ 0x8e,0} }, { { 0x0f,0},{ 0x8f,0} }, /*00c*/ + { { 0x10,0},{ 0x90,0} }, { { 0x11,0},{ 0x91,0} }, { { 0x12,0},{ 0x92,0} }, { { 0x13,0},{ 0x93,0} }, /*010*/ + { { 0x14,0},{ 0x94,0} }, { { 0x15,0},{ 0x95,0} }, { { 0x16,0},{ 0x96,0} }, { { 0x17,0},{ 0x97,0} }, /*014*/ + { { 0x18,0},{ 0x98,0} }, { { 0x19,0},{ 0x99,0} }, { { 0x1a,0},{ 0x9a,0} }, { { 0x1b,0},{ 0x9b,0} }, /*018*/ + { { 0x1c,0},{ 0x9c,0} }, { { 0x1d,0},{ 0x9d,0} }, { { 0x1e,0},{ 0x9e,0} }, { { 0x1f,0},{ 0x9f,0} }, /*01c*/ + { { 0x20,0},{ 0xa0,0} }, { { 0x21,0},{ 0xa1,0} }, { { 0x22,0},{ 0xa2,0} }, { { 0x23,0},{ 0xa3,0} }, /*020*/ + { { 0x24,0},{ 0xa4,0} }, { { 0x25,0},{ 0xa5,0} }, { { 0x26,0},{ 0xa6,0} }, { { 0x27,0},{ 0xa7,0} }, /*024*/ + { { 0x28,0},{ 0xa8,0} }, { { 0x29,0},{ 0xa9,0} }, { { 0x2a,0},{ 0xaa,0} }, { { 0x2b,0},{ 0xab,0} }, /*028*/ + { { 0x2c,0},{ 0xac,0} }, { { 0x2d,0},{ 0xad,0} }, { { 0x2e,0},{ 0xae,0} }, { { 0x2f,0},{ 0xaf,0} }, /*02c*/ + { { 0x30,0},{ 0xb0,0} }, { { 0x31,0},{ 0xb1,0} }, { { 0x32,0},{ 0xb2,0} }, { { 0x33,0},{ 0xb3,0} }, /*030*/ + { { 0x34,0},{ 0xb4,0} }, { { 0x35,0},{ 0xb5,0} }, { { 0x36,0},{ 0xb6,0} }, { { 0x37,0},{ 0xb7,0} }, /*034*/ + { { 0x38,0},{ 0xb8,0} }, { { 0x39,0},{ 0xb9,0} }, { { 0x3a,0},{ 0xba,0} }, { { 0x3b,0},{ 0xbb,0} }, /*038*/ + { { 0x3c,0},{ 0xbc,0} }, { { 0x3d,0},{ 0xbd,0} }, { { 0x3e,0},{ 0xbe,0} }, { { 0x3f,0},{ 0xbf,0} }, /*03c*/ + { { 0x40,0},{ 0xc0,0} }, { { 0x41,0},{ 0xc1,0} }, { { 0x42,0},{ 0xc2,0} }, { { 0x43,0},{ 0xc3,0} }, /*040*/ + { { 0x44,0},{ 0xc4,0} }, { { 0x45,0},{ 0xc5,0} }, { { 0x46,0},{ 0xc6,0} }, { { 0x47,0},{ 0xc7,0} }, /*044*/ + { { 0x48,0},{ 0xc8,0} }, { { 0x49,0},{ 0xc9,0} }, { { 0x4a,0},{ 0xca,0} }, { { 0x4b,0},{ 0xcb,0} }, /*048*/ + { { 0x4c,0},{ 0xcc,0} }, { { 0x4d,0},{ 0xcd,0} }, { { 0x4e,0},{ 0xce,0} }, { { 0x4f,0},{ 0xcf,0} }, /*04c*/ + { { 0x50,0},{ 0xd0,0} }, { { 0x51,0},{ 0xd1,0} }, { { 0x52,0},{ 0xd2,0} }, { { 0x53,0},{ 0xd3,0} }, /*050*/ + { { 0x54,0},{ 0xd4,0} }, { { 0x55,0},{ 0xd5,0} }, { { 0x56,0},{ 0xd6,0} }, { { 0x57,0},{ 0xd7,0} }, /*054*/ + { { 0x58,0},{ 0xd8,0} }, { { 0x59,0},{ 0xd9,0} }, { { 0x5a,0},{ 0xda,0} }, { { 0x5b,0},{ 0xdb,0} }, /*058*/ + { { 0x5c,0},{ 0xdc,0} }, { { 0x5d,0},{ 0xdd,0} }, { { 0x5e,0},{ 0xde,0} }, { { 0x5f,0},{ 0xdf,0} }, /*05c*/ + { { 0x60,0},{ 0xe0,0} }, { { 0x61,0},{ 0xe1,0} }, { { 0x62,0},{ 0xe2,0} }, { { 0x63,0},{ 0xe3,0} }, /*060*/ + { { 0x64,0},{ 0xe4,0} }, { { 0x65,0},{ 0xe5,0} }, { { 0x66,0},{ 0xe6,0} }, { { 0x67,0},{ 0xe7,0} }, /*064*/ + { { 0x68,0},{ 0xe8,0} }, { { 0x69,0},{ 0xe9,0} }, { { 0x6a,0},{ 0xea,0} }, { { 0x6b,0},{ 0xeb,0} }, /*068*/ + { { 0x6c,0},{ 0xec,0} }, { { 0x6d,0},{ 0xed,0} }, { { 0x6e,0},{ 0xee,0} }, { { 0x6f,0},{ 0xef,0} }, /*06c*/ + { { 0x70,0},{ 0xf0,0} }, { { 0x71,0},{ 0xf1,0} }, { { 0x72,0},{ 0xf2,0} }, { { 0x73,0},{ 0xf3,0} }, /*070*/ + { { 0x74,0},{ 0xf4,0} }, { { 0x75,0},{ 0xf5,0} }, { { 0x76,0},{ 0xf6,0} }, { { 0x77,0},{ 0xf7,0} }, /*074*/ + { { 0x78,0},{ 0xf8,0} }, { { 0x79,0},{ 0xf9,0} }, { { 0x7a,0},{ 0xfa,0} }, { { 0x7b,0},{ 0xfb,0} }, /*078*/ + { { 0x7c,0},{ 0xfc,0} }, { { 0x7d,0},{ 0xfd,0} }, { { 0x7e,0},{ 0xfe,0} }, { { 0x7f,0},{ 0xff,0} }, /*07c*/ + + { { 0x80,0},{ 0} }, { { 0x81,0},{ 0} }, { { 0x82,0},{ 0} }, { { 0},{ 0} }, /*080*/ + { { 0},{ 0} }, { { 0x85,0},{ 0} }, { { 0x86,0},{ 0} }, { { 0x87,0},{ 0} }, /*084*/ + { { 0x88,0},{ 0} }, { { 0x89,0},{ 0} }, { { 0x8a,0},{ 0} }, { { 0x8b,0},{ 0} }, /*088*/ + { { 0x8c,0},{ 0} }, { { 0x8d,0},{ 0} }, { { 0x8e,0},{ 0} }, { { 0x8f,0},{ 0} }, /*08c*/ + { { 0x90,0},{ 0} }, { { 0x91,0},{ 0} }, { { 0x92,0},{ 0} }, { { 0x93,0},{ 0} }, /*090*/ + { { 0x94,0},{ 0} }, { { 0x95,0},{ 0} }, { { 0x96,0},{ 0} }, { { 0x97,0},{ 0} }, /*094*/ + { { 0x98,0},{ 0} }, { { 0x99,0},{ 0} }, { { 0x9a,0},{ 0} }, { { 0x9b,0},{ 0} }, /*098*/ + { { 0x9c,0},{ 0} }, { { 0x9d,0},{ 0} }, { { 0x9e,0},{ 0} }, { { 0x9f,0},{ 0} }, /*09c*/ + { { 0xa0,0},{ 0} }, { { 0xa1,0},{ 0} }, { { 0xa2,0},{ 0} }, { { 0xa3,0},{ 0} }, /*0a0*/ + { { 0xa4,0},{ 0} }, { { 0xa5,0},{ 0} }, { { 0xa6,0},{ 0} }, { { 0xa7,0},{ 0} }, /*0a4*/ + { { 0xa8,0},{ 0} }, { { 0xa9,0},{ 0} }, { { 0xaa,0},{ 0} }, { { 0xab,0},{ 0} }, /*0a8*/ + { { 0xac,0},{ 0} }, { { 0xad,0},{ 0} }, { { 0xae,0},{ 0} }, { { 0xaf,0},{ 0} }, /*0ac*/ + { { 0xb0,0},{ 0} }, { { 0xb1,0},{ 0} }, { { 0xb2,0},{ 0} }, { { 0xb3,0},{ 0} }, /*0b0*/ + { { 0xb4,0},{ 0} }, { { 0xb5,0},{ 0} }, { { 0xb6,0},{ 0} }, { { 0xb7,0},{ 0} }, /*0b4*/ + { { 0xb8,0},{ 0} }, { { 0xb9,0},{ 0} }, { { 0xba,0},{ 0} }, { { 0xbb,0},{ 0} }, /*0b8*/ + { { 0xbc,0},{ 0} }, { { 0xbd,0},{ 0} }, { { 0xbe,0},{ 0} }, { { 0xbf,0},{ 0} }, /*0bc*/ + { { 0xc0,0},{ 0} }, { { 0xc1,0},{ 0} }, { { 0xc2,0},{ 0} }, { { 0xc3,0},{ 0} }, /*0c0*/ + { { 0xc4,0},{ 0} }, { { 0xc5,0},{ 0} }, { { 0xc6,0},{ 0} }, { { 0xc7,0},{ 0} }, /*0c4*/ + { { 0xc8,0},{ 0} }, { { 0xc9,0},{ 0} }, { { 0xca,0},{ 0} }, { { 0xcb,0},{ 0} }, /*0c8*/ + { { 0xcc,0},{ 0} }, { { 0xcd,0},{ 0} }, { { 0xce,0},{ 0} }, { { 0xcf,0},{ 0} }, /*0cc*/ + { { 0xd0,0},{ 0} }, { { 0xd1,0},{ 0} }, { { 0xd2,0},{ 0} }, { { 0xd3,0},{ 0} }, /*0d0*/ + { { 0xd4,0},{ 0} }, { { 0xd5,0},{ 0} }, { { 0xd6,0},{ 0} }, { { 0xd7,0},{ 0} }, /*0d4*/ + { { 0xd8,0},{ 0} }, { { 0xd9,0},{ 0} }, { { 0xda,0},{ 0} }, { { 0xdb,0},{ 0} }, /*0d8*/ + { { 0xdc,0},{ 0} }, { { 0xdd,0},{ 0} }, { { 0xde,0},{ 0} }, { { 0xdf,0},{ 0} }, /*0dc*/ + { { 0xe0,0},{ 0} }, { { 0xe1,0},{ 0} }, { { 0xe2,0},{ 0} }, { { 0xe3,0},{ 0} }, /*0e0*/ + { { 0xe4,0},{ 0} }, { { 0xe5,0},{ 0} }, { { 0xe6,0},{ 0} }, { { 0xe7,0},{ 0} }, /*0e4*/ + { { 0xe8,0},{ 0} }, { { 0xe9,0},{ 0} }, { { 0xea,0},{ 0} }, { { 0xeb,0},{ 0} }, /*0e8*/ + { { 0xec,0},{ 0} }, { { 0xed,0},{ 0} }, { { 0xee,0},{ 0} }, { { 0xef,0},{ 0} }, /*0ec*/ + { { 0},{ 0} }, { { 0xf1,0},{ 0} }, { { 0xf2,0},{ 0} }, { { 0xf3,0},{ 0} }, /*0f0*/ + { { 0xf4,0},{ 0} }, { { 0xf5,0},{ 0} }, { { 0xf6,0},{ 0} }, { { 0xf7,0},{ 0} }, /*0f4*/ + { { 0xf8,0},{ 0} }, { { 0xf9,0},{ 0} }, { { 0xfa,0},{ 0} }, { { 0xfb,0},{ 0} }, /*0f8*/ + { { 0xfc,0},{ 0} }, { { 0xfd,0},{ 0} }, { { 0xfe,0},{ 0} }, { { 0xff,0},{ 0} }, /*0fc*/ + + { {0xe1,0x1d,0},{0xe1, 0x9d,0} }, { {0xe0,0x01,0},{0xe0, 0x81,0} }, { {0xe0,0x02,0},{0xe0, 0x82,0} }, { {0xe0,0x03,0},{0xe0, 0x83,0} }, /*100*/ + { {0xe0,0x04,0},{0xe0, 0x84,0} }, { {0xe0,0x05,0},{0xe0, 0x85,0} }, { {0xe0,0x06,0},{0xe0, 0x86,0} }, { {0xe0,0x07,0},{0xe0, 0x87,0} }, /*104*/ + { {0xe0,0x08,0},{0xe0, 0x88,0} }, { {0xe0,0x09,0},{0xe0, 0x89,0} }, { {0xe0,0x0a,0},{0xe0, 0x8a,0} }, { {0xe0,0x0b,0},{0xe0, 0x8b,0} }, /*108*/ + { {0xe0,0x0c,0},{0xe0, 0x8c,0} }, { { 0},{ 0} }, { {0xe0,0x0e,0},{0xe0, 0x8e,0} }, { {0xe0,0x0f,0},{0xe0, 0x8f,0} }, /*10c*/ + { {0xe0,0x10,0},{0xe0, 0x90,0} }, { {0xe0,0x11,0},{0xe0, 0x91,0} }, { {0xe0,0x12,0},{0xe0, 0x92,0} }, { {0xe0,0x13,0},{0xe0, 0x93,0} }, /*110*/ + { {0xe0,0x14,0},{0xe0, 0x94,0} }, { {0xe0,0x15,0},{0xe0, 0x95,0} }, { {0xe0,0x16,0},{0xe0, 0x96,0} }, { {0xe0,0x17,0},{0xe0, 0x97,0} }, /*114*/ + { {0xe0,0x18,0},{0xe0, 0x98,0} }, { {0xe0,0x19,0},{0xe0, 0x99,0} }, { {0xe0,0x1a,0},{0xe0, 0x9a,0} }, { {0xe0,0x1b,0},{0xe0, 0x9b,0} }, /*118*/ + { {0xe0,0x1c,0},{0xe0, 0x9c,0} }, { {0xe0,0x1d,0},{0xe0, 0x9d,0} }, { {0xe0,0x1e,0},{0xe0, 0x9e,0} }, { {0xe0,0x1f,0},{0xe0, 0x9f,0} }, /*11c*/ + { {0xe0,0x20,0},{0xe0, 0xa0,0} }, { {0xe0,0x21,0},{0xe0, 0xa1,0} }, { {0xe0,0x22,0},{0xe0, 0xa2,0} }, { {0xe0,0x23,0},{0xe0, 0xa3,0} }, /*120*/ + { {0xe0,0x24,0},{0xe0, 0xa4,0} }, { {0xe0,0x25,0},{0xe0, 0xa5,0} }, { {0xe0,0x26,0},{0xe0, 0xa6,0} }, { { 0},{ 0} }, /*124*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ + { {0xe0,0x2c,0},{0xe0, 0xac,0} }, { {0xe0,0x2d,0},{0xe0, 0xad,0} }, { {0xe0,0x2e,0},{0xe0, 0xae,0} }, { {0xe0,0x2f,0},{0xe0, 0xaf,0} }, /*12c*/ + { {0xe0,0x30,0},{0xe0, 0xb0,0} }, { {0xe0,0x31,0},{0xe0, 0xb1,0} }, { {0xe0,0x32,0},{0xe0, 0xb2,0} }, { { 0},{ 0} }, /*130*/ + { {0xe0,0x34,0},{0xe0, 0xb4,0} }, { {0xe0,0x35,0},{0xe0, 0xb5,0} }, { { 0},{ 0} }, { {0xe0,0x37,0},{0xe0, 0xb7,0} }, /*134*/ + { {0xe0,0x38,0},{0xe0, 0xb8,0} }, { { 0},{ 0} }, { {0xe0,0x3a,0},{0xe0, 0xba,0} }, { {0xe0,0x3b,0},{0xe0, 0xbb,0} }, /*138*/ + { {0xe0,0x3c,0},{0xe0, 0xbc,0} }, { {0xe0,0x3d,0},{0xe0, 0xbd,0} }, { {0xe0,0x3e,0},{0xe0, 0xbe,0} }, { {0xe0,0x3f,0},{0xe0, 0xbf,0} }, /*13c*/ + { {0xe0,0x40,0},{0xe0, 0xc0,0} }, { {0xe0,0x41,0},{0xe0, 0xc1,0} }, { {0xe0,0x42,0},{0xe0, 0xc2,0} }, { {0xe0,0x43,0},{0xe0, 0xc3,0} }, /*140*/ + { {0xe0,0x44,0},{0xe0, 0xc4,0} }, { { 0},{ 0} }, { {0xe0,0x46,0},{0xe0, 0xc6,0} }, { {0xe0,0x47,0},{0xe0, 0xc7,0} }, /*144*/ + { {0xe0,0x48,0},{0xe0, 0xc8,0} }, { {0xe0,0x49,0},{0xe0, 0xc9,0} }, { { 0},{ 0} }, { {0xe0,0x4b,0},{0xe0, 0xcb,0} }, /*148*/ + { {0xe0,0x4c,0},{0xe0, 0xcc,0} }, { {0xe0,0x4d,0},{0xe0, 0xcd,0} }, { {0xe0,0x4e,0},{0xe0, 0xce,0} }, { {0xe0,0x4f,0},{0xe0, 0xcf,0} }, /*14c*/ + { {0xe0,0x50,0},{0xe0, 0xd0,0} }, { {0xe0,0x51,0},{0xe0, 0xd1,0} }, { {0xe0,0x52,0},{0xe0, 0xd2,0} }, { {0xe0,0x53,0},{0xe0, 0xd3,0} }, /*150*/ + { { 0},{ 0} }, { {0xe0,0x55,0},{0xe0, 0xd5,0} }, { { 0},{ 0} }, { {0xe0,0x57,0},{0xe0, 0xd7,0} }, /*154*/ + { {0xe0,0x58,0},{0xe0, 0xd8,0} }, { {0xe0,0x59,0},{0xe0, 0xd9,0} }, { {0xe0,0x5a,0},{0xe0, 0xaa,0} }, { {0xe0,0x5b,0},{0xe0, 0xdb,0} }, /*158*/ + { {0xe0,0x5c,0},{0xe0, 0xdc,0} }, { {0xe0,0x5d,0},{0xe0, 0xdd,0} }, { {0xe0,0x5e,0},{0xe0, 0xee,0} }, { {0xe0,0x5f,0},{0xe0, 0xdf,0} }, /*15c*/ + { { 0},{ 0} }, { {0xe0,0x61,0},{0xe0, 0xe1,0} }, { {0xe0,0x62,0},{0xe0, 0xe2,0} }, { {0xe0,0x63,0},{0xe0, 0xe3,0} }, /*160*/ + { {0xe0,0x64,0},{0xe0, 0xe4,0} }, { {0xe0,0x65,0},{0xe0, 0xe5,0} }, { {0xe0,0x66,0},{0xe0, 0xe6,0} }, { {0xe0,0x67,0},{0xe0, 0xe7,0} }, /*164*/ + { {0xe0,0x68,0},{0xe0, 0xe8,0} }, { {0xe0,0x69,0},{0xe0, 0xe9,0} }, { {0xe0,0x6a,0},{0xe0, 0xea,0} }, { {0xe0,0x6b,0},{0xe0, 0xeb,0} }, /*168*/ + { {0xe0,0x6c,0},{0xe0, 0xec,0} }, { {0xe0,0x6d,0},{0xe0, 0xed,0} }, { {0xe0,0x6e,0},{0xe0, 0xee,0} }, { { 0},{ 0} }, /*16c*/ + { {0xe0,0x70,0},{0xe0, 0xf0,0} }, { {0xe0,0x71,0},{0xe0, 0xf1,0} }, { {0xe0,0x72,0},{0xe0, 0xf2,0} }, { {0xe0,0x73,0},{0xe0, 0xf3,0} }, /*170*/ + { {0xe0,0x74,0},{0xe0, 0xf4,0} }, { {0xe0,0x75,0},{0xe0, 0xf5,0} }, { { 0},{ 0} }, { {0xe0,0x77,0},{0xe0, 0xf7,0} }, /*174*/ + { {0xe0,0x78,0},{0xe0, 0xf8,0} }, { {0xe0,0x79,0},{0xe0, 0xf9,0} }, { {0xe0,0x7a,0},{0xe0, 0xfa,0} }, { {0xe0,0x7b,0},{0xe0, 0xfb,0} }, /*178*/ + { {0xe0,0x7c,0},{0xe0, 0xfc,0} }, { {0xe0,0x7d,0},{0xe0, 0xfd,0} }, { {0xe0,0x7e,0},{0xe0, 0xfe,0} }, { {0xe0,0x7f,0},{0xe0, 0xff,0} }, /*17c*/ + + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ + { { 0},{ 0} }, { {0xe0,0xe1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{ 0} }, { { 0},{ 0} }, /*1ec*/ + { { 0},{ 0} }, { {0xe0,0xf1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/ + // clang-format on +}; + +static const scancode scancode_set2[512] = { + // clang-format off + { { 0},{ 0} }, { { 0x76,0},{ 0xF0,0x76,0} }, { { 0x16,0},{ 0xF0,0x16,0} }, { { 0x1E,0},{ 0xF0,0x1E,0} }, /*000*/ + { { 0x26,0},{ 0xF0,0x26,0} }, { { 0x25,0},{ 0xF0,0x25,0} }, { { 0x2E,0},{ 0xF0,0x2E,0} }, { { 0x36,0},{ 0xF0,0x36,0} }, /*004*/ + { { 0x3D,0},{ 0xF0,0x3D,0} }, { { 0x3E,0},{ 0xF0,0x3E,0} }, { { 0x46,0},{ 0xF0,0x46,0} }, { { 0x45,0},{ 0xF0,0x45,0} }, /*008*/ + { { 0x4E,0},{ 0xF0,0x4E,0} }, { { 0x55,0},{ 0xF0,0x55,0} }, { { 0x66,0},{ 0xF0,0x66,0} }, { { 0x0D,0},{ 0xF0,0x0D,0} }, /*00c*/ + { { 0x15,0},{ 0xF0,0x15,0} }, { { 0x1D,0},{ 0xF0,0x1D,0} }, { { 0x24,0},{ 0xF0,0x24,0} }, { { 0x2D,0},{ 0xF0,0x2D,0} }, /*010*/ + { { 0x2C,0},{ 0xF0,0x2C,0} }, { { 0x35,0},{ 0xF0,0x35,0} }, { { 0x3C,0},{ 0xF0,0x3C,0} }, { { 0x43,0},{ 0xF0,0x43,0} }, /*014*/ + { { 0x44,0},{ 0xF0,0x44,0} }, { { 0x4D,0},{ 0xF0,0x4D,0} }, { { 0x54,0},{ 0xF0,0x54,0} }, { { 0x5B,0},{ 0xF0,0x5B,0} }, /*018*/ + { { 0x5A,0},{ 0xF0,0x5A,0} }, { { 0x14,0},{ 0xF0,0x14,0} }, { { 0x1C,0},{ 0xF0,0x1C,0} }, { { 0x1B,0},{ 0xF0,0x1B,0} }, /*01c*/ + { { 0x23,0},{ 0xF0,0x23,0} }, { { 0x2B,0},{ 0xF0,0x2B,0} }, { { 0x34,0},{ 0xF0,0x34,0} }, { { 0x33,0},{ 0xF0,0x33,0} }, /*020*/ + { { 0x3B,0},{ 0xF0,0x3B,0} }, { { 0x42,0},{ 0xF0,0x42,0} }, { { 0x4B,0},{ 0xF0,0x4B,0} }, { { 0x4C,0},{ 0xF0,0x4C,0} }, /*024*/ + { { 0x52,0},{ 0xF0,0x52,0} }, { { 0x0E,0},{ 0xF0,0x0E,0} }, { { 0x12,0},{ 0xF0,0x12,0} }, { { 0x5D,0},{ 0xF0,0x5D,0} }, /*028*/ + { { 0x1A,0},{ 0xF0,0x1A,0} }, { { 0x22,0},{ 0xF0,0x22,0} }, { { 0x21,0},{ 0xF0,0x21,0} }, { { 0x2A,0},{ 0xF0,0x2A,0} }, /*02c*/ + { { 0x32,0},{ 0xF0,0x32,0} }, { { 0x31,0},{ 0xF0,0x31,0} }, { { 0x3A,0},{ 0xF0,0x3A,0} }, { { 0x41,0},{ 0xF0,0x41,0} }, /*030*/ + { { 0x49,0},{ 0xF0,0x49,0} }, { { 0x4A,0},{ 0xF0,0x4A,0} }, { { 0x59,0},{ 0xF0,0x59,0} }, { { 0x7C,0},{ 0xF0,0x7C,0} }, /*034*/ + { { 0x11,0},{ 0xF0,0x11,0} }, { { 0x29,0},{ 0xF0,0x29,0} }, { { 0x58,0},{ 0xF0,0x58,0} }, { { 0x05,0},{ 0xF0,0x05,0} }, /*038*/ + { { 0x06,0},{ 0xF0,0x06,0} }, { { 0x04,0},{ 0xF0,0x04,0} }, { { 0x0C,0},{ 0xF0,0x0C,0} }, { { 0x03,0},{ 0xF0,0x03,0} }, /*03c*/ + { { 0x0B,0},{ 0xF0,0x0B,0} }, { { 0x83,0},{ 0xF0,0x83,0} }, { { 0x0A,0},{ 0xF0,0x0A,0} }, { { 0x01,0},{ 0xF0,0x01,0} }, /*040*/ + { { 0x09,0},{ 0xF0,0x09,0} }, { { 0x77,0},{ 0xF0,0x77,0} }, { { 0x7E,0},{ 0xF0,0x7E,0} }, { { 0x6C,0},{ 0xF0,0x6C,0} }, /*044*/ + { { 0x75,0},{ 0xF0,0x75,0} }, { { 0x7D,0},{ 0xF0,0x7D,0} }, { { 0x7B,0},{ 0xF0,0x7B,0} }, { { 0x6B,0},{ 0xF0,0x6B,0} }, /*048*/ + { { 0x73,0},{ 0xF0,0x73,0} }, { { 0x74,0},{ 0xF0,0x74,0} }, { { 0x79,0},{ 0xF0,0x79,0} }, { { 0x69,0},{ 0xF0,0x69,0} }, /*04c*/ + { { 0x72,0},{ 0xF0,0x72,0} }, { { 0x7A,0},{ 0xF0,0x7A,0} }, { { 0x70,0},{ 0xF0,0x70,0} }, { { 0x71,0},{ 0xF0,0x71,0} }, /*050*/ + { { 0x84,0},{ 0xF0,0x84,0} }, { { 0x60,0},{ 0xF0,0x60,0} }, { { 0x61,0},{ 0xF0,0x61,0} }, { { 0x78,0},{ 0xF0,0x78,0} }, /*054*/ + { { 0x07,0},{ 0xF0,0x07,0} }, { { 0x0F,0},{ 0xF0,0x0F,0} }, { { 0x17,0},{ 0xF0,0x17,0} }, { { 0x1F,0},{ 0xF0,0x1F,0} }, /*058*/ + { { 0x27,0},{ 0xF0,0x27,0} }, { { 0x2F,0},{ 0xF0,0x2F,0} }, { { 0x37,0},{ 0xF0,0x37,0} }, { { 0x3F,0},{ 0xF0,0x3F,0} }, /*05c*/ + { { 0x47,0},{ 0xF0,0x47,0} }, { { 0x4F,0},{ 0xF0,0x4F,0} }, { { 0x56,0},{ 0xF0,0x56,0} }, { { 0x5E,0},{ 0xF0,0x5E,0} }, /*060*/ + { { 0x08,0},{ 0xF0,0x08,0} }, { { 0x10,0},{ 0xF0,0x10,0} }, { { 0x18,0},{ 0xF0,0x18,0} }, { { 0x20,0},{ 0xF0,0x20,0} }, /*064*/ + { { 0x28,0},{ 0xF0,0x28,0} }, { { 0x30,0},{ 0xF0,0x30,0} }, { { 0x38,0},{ 0xF0,0x38,0} }, { { 0x40,0},{ 0xF0,0x40,0} }, /*068*/ + { { 0x48,0},{ 0xF0,0x48,0} }, { { 0x50,0},{ 0xF0,0x50,0} }, { { 0x57,0},{ 0xF0,0x57,0} }, { { 0x6F,0},{ 0xF0,0x6F,0} }, /*06c*/ + { { 0x13,0},{ 0xF0,0x13,0} }, { { 0x19,0},{ 0xF0,0x19,0} }, { { 0x39,0},{ 0xF0,0x39,0} }, { { 0x51,0},{ 0xF0,0x51,0} }, /*070*/ + { { 0x53,0},{ 0xF0,0x53,0} }, { { 0x5C,0},{ 0xF0,0x5C,0} }, { { 0x5F,0},{ 0xF0,0x5F,0} }, { { 0x62,0},{ 0xF0,0x62,0} }, /*074*/ + { { 0x63,0},{ 0xF0,0x63,0} }, { { 0x64,0},{ 0xF0,0x64,0} }, { { 0x65,0},{ 0xF0,0x65,0} }, { { 0x67,0},{ 0xF0,0x67,0} }, /*078*/ + { { 0x68,0},{ 0xF0,0x68,0} }, { { 0x6A,0},{ 0xF0,0x6A,0} }, { { 0x6D,0},{ 0xF0,0x6D,0} }, { { 0x6E,0},{ 0xF0,0x6E,0} }, /*07c*/ + + { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ + { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ + { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ + { { 0x8c,0},{ 0xf0,0x8c,0} }, { { 0x8d,0},{ 0xf0,0x8d,0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ + { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ + { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ + { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ + { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ + { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ + { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ + { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ + { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ + { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ + { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ + { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ + { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ + { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ + { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ + { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ + { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ + { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ + { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ + { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ + { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ + { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ + { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ + { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ + { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ + { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ + { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ + { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ + { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ + + { {0xe1,0x14,0},{0xe1,0xf0,0x14,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ + { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ + { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ + { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ + { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ + { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ + { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ + { {0xe0,0x5A,0},{0xe0,0xF0,0x5A,0} }, { {0xe0,0x14,0},{0xe0,0xF0,0x14,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ + { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ + { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ + { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ + { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ + { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {0xe0,0x4A,0},{0xe0,0xF0,0x4A,0} }, { { 0},{ 0} }, { {0xe0,0x7C,0},{0xe0,0xF0,0x7C,0} }, /*134*/ + { {0xe0,0x11,0},{0xe0,0xF0,0x11,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ + { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ + { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ + { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {0xe0,0x6C,0},{0xe0,0xF0,0x6C,0} }, /*144*/ + { {0xe0,0x75,0},{0xe0,0xF0,0x75,0} }, { {0xe0,0x7D,0},{0xe0,0xF0,0x7D,0} }, { { 0},{ 0} }, { {0xe0,0x6B,0},{0xe0,0xF0,0x6B,0} }, /*148*/ + { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {0xe0,0x74,0},{0xe0,0xF0,0x74,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {0xe0,0x69,0},{0xe0,0xF0,0x69,0} }, /*14c*/ + { {0xe0,0x72,0},{0xe0,0xF0,0x72,0} }, { {0xe0,0x7A,0},{0xe0,0xF0,0x7A,0} }, { {0xe0,0x70,0},{0xe0,0xF0,0x70,0} }, { {0xe0,0x71,0},{0xe0,0xF0,0x71,0} }, /*150*/ + { { 0},{ 0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ + { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {0xe0,0x1F,0},{0xe0,0xF0,0x1F,0} }, /*158*/ + { {0xe0,0x27,0},{0xe0,0xF0,0x27,0} }, { {0xe0,0x2F,0},{0xe0,0xF0,0x2F,0} }, { {0xe0,0x37,0},{0xe0,0xF0,0x37,0} }, { {0xe0,0x3F,0},{0xe0,0xF0,0x3F,0} }, /*15c*/ + { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {0xe0,0x5E,0},{0xe0,0xF0,0x5E,0} }, /*160*/ + { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ + { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ + { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ + { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ + { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ + { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ + { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ + + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ + { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ + { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ + // clang-format on +}; + +static const scancode scancode_set3[512] = { + // clang-format off + { { 0},{ 0} }, { { 0x08,0},{ 0xf0,0x08,0} }, { { 0x16,0},{ 0xf0,0x16,0} }, { { 0x1E,0},{ 0xf0,0x1E,0} }, /*000*/ + { { 0x26,0},{ 0xf0,0x26,0} }, { { 0x25,0},{ 0xf0,0x25,0} }, { { 0x2E,0},{ 0xf0,0x2E,0} }, { { 0x36,0},{ 0xf0,0x36,0} }, /*004*/ + { { 0x3D,0},{ 0xf0,0x3D,0} }, { { 0x3E,0},{ 0xf0,0x3E,0} }, { { 0x46,0},{ 0xf0,0x46,0} }, { { 0x45,0},{ 0xf0,0x45,0} }, /*008*/ + { { 0x4E,0},{ 0xf0,0x4E,0} }, { { 0x55,0},{ 0xf0,0x55,0} }, { { 0x66,0},{ 0xf0,0x66,0} }, { { 0x0D,0},{ 0xf0,0x0D,0} }, /*00c*/ + { { 0x15,0},{ 0xf0,0x15,0} }, { { 0x1D,0},{ 0xf0,0x1D,0} }, { { 0x24,0},{ 0xf0,0x24,0} }, { { 0x2D,0},{ 0xf0,0x2D,0} }, /*010*/ + { { 0x2C,0},{ 0xf0,0x2C,0} }, { { 0x35,0},{ 0xf0,0x35,0} }, { { 0x3C,0},{ 0xf0,0x3C,0} }, { { 0x43,0},{ 0xf0,0x43,0} }, /*014*/ + { { 0x44,0},{ 0xf0,0x44,0} }, { { 0x4D,0},{ 0xf0,0x4D,0} }, { { 0x54,0},{ 0xf0,0x54,0} }, { { 0x5B,0},{ 0xf0,0x5B,0} }, /*018*/ + { { 0x5A,0},{ 0xf0,0x5A,0} }, { { 0x11,0},{ 0xf0,0x11,0} }, { { 0x1C,0},{ 0xf0,0x1C,0} }, { { 0x1B,0},{ 0xf0,0x1B,0} }, /*01c*/ + { { 0x23,0},{ 0xf0,0x23,0} }, { { 0x2B,0},{ 0xf0,0x2B,0} }, { { 0x34,0},{ 0xf0,0x34,0} }, { { 0x33,0},{ 0xf0,0x33,0} }, /*020*/ + { { 0x3B,0},{ 0xf0,0x3B,0} }, { { 0x42,0},{ 0xf0,0x42,0} }, { { 0x4B,0},{ 0xf0,0x4B,0} }, { { 0x4C,0},{ 0xf0,0x4C,0} }, /*024*/ + { { 0x52,0},{ 0xf0,0x52,0} }, { { 0x0E,0},{ 0xf0,0x0E,0} }, { { 0x12,0},{ 0xf0,0x12,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, /*028*/ + { { 0x1A,0},{ 0xf0,0x1A,0} }, { { 0x22,0},{ 0xf0,0x22,0} }, { { 0x21,0},{ 0xf0,0x21,0} }, { { 0x2A,0},{ 0xf0,0x2A,0} }, /*02c*/ + { { 0x32,0},{ 0xf0,0x32,0} }, { { 0x31,0},{ 0xf0,0x31,0} }, { { 0x3A,0},{ 0xf0,0x3A,0} }, { { 0x41,0},{ 0xf0,0x41,0} }, /*030*/ + { { 0x49,0},{ 0xf0,0x49,0} }, { { 0x4A,0},{ 0xf0,0x4A,0} }, { { 0x59,0},{ 0xf0,0x59,0} }, { { 0x7E,0},{ 0xf0,0x7E,0} }, /*034*/ + { { 0x19,0},{ 0xf0,0x19,0} }, { { 0x29,0},{ 0xf0,0x29,0} }, { { 0x14,0},{ 0xf0,0x14,0} }, { { 0x07,0},{ 0xf0,0x07,0} }, /*038*/ + { { 0x0F,0},{ 0xf0,0x0F,0} }, { { 0x17,0},{ 0xf0,0x17,0} }, { { 0x1F,0},{ 0xf0,0x1F,0} }, { { 0x27,0},{ 0xf0,0x27,0} }, /*03c*/ + { { 0x2F,0},{ 0xf0,0x2F,0} }, { { 0x37,0},{ 0xf0,0x37,0} }, { { 0x3F,0},{ 0xf0,0x3F,0} }, { { 0x47,0},{ 0xf0,0x47,0} }, /*040*/ + { { 0x4F,0},{ 0xf0,0x4F,0} }, { { 0x76,0},{ 0xf0,0x76,0} }, { { 0x5F,0},{ 0xf0,0x5F,0} }, { { 0x6C,0},{ 0xf0,0x6C,0} }, /*044*/ + { { 0x75,0},{ 0xf0,0x75,0} }, { { 0x7D,0},{ 0xf0,0x7D,0} }, { { 0x84,0},{ 0xf0,0x84,0} }, { { 0x6B,0},{ 0xf0,0x6B,0} }, /*048*/ + { { 0x73,0},{ 0xf0,0x73,0} }, { { 0x74,0},{ 0xf0,0x74,0} }, { { 0x7C,0},{ 0xf0,0x7C,0} }, { { 0x69,0},{ 0xf0,0x69,0} }, /*04c*/ + { { 0x72,0},{ 0xf0,0x72,0} }, { { 0x7A,0},{ 0xf0,0x7A,0} }, { { 0x70,0},{ 0xf0,0x70,0} }, { { 0x71,0},{ 0xf0,0x71,0} }, /*050*/ + { { 0x57,0},{ 0xf0,0x57,0} }, { { 0x60,0},{ 0xf0,0x60,0} }, { { 0},{ 0} }, { { 0x56,0},{ 0xf0,0x56,0} }, /*054*/ + { { 0x5E,0},{ 0xf0,0x5E,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*058*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*05c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*060*/ + { { 0},{ 0} }, { { 0x10,0},{ 0xf0,0x10,0} }, { { 0x18,0},{ 0xf0,0x18,0} }, { { 0x20,0},{ 0xf0,0x20,0} }, /*064*/ + { { 0x28,0},{ 0xf0,0x28,0} }, { { 0x30,0},{ 0xf0,0x30,0} }, { { 0x38,0},{ 0xf0,0x38,0} }, { { 0x40,0},{ 0xf0,0x40,0} }, /*068*/ + { { 0x48,0},{ 0xf0,0x48,0} }, { { 0x50,0},{ 0xf0,0x50,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*06c*/ + { { 0x87,0},{ 0xf0,0x87,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0x51,0},{ 0xf0,0x51,0} }, /*070*/ + { { 0x53,0},{ 0xf0,0x53,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, { { 0},{ 0} }, { { 0x62,0},{ 0xf0,0x62,0} }, /*074*/ + { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x85,0} }, /*078*/ + { { 0x68,0},{ 0xf0,0x68,0} }, { { 0x13,0},{ 0xf0,0x13,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*07c*/ + + { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ + { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ + { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ + { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ + { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ + { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ + { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ + { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ + { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ + { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ + { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ + { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ + { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ + { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ + { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ + { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ + { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ + { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ + { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ + { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ + { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ + { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ + { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ + { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ + { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ + { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ + { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ + { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ + { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ + { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ + { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ + + { { 0x62,0},{ 0xF0,0x62,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ + { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ + { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ + { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ + { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ + { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ + { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ + { { 0x79,0},{ 0xf0,0x79,0} }, { { 0x58,0},{ 0xf0,0x58,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ + { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ + { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ + { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ + { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ + { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { { 0x77,0},{ 0xf0,0x77,0} }, { { 0},{ 0} }, { { 0x57,0},{ 0xf0,0x57,0} }, /*134*/ + { { 0x39,0},{ 0xf0,0x39,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ + { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ + { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ + { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { { 0x6E,0},{ 0xf0,0x6E,0} }, /*144*/ + { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x6F,0},{ 0xf0,0x6F,0} }, { { 0},{ 0} }, { { 0x61,0},{ 0xf0,0x61,0} }, /*148*/ + { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { { 0x6A,0},{ 0xf0,0x6A,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { { 0x65,0},{ 0xf0,0x65,0} }, /*14c*/ + { { 0x60,0},{ 0xf0,0x60,0} }, { { 0x6D,0},{ 0xf0,0x6D,0} }, { { 0x67,0},{ 0xf0,0x67,0} }, { { 0x64,0},{ 0xf0,0x64,0} }, /*150*/ + { { 0xd4,0},{ 0xf0,0xD4,0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ + { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { { 0x8B,0},{ 0xf0,0x8B,0} }, /*158*/ + { { 0x8C,0},{ 0xf0,0x8C,0} }, { { 0x8D,0},{ 0xf0,0x8D,0} }, { { 0},{ 0} }, { { 0x7F,0},{ 0xf0,0x7F,0} }, /*15c*/ + { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { { 0},{ 0} }, /*160*/ + { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ + { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ + { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ + { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ + { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ + { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ + { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ + + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ + { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ + { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ + { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ + { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ + // clang-format on +}; + +// #define ENABLE_KEYBOARD_AT_LOG 1 +#ifdef ENABLE_KEYBOARD_AT_LOG +int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; + +static void +kbd_log(const char *fmt, ...) +{ + va_list ap; + + if (keyboard_at_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define kbd_log(fmt, ...) +#endif + +static void +set_scancode_map(atkbd_t *dev) +{ + switch (keyboard_mode) { + case 1: + default: + keyboard_set_table(scancode_set1); + break; + case 2: + keyboard_set_table(scancode_set2); + break; + + case 3: + keyboard_set_table(scancode_set3); + break; + } +} + +static void +kbc_queue_reset(atkbd_t *dev, uint8_t channel) +{ + switch (channel) { + case 1: + dev->key_queue_start = dev->key_queue_end = 0; + memset(dev->key_queue, 0x00, sizeof(dev->key_queue)); + /* FALLTHROUGH */ + case 4: + dev->key_cmd_queue_start = dev->key_cmd_queue_end = 0; + memset(dev->key_cmd_queue, 0x00, sizeof(dev->key_cmd_queue)); + break; + + case 2: + dev->mouse_queue_start = dev->mouse_queue_end = 0; + memset(dev->mouse_queue, 0x00, sizeof(dev->mouse_queue)); + /* FALLTHROUGH */ + case 3: + dev->mouse_cmd_queue_start = dev->mouse_cmd_queue_end = 0; + memset(dev->mouse_cmd_queue, 0x00, sizeof(dev->mouse_cmd_queue)); + break; + + case 0: + default: + dev->key_ctrl_queue_start = dev->key_ctrl_queue_end = 0; + memset(dev->key_ctrl_queue, 0x00, sizeof(dev->key_ctrl_queue)); + } +} + +static void +kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel) +{ + switch (channel) { + case 4: + kbd_log("ATkbc: dev->key_cmd_queue[%02X] = %02X;\n", dev->key_cmd_queue_end, val); + dev->key_cmd_queue[dev->key_cmd_queue_end] = val; + dev->key_cmd_queue_end = (dev->key_cmd_queue_end + 1) & 0xf; + break; + case 3: + kbd_log("ATkbc: dev->mouse_cmd_queue[%02X] = %02X;\n", dev->mouse_cmd_queue_end, val); + dev->mouse_cmd_queue[dev->mouse_cmd_queue_end] = val; + dev->mouse_cmd_queue_end = (dev->mouse_cmd_queue_end + 1) & 0xf; + break; + case 2: + kbd_log("ATkbc: dev->mouse_queue[%02X] = %02X;\n", dev->mouse_queue_end, val); + dev->mouse_queue[dev->mouse_queue_end] = val; + dev->mouse_queue_end = (dev->mouse_queue_end + 1) & 0xf; + break; + case 1: + kbd_log("ATkbc: dev->key_queue[%02X] = %02X;\n", dev->key_queue_end, val); + dev->key_queue[dev->key_queue_end] = val; + dev->key_queue_end = (dev->key_queue_end + 1) & 0xf; + break; + case 0: + default: + kbd_log("ATkbc: dev->key_ctrl_queue[%02X] = %02X;\n", dev->key_ctrl_queue_end, val); + dev->key_ctrl_queue[dev->key_ctrl_queue_end] = val; + dev->key_ctrl_queue_end = (dev->key_ctrl_queue_end + 1) & 0x3f; + break; + } +} + +static int +kbc_translate(atkbd_t *dev, uint8_t val) +{ + int xt_mode = (dev->mem[0x20] & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); + int translate = (dev->mem[0x20] & 0x40) || xt_mode || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + int ret = - 1; + + /* Allow for scan code translation. */ + if (translate && (val == 0xf0)) { + kbd_log("ATkbd: translate is on, F0 prefix detected\n"); + dev->sc_or = 0x80; + return ret; + } + + /* Skip break code if translated make code has bit 7 set. */ + if (translate && (dev->sc_or == 0x80) && (nont_to_t[val] & 0x80)) { + kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); + dev->sc_or = 0; + return ret; + } + + /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ + if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && + (keyboard_recv(0x138) || keyboard_recv(0x11d))) switch (val) { + case 0x4f: + t3100e_notify_set(0x01); + break; /* End */ + case 0x50: + t3100e_notify_set(0x02); + break; /* Down */ + case 0x51: + t3100e_notify_set(0x03); + break; /* PgDn */ + case 0x52: + t3100e_notify_set(0x04); + break; /* Ins */ + case 0x53: + t3100e_notify_set(0x05); + break; /* Del */ + case 0x54: + t3100e_notify_set(0x06); + break; /* SysRQ */ + case 0x45: + t3100e_notify_set(0x07); + break; /* NumLock */ + case 0x46: + t3100e_notify_set(0x08); + break; /* ScrLock */ + case 0x47: + t3100e_notify_set(0x09); + break; /* Home */ + case 0x48: + t3100e_notify_set(0x0a); + break; /* Up */ + case 0x49: + t3100e_notify_set(0x0b); + break; /* PgUp */ + case 0x4a: + t3100e_notify_set(0x0c); + break; /* Keypad - */ + case 0x4b: + t3100e_notify_set(0x0d); + break; /* Left */ + case 0x4c: + t3100e_notify_set(0x0e); + break; /* KP 5 */ + case 0x4d: + t3100e_notify_set(0x0f); + break; /* Right */ + } + + kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); +#ifdef ENABLE_KEYBOARD_AT_LOG + kbd_log("scan code: "); + if (translate) { + kbd_log("%02X (original: ", (nont_to_t[val] | dev->sc_or)); + if (dev->sc_or == 0x80) + kbd_log("F0 "); + kbd_log("%02X)\n", val); + } else + kbd_log("%02X\n", val); +#endif + + ret = translate ? (nont_to_t[val] | dev->sc_or) : val; + + if (dev->sc_or == 0x80) + dev->sc_or = 0; + + return ret; +} + +static void +add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) +{ + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + int temp = (channel == 1) ? kbc_translate(dev, val) : val; + + if (temp == -1) + return; + + if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TG) || + (kbc_ven == KBC_VEN_TG_GREEN) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); + else + stat_hi |= 0x10; + + kbd_log("ATkbc: Adding %02X to front on channel %i...\n", temp, channel); + dev->status = (dev->status & ~0xf0) | STAT_OFULL | stat_hi; + + /* WARNING: On PS/2, all IRQ's are level-triggered, but the IBM PS/2 KBC firmware is explicitly + written to pulse its P2 IRQ bits, so they should be kept as as edge-triggered here. */ + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (channel >= 2) { + dev->status |= STAT_MFULL; + + if (dev->mem[0x20] & 0x02) + picint_common(1 << 12, 0, 1); + picint_common(1 << 1, 0, 0); + } else { + if (dev->mem[0x20] & 0x01) + picint_common(1 << 1, 0, 1); + picint_common(1 << 12, 0, 0); + } + } else if (dev->mem[0x20] & 0x01) + picintlevel(1 << 1); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */ + + dev->out = temp; +} + +static void +add_data_kbd_cmd_queue(atkbd_t *dev, uint8_t val) +{ + if (dev->key_cmd_queue_end >= 16) { + kbd_log("ATkbc: Unable to add to queue, dev->key_cmd_queue_end >= 16\n"); + return; + } + kbd_log("ATkbc: dev->key_cmd_queue[%02X] = %02X;\n", dev->key_cmd_queue_end, val); + kbc_queue_add(dev, val, 4); + dev->kbd_last_scan_code = val; +} + +static void +add_data_kbd_queue(atkbd_t *dev, uint8_t val) +{ + if (!keyboard_scan || (dev->key_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (dev->key_queue_end >= 16)); + return; + } + kbd_log("ATkbc: key_queue[%02X] = %02X;\n", dev->key_queue_end, val); + kbc_queue_add(dev, val, 1); + dev->kbd_last_scan_code = val; +} + +static void +add_data_kbd_front(atkbd_t *dev, uint8_t val) +{ + add_data_kbd_cmd_queue(dev, val); +} + +static void kbd_process_cmd(void *priv); +static void kbc_process_cmd(void *priv); + +static void +set_enable_kbd(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xef; + dev->mem[0x20] |= (enable ? 0x00 : 0x10); +} + +static void +set_enable_mouse(atkbd_t *dev, uint8_t enable) +{ + dev->mem[0x20] &= 0xdf; + dev->mem[0x20] |= (enable ? 0x00 : 0x20); +} + +static void +kbc_ibf_process(atkbd_t *dev) +{ + /* IBF set, process both commands and data. */ + dev->status &= ~STAT_IFULL; + dev->kbc_state = KBC_STATE_MAIN_IBF; + if (dev->status & STAT_CD) + kbc_process_cmd(dev); + else { + set_enable_kbd(dev, 1); + dev->key_wantcmd = 1; + dev->key_dat = dev->ib; + dev->kbc_state = KBC_STATE_SEND_KBD; + } +} + +static void +kbc_scan_kbd_at(atkbd_t *dev) +{ + if (!(dev->mem[0x20] & 0x10)) { + /* Both OBF and IBF clear and keyboard is enabled. */ + /* XT mode. */ + if (dev->mem[0x20] & 0x20) { + if (dev->out_new != -1) { + add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); + dev->out_new = -1; + dev->kbc_state = KBC_STATE_MAIN_IBF; + } else if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + /* AT mode. */ + } else { + // dev->t = dev->mem[0x28]; + if (dev->mem[0x2e] != 0x00) { + // if (!(dev->t & 0x02)) + // return; + dev->mem[0x2e] = 0x00; + } + dev->output_port &= 0xbf; + if (dev->out_new != -1) { + /* In our case, we never have noise on the line, so we can simplify this. */ + /* Read data from the keyboard. */ + if (dev->mem[0x20] & 0x40) { + if ((dev->mem[0x20] & 0x08) || (dev->input_port & 0x80)) + add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); + dev->mem[0x2d] = (dev->out_new == 0xf0) ? 0x80 : 0x00; + } else + add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); + dev->out_new = -1; + dev->kbc_state = KBC_STATE_MAIN_IBF; + } + } + } +} + +static void write_output(atkbd_t *dev, uint8_t val); + +static void +kbc_poll_at(atkbd_t *dev) +{ + switch (dev->kbc_state) { + case KBC_STATE_RESET: + if (dev->status & STAT_IFULL) { + dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL; + if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) + kbc_process_cmd(dev); + } + break; + case KBC_STATE_MAIN_IBF: + default: + if (dev->status & STAT_OFULL) { + /* OBF set, wait until it is cleared but still process commands. */ + if ((dev->status & STAT_IFULL) && (dev->status & STAT_CD)) { + dev->status &= ~STAT_IFULL; + kbc_process_cmd(dev); + } + } else if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else if (!(dev->mem[0x20] & 0x10)) + dev->kbc_state = KBC_STATE_MAIN_KBD; + break; + case KBC_STATE_MAIN_KBD: + case KBC_STATE_MAIN_BOTH: + if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else { + (void) kbc_scan_kbd_at(dev); + dev->kbc_state = KBC_STATE_MAIN_IBF; + } + break; + case KBC_STATE_KBC_OUT: + /* Keyboard controller command want to output multiple bytes. */ + if (dev->status & STAT_IFULL) { + /* Data from host aborts dumping. */ + dev->kbc_state = KBC_STATE_MAIN_IBF; + kbc_ibf_process(dev); + } + /* Do not continue dumping until OBF is clear. */ + if (!(dev->status & STAT_OFULL)) { + kbd_log("ATkbc: %02X coming from channel 0\n", dev->key_ctrl_queue[dev->key_ctrl_queue_start]); + add_to_kbc_queue_front(dev, dev->key_ctrl_queue[dev->key_ctrl_queue_start], 0, 0x00); + dev->key_ctrl_queue_start = (dev->key_ctrl_queue_start + 1) & 0x3f; + if (dev->key_ctrl_queue_start == dev->key_ctrl_queue_end) + dev->kbc_state = KBC_STATE_MAIN_IBF; + } + break; + case KBC_STATE_KBC_PARAM: + /* Keyboard controller command wants data, wait for said data. */ + if (dev->status & STAT_IFULL) { + /* Command written, abort current command. */ + if (dev->status & STAT_CD) + dev->kbc_state = KBC_STATE_MAIN_IBF; + + dev->status &= ~STAT_IFULL; + kbc_process_cmd(dev); + } + break; + case KBC_STATE_SEND_KBD: + if (!dev->key_wantcmd) + dev->kbc_state = KBC_STATE_SCAN_KBD; + break; + case KBC_STATE_SCAN_KBD: + kbc_scan_kbd_at(dev); + break; + } +} + +/* + Correct Procedure: + 1. Controller asks the device (keyboard or mouse) for a byte. + 2. The device, unless it's in the reset or command states, sees if there's anything to give it, + and if yes, begins the transfer. + 3. The controller checks if there is a transfer, if yes, transfers the byte and sends it to the host, + otherwise, checks the next device, or if there is no device left to check, checks if IBF is full + and if yes, processes it. + */ +static int +kbc_scan_kbd_ps2(atkbd_t *dev) +{ + if (dev->out_new != -1) { + kbd_log("ATkbc: %02X coming from channel 1\n", dev->out_new & 0xff); + add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); + dev->out_new = -1; + dev->kbc_state = KBC_STATE_MAIN_IBF; + return 1; + } + + return 0; +} + +static int +kbc_scan_aux_ps2(atkbd_t *dev) +{ + if (dev->out_new_mouse != -1) { + kbd_log("ATkbc: %02X coming from channel 2\n", dev->out_new_mouse & 0xff); + add_to_kbc_queue_front(dev, dev->out_new_mouse, 2, 0x00); + dev->out_new_mouse = -1; + dev->kbc_state = KBC_STATE_MAIN_IBF; + return 1; + } + + return 0; +} + +static void +kbc_poll_ps2(atkbd_t *dev) +{ + switch (dev->kbc_state) { + case KBC_STATE_RESET: + if (dev->status & STAT_IFULL) { + dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL; + if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) + kbc_process_cmd(dev); + } + break; + case KBC_STATE_MAIN_IBF: + default: + if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else if (!(dev->status & STAT_OFULL)) { + if (dev->mem[0x20] & 0x20) { + if (!(dev->mem[0x20] & 0x10)) { + dev->output_port &= 0xbf; + dev->kbc_state = KBC_STATE_MAIN_KBD; + } + } else { + dev->output_port &= 0xf7; + if (dev->mem[0x20] & 0x10) + dev->kbc_state = KBC_STATE_MAIN_MOUSE; + else { + dev->output_port &= 0xbf; + dev->kbc_state = KBC_STATE_MAIN_BOTH; + } + } + } + break; + case KBC_STATE_MAIN_KBD: + if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else { + (void) kbc_scan_kbd_ps2(dev); + dev->kbc_state = KBC_STATE_MAIN_IBF; + } + break; + case KBC_STATE_MAIN_MOUSE: + if (dev->status & STAT_IFULL) + kbc_ibf_process(dev); + else { + (void) kbc_scan_aux_ps2(dev); + dev->kbc_state = KBC_STATE_MAIN_IBF; + } + break; + case KBC_STATE_MAIN_BOTH: + if (kbc_scan_kbd_ps2(dev)) + dev->kbc_state = KBC_STATE_MAIN_IBF; + else + dev->kbc_state = KBC_STATE_MAIN_MOUSE; + break; + case KBC_STATE_KBC_OUT: + /* Keyboard controller command want to output multiple bytes. */ + if (dev->status & STAT_IFULL) { + /* Data from host aborts dumping. */ + dev->kbc_state = KBC_STATE_MAIN_IBF; + kbc_ibf_process(dev); + } + /* Do not continue dumping until OBF is clear. */ + if (!(dev->status & STAT_OFULL)) { + kbd_log("ATkbc: %02X coming from channel 0\n", dev->out_new & 0xff); + add_to_kbc_queue_front(dev, dev->key_ctrl_queue[dev->key_ctrl_queue_start], 0, 0x00); + dev->key_ctrl_queue_start = (dev->key_ctrl_queue_start + 1) & 0x3f; + if (dev->key_ctrl_queue_start == dev->key_ctrl_queue_end) + dev->kbc_state = KBC_STATE_MAIN_IBF; + } + break; + case KBC_STATE_KBC_PARAM: + /* Keyboard controller command wants data, wait for said data. */ + if (dev->status & STAT_IFULL) { + /* Command written, abort current command. */ + if (dev->status & STAT_CD) + dev->kbc_state = KBC_STATE_MAIN_IBF; + + dev->status &= ~STAT_IFULL; + kbc_process_cmd(dev); + } + break; + case KBC_STATE_SEND_KBD: + if (!dev->key_wantcmd) + dev->kbc_state = KBC_STATE_SCAN_KBD; + break; + case KBC_STATE_SCAN_KBD: + (void) kbc_scan_kbd_ps2(dev); + break; + case KBC_STATE_SEND_MOUSE: + if (!dev->mouse_wantcmd) + dev->kbc_state = KBC_STATE_SCAN_MOUSE; + break; + case KBC_STATE_SCAN_MOUSE: + (void) kbc_scan_aux_ps2(dev); + break; + } +} + +static void +kbc_poll_kbd(atkbd_t *dev) +{ + switch (dev->kbd_state) { + case DEV_STATE_MAIN_1: + /* Process the command if needed and then return to main loop #2. */ + if (dev->key_wantcmd) { + kbd_log("ATkbc: Processing keyboard command %02X...\n", dev->key_dat); + kbc_queue_reset(dev, 4); + // dev->out_new = -1; + kbd_process_cmd(dev); + dev->key_wantcmd = 0; + } else + dev->kbd_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 (keyboard_scan && (dev->out_new == -1) && (dev->key_queue_start != dev->key_queue_end)) { + kbd_log("ATkbc: %02X (DATA) on channel 1\n", dev->key_queue[dev->key_queue_start]); + dev->out_new = dev->key_queue[dev->key_queue_start]; + dev->key_queue_start = (dev->key_queue_start + 1) & 0xf; + } + if (!keyboard_scan || dev->key_wantcmd) + dev->kbd_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->key_wantcmd) { + kbd_log("ATkbc: Processing keyboard command %02X...\n", dev->key_dat); + kbc_queue_reset(dev, 4); + kbd_process_cmd(dev); + dev->key_wantcmd = 0; + break; + } + /* FALLTHROUGH */ + case DEV_STATE_MAIN_WANT_IN: + /* Output command response and then wait for host data. */ + if ((dev->out_new == -1) && (dev->key_cmd_queue_start != dev->key_cmd_queue_end)) { + kbd_log("ATkbc: %02X (CMD ) on channel 1\n", dev->key_cmd_queue[dev->key_cmd_queue_start]); + dev->out_new = dev->key_cmd_queue[dev->key_cmd_queue_start]; + dev->key_cmd_queue_start = (dev->key_cmd_queue_start + 1) & 0xf; + } + if (dev->key_cmd_queue_start == dev->key_cmd_queue_end) + dev->kbd_state = (dev->kbd_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->key_wantcmd) { + kbd_log("ATkbc: Processing keyboard command %02X parameter %02X...\n", dev->key_command, dev->key_dat); + kbc_queue_reset(dev, 4); + // dev->out_new = -1; + kbd_process_cmd(dev); + dev->key_wantcmd = 0; + } + break; + } +} + +static void +kbc_poll_aux(atkbd_t *dev) +{ + switch (dev->mouse_state) { + case DEV_STATE_MAIN_1: + /* Process the command if needed and then return to main loop #2. */ + if (dev->mouse_wantcmd) { + kbd_log("ATkbc: Processing mouse command %02X...\n", dev->mouse_dat); + kbc_queue_reset(dev, 3); + // dev->out_new_mouse = -1; + dev->mouse_state = DEV_STATE_MAIN_OUT; + mouse_write(dev->mouse_dat, mouse_p); + if ((dev->mouse_dat == 0xe8) || (dev->mouse_dat == 0xf3)) + dev->mouse_state = DEV_STATE_MAIN_WANT_IN; + dev->mouse_wantcmd = 0; + } else + dev->mouse_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 (mouse_scan && (dev->out_new_mouse == -1) && (dev->mouse_queue_start != dev->mouse_queue_end)) { + kbd_log("ATkbc: %02X (DATA) on channel 2\n", dev->mouse_queue[dev->mouse_queue_start]); + dev->out_new_mouse = dev->mouse_queue[dev->mouse_queue_start]; + dev->mouse_queue_start = (dev->mouse_queue_start + 1) & 0xf; + } + if (!mouse_scan || dev->mouse_wantcmd) + dev->mouse_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->mouse_wantcmd) { + kbd_log("ATkbc: Processing mouse command %02X...\n", dev->mouse_dat); + kbc_queue_reset(dev, 3); + dev->mouse_state = DEV_STATE_MAIN_OUT; + mouse_write(dev->mouse_dat, mouse_p); + if ((dev->mouse_dat == 0xe8) || (dev->mouse_dat == 0xf3)) + dev->mouse_state = DEV_STATE_MAIN_WANT_IN; + dev->mouse_wantcmd = 0; + break; + } + /* FALLTHROUGH */ + case DEV_STATE_MAIN_WANT_IN: + /* Output command response and then wait for host data. */ + if ((dev->out_new_mouse == -1) && (dev->mouse_cmd_queue_start != dev->mouse_cmd_queue_end)) { + kbd_log("ATkbc: %02X (CMD ) on channel 2\n", dev->mouse_cmd_queue[dev->mouse_cmd_queue_start]); + dev->out_new_mouse = dev->mouse_cmd_queue[dev->mouse_cmd_queue_start]; + dev->mouse_cmd_queue_start = (dev->mouse_cmd_queue_start + 1) & 0xf; + } + if (dev->mouse_cmd_queue_start == dev->mouse_cmd_queue_end) + dev->mouse_state = (dev->mouse_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->mouse_wantcmd) { + kbd_log("ATkbc: Processing mouse command parameter %02X...\n", dev->mouse_dat); + kbc_queue_reset(dev, 3); + // dev->out_new_mouse = -1; + dev->mouse_state = DEV_STATE_MAIN_OUT; + mouse_write(dev->mouse_dat, mouse_p); + dev->mouse_wantcmd = 0; + } + break; + } +} + +/* TODO: State machines for controller, keyboard, and mouse. */ +static void +kbd_poll(void *priv) +{ + atkbd_t *dev = (atkbd_t *) priv; + + timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); + + /* TODO: Use a fuction pointer for this (also needed to the AMI KBC mode switching) + and implement the password security state. */ + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + kbc_poll_ps2(dev); + else + kbc_poll_at(dev); + + kbc_poll_kbd(dev); + + if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && mouse_write) + kbc_poll_aux(dev); + + // if (kbc_ports[0] && kbc_ports[0]>-priv) + // kbc_ports[0]>poll(kbc_ports[0]>-priv); + + // if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && kbc_ports[1] && kbc_ports[1]>-priv) + // kbc_ports[1]>poll(kbc_ports[1]>-priv); +} + +static void +add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) +{ + int i; + + for (i = 0; i < len; i++) + add_data_kbd_queue(dev, val[i]); +} + +static void +add_data_kbd(uint16_t val) +{ + atkbd_t *dev = SavedKbd; + uint8_t fake_shift[4]; + uint8_t num_lock = 0, shift_states = 0; + + keyboard_get_states(NULL, &num_lock, NULL); + shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; + + switch (val) { + case FAKE_LSHIFT_ON: + kbd_log("fake left shift on, scan code: "); + if (num_lock) { + if (shift_states) { + kbd_log("N/A (one or both shifts on)\n"); + break; + } else { + /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x2a; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x12; + add_data_vals(dev, fake_shift, 2); + break; + + default: + kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + } else { + if (shift_states & STATE_LSHIFT) { + /* Num lock off and left shift pressed. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xaa; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xf0; + fake_shift[2] = 0x12; + add_data_vals(dev, fake_shift, 3); + break; + + default: + kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + if (shift_states & STATE_RSHIFT) { + /* Num lock off and right shift pressed. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xb6; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xf0; + fake_shift[2] = 0x59; + add_data_vals(dev, fake_shift, 3); + break; + + default: + kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + kbd_log(shift_states ? "" : "N/A (both shifts off)\n"); + } + break; + + case FAKE_LSHIFT_OFF: + kbd_log("fake left shift on, scan code: "); + if (num_lock) { + if (shift_states) { + kbd_log("N/A (one or both shifts on)\n"); + break; + } else { + /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xaa; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0xf0; + fake_shift[2] = 0x12; + add_data_vals(dev, fake_shift, 3); + break; + + default: + kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + } else { + if (shift_states & STATE_LSHIFT) { + /* Num lock off and left shift pressed. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x2a; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x12; + add_data_vals(dev, fake_shift, 2); + break; + + default: + kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + if (shift_states & STATE_RSHIFT) { + /* Num lock off and right shift pressed. */ + switch (keyboard_mode & 0x02) { + case 1: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x36; + add_data_vals(dev, fake_shift, 2); + break; + + case 2: + fake_shift[0] = 0xe0; + fake_shift[1] = 0x59; + add_data_vals(dev, fake_shift, 2); + break; + + default: + kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); + break; + } + } + kbd_log(shift_states ? "" : "N/A (both shifts off)\n"); + } + break; + + default: + add_data_kbd_queue(dev, val); + break; + } +} + +static void +write_output(atkbd_t *dev, uint8_t val) +{ + uint8_t old = dev->output_port; + kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); + + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + +#if 0 + /* PS/2: Handle IRQ's. */ + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + /* IRQ 12 */ + picint_common(1 << 12, 0, val & 0x20); + + /* IRQ 1 */ + picint_common(1 << 1, 0, val & 0x10); + } +#endif + + /* AT, PS/2: Handle A20. */ + if ((old ^ val) & 0x02) { /* A20 enable change */ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + + /* AT, PS/2: Handle reset. */ + /* 0 holds the CPU in the RESET state, 1 releases it. To simplify this, + we just do everything on release. */ + if ((old ^ val) & 0x01) { /*Reset*/ + if (!(val & 0x01)) { /* Pin 0 selected. */ + /* Pin 0 selected. */ + kbd_log("write_output(): Pulse reset!\n"); + if (machines[machine].flags & MACHINE_COREBOOT) { + /* The SeaBIOS hard reset code attempts a KBC reset if ACPI RESET_REG + is not available. However, the KBC reset is normally a soft reset, so + SeaBIOS gets caught in a soft reset loop as it tries to hard reset the + machine. Hack around this by making the KBC reset a hard reset only on + coreboot machines. */ + pc_reset_hard(); + } else { + softresetx86(); /*Pulse reset!*/ + cpu_set_edx(); + flushmmucache(); + if (kbc_ven == KBC_VEN_ALI) + smbase = 0x00030000; + } + } + } + + /* Do this here to avoid an infinite reset loop. */ + dev->output_port = val; +} + +static void +write_output_fast_a20(atkbd_t *dev, uint8_t val) +{ + uint8_t old = dev->output_port; + kbd_log("ATkbc: write output port in fast A20 mode: %02X (old: %02X)\n", val, dev->output_port); + + /* AT, PS/2: Handle A20. */ + if ((old ^ val) & 0x02) { /* A20 enable change */ + mem_a20_key = val & 0x02; + mem_a20_recalc(); + flushmmucache(); + } + + /* Do this here to avoid an infinite reset loop. */ + dev->output_port = val; +} + +static void +write_cmd(atkbd_t *dev, uint8_t val) +{ + kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); + + /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ + if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { + val &= ~CCB_TRANSLATE; + dev->mem[0x20] &= ~CCB_TRANSLATE; + } else if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + if (val & 0x10) + dev->mem[0x2e] = 0x01; + } + + kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); + + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + /* Update the output port to mirror the IBF and OBF bits, if active. */ + write_output(dev, (dev->output_port & 0x0f) | ((val & 0x03) << 4) | ((val & 0x20) ? 0xc0 : 0x00)); + } + + kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); + + dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); +} + +static void +pulse_output(atkbd_t *dev, uint8_t mask) +{ + if (mask != 0x0f) { + dev->old_output_port = dev->output_port & ~(0xf0 | mask); + kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); + write_output(dev, dev->output_port & (0xf0 | mask)); + timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); + } +} + +static void +pulse_poll(void *priv) +{ + atkbd_t *dev = (atkbd_t *) priv; + + kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); + write_output(dev, dev->output_port | dev->old_output_port); +} + +static uint8_t +write64_generic(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + uint8_t current_drive, fixed_bits; + uint8_t kbc_ven = 0x0; + kbc_ven = dev->flags & KBC_VEN_MASK; + + switch (val) { + case 0xa4: /* check if password installed */ + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: check if password installed\n"); + add_to_kbc_queue_front(dev, 0xf1, 0, 0x00); + return 0; + } + break; + + case 0xa7: /* disable mouse port */ + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: disable mouse port\n"); + set_enable_mouse(dev, 0); + return 0; + } + break; + + case 0xa8: /*Enable mouse port*/ + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: enable mouse port\n"); + set_enable_mouse(dev, 1); + return 0; + } + break; + + case 0xa9: /*Test mouse port*/ + kbd_log("ATkbc: test mouse port\n"); + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); /* no error, this is testing the channel 2 interface */ + return 0; + } + break; + + case 0xaf: /* read keyboard version */ + kbd_log("ATkbc: read keyboard version\n"); + add_to_kbc_queue_front(dev, 0x42, 0, 0x00); + return 0; + + case 0xc0: /* read input port */ + kbd_log("ATkbc: read input port\n"); + fixed_bits = 4; + /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ + if (kbc_ven == KBC_VEN_INTEL_AMI) + fixed_bits |= 0x40; + if (kbc_ven == KBC_VEN_IBM_PS1) { + current_drive = fdc_get_current_drive(); + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), + 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); + } else if (kbc_ven == KBC_VEN_NCR) { + /* switch settings + * bit 7: keyboard disable + * bit 6: display type (0 color, 1 mono) + * bit 5: power-on default speed (0 high, 1 low) + * bit 4: sense RAM size (0 unsupported, 1 512k on system board) + * bit 3: coprocessor detect + * bit 2: unused + * bit 1: high/auto speed + * bit 0: dma mode + */ + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, + 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc); + } else { + if ((kbc_ven == KBC_VEN_TG) || (kbc_ven == KBC_VEN_TG_GREEN)) { + /* Bit 3, 2: + 1, 1: TriGem logo; + 1, 0: Garbled logo; + 0, 1: Epson logo; + 0, 0: Generic AMI logo. */ + if (dev->pci) + fixed_bits |= 8; + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); + } else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) +#if 0 + add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & + (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); +#else + add_to_kbc_queue_front(dev, ((dev->input_port | fixed_bits) & 0xf0) | (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c), 0, 0x00); +#endif + else + add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc); + } + return 0; + + case 0xd3: /* write mouse output buffer */ + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: write mouse output buffer\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + return 0; + } + break; + + case 0xd4: /* write to mouse */ + kbd_log("ATkbc: write to mouse\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + return 0; + + case 0xf0 ... 0xff: + kbd_log("ATkbc: pulse %01X\n", val & 0x0f); + pulse_output(dev, val & 0x0f); + return 0; + } + + kbd_log("ATkbc: bad command %02X\n", val); + return 1; +} + +static uint8_t +write60_ami(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + + switch (dev->command) { + /* 0x40 - 0x5F are aliases for 0x60-0x7F */ + case 0x40 ... 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->mem[(dev->command & 0x1f) + 0x20] = val; + if (dev->command == 0x60) + write_cmd(dev, val); + return 0; + + case 0xa5: /* get extended controller RAM */ + kbd_log("ATkbc: AMI - get extended controller RAM\n"); + add_to_kbc_queue_front(dev, dev->mem[val], 0, 0x00); + return 0; + + case 0xaf: /* set extended controller RAM */ + kbd_log("ATkbc: AMI - set extended controller RAM\n"); + if (dev->secr_phase == 1) { + dev->mem_addr = val; + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + dev->secr_phase = 2; + } else if (dev->secr_phase == 2) { + dev->mem[dev->mem_addr] = val; + dev->secr_phase = 0; + } + return 0; + + case 0xc1: + kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); + dev->input_port = val; + return 0; + + case 0xcb: /* set keyboard mode */ + kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->ami_flags = val; + return 0; + } + + return 1; +} + +static uint8_t +write64_ami(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + switch (val) { + case 0x00 ... 0x1f: + kbd_log("ATkbc: AMI - alias read from %08X\n", val); + add_to_kbc_queue_front(dev, dev->mem[val + 0x20], 0, 0x00); + return 0; + + case 0x40 ... 0x5f: + kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + return 0; + + case 0xa0: /* copyright message */ + kbc_queue_add(dev, 0x28, 0); + kbc_queue_add(dev, 0x00, 0); + dev->kbc_state = KBC_STATE_KBC_OUT; + break; + + case 0xa1: /* get controller version */ + kbd_log("ATkbc: AMI - get controller version\n"); + if ((kbc_ven == KBC_VEN_TG) || (kbc_ven == KBC_VEN_TG_GREEN)) + add_to_kbc_queue_front(dev, 'Z', 0, 0x00); + else if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (kbc_ven == KBC_VEN_ALI) + add_to_kbc_queue_front(dev, 'F', 0, 0x00); + else if ((dev->flags & KBC_VEN_MASK) == KBC_VEN_INTEL_AMI) + add_to_kbc_queue_front(dev, '5', 0, 0x00); + else if (cpu_64bitbus) + add_to_kbc_queue_front(dev, 'R', 0, 0x00); + else if (is486) + add_to_kbc_queue_front(dev, 'P', 0, 0x00); + else + add_to_kbc_queue_front(dev, 'H', 0, 0x00); + } else if (is386 && !is486) { + if (cpu_16bitbus) + add_to_kbc_queue_front(dev, 'D', 0, 0x00); + else + add_to_kbc_queue_front(dev, 'B', 0, 0x00); + } else if (!is386) + add_to_kbc_queue_front(dev, '8', 0, 0x00); + else + add_to_kbc_queue_front(dev, 'F', 0, 0x00); + return 0; + + case 0xa2: /* clear keyboard controller lines P22/P23 */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); + write_output(dev, dev->output_port & 0xf3); + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + } + break; + + case 0xa3: /* set keyboard controller lines P22/P23 */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); + write_output(dev, dev->output_port | 0x0c); + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + } + break; + + case 0xa4: /* write clock = low */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: AMI - write clock = low\n"); + dev->ami_stat &= 0xfe; + return 0; + } + break; + + case 0xa5: /* write clock = high */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: AMI - write clock = high\n"); + dev->ami_stat |= 0x01; + } else { + kbd_log("ATkbc: get extended controller RAM\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + } + return 0; + + case 0xa6: /* read clock */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: AMI - read clock\n"); + add_to_kbc_queue_front(dev, (dev->ami_stat & 1) ? 0xff : 0x00, 0, 0x00); + return 0; + } + break; + + case 0xa7: /* write cache bad */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: AMI - write cache bad\n"); + dev->ami_stat &= 0xfd; + return 0; + } + break; + + case 0xa8: /* write cache good */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: AMI - write cache good\n"); + dev->ami_stat |= 0x02; + return 0; + } + break; + + case 0xa9: /* read cache */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: AMI - read cache\n"); + add_to_kbc_queue_front(dev, (dev->ami_stat & 2) ? 0xff : 0x00, 0, 0x00); + return 0; + } + break; + + case 0xaf: /* set extended controller RAM */ + if (kbc_ven == KBC_VEN_ALI) { + kbd_log("ATkbc: Award/ALi/VIA keyboard controller revision\n"); + add_to_kbc_queue_front(dev, 0x43, 0, 0x00); + } else { + kbd_log("ATkbc: set extended controller RAM\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + dev->secr_phase = 1; + } + return 0; + + case 0xb0 ... 0xb3: + /* set KBC lines P10-P13 (input port bits 0-3) low */ + kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); + if (!(dev->flags & DEVICE_PCI) || (val > 0xb1)) + dev->input_port &= ~(1 << (val & 0x03)); + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + + case 0xb4: case 0xb5: + /* set KBC lines P22-P23 (output port bits 2-3) low */ + kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); + if (!(dev->flags & DEVICE_PCI)) + write_output(dev, dev->output_port & ~(4 << (val & 0x01))); + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + + case 0xb8 ... 0xbb: + /* set KBC lines P10-P13 (input port bits 0-3) high */ + kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); + if (!(dev->flags & DEVICE_PCI) || (val > 0xb9)) { + dev->input_port |= (1 << (val & 0x03)); + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + } + return 0; + + case 0xbc: case 0xbd: + /* set KBC lines P22-P23 (output port bits 2-3) high */ + kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); + if (!(dev->flags & DEVICE_PCI)) + write_output(dev, dev->output_port | (4 << (val & 0x01))); + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + + case 0xc1: /* write input port */ + kbd_log("ATkbc: AMI MegaKey - write input port\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + return 0; + + case 0xc4: + /* set KBC line P14 low */ + kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); + dev->input_port &= 0xef; + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + case 0xc5: + /* set KBC line P15 low */ + kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); + dev->input_port &= 0xdf; + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + + case 0xc8: + /* + * unblock KBC lines P22/P23 + * (allow command D1 to change bits 2/3 of the output port) + */ + kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); + dev->ami_flags &= 0xfb; + return 0; + + case 0xc9: + /* + * block KBC lines P22/P23 + * (disallow command D1 from changing bits 2/3 of the port) + */ + kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); + dev->ami_flags |= 0x04; + return 0; + + case 0xcc: + /* set KBC line P14 high */ + kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); + dev->input_port |= 0x10; + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + case 0xcd: + /* set KBC line P15 high */ + kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); + dev->input_port |= 0x20; + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + + case 0xef: /* ??? - sent by AMI486 */ + kbd_log("ATkbc: ??? - sent by AMI486\n"); + return 0; + } + + return write64_generic(dev, val); +} + +static uint8_t +write64_ibm_mca(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + + switch (val) { + case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ + kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); + dev->status &= 0x0f; + dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); + return 0; + + case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ + kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); + dev->status &= 0x0f; + dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); + return 0; + + case 0xaf: + kbd_log("ATkbc: bad KBC command AF\n"); + return 1; + + case 0xf0 ... 0xff: + kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); + pulse_output(dev, (val & 0x03) | 0x0c); + return 0; + } + + return write64_generic(dev, val); +} + +static uint8_t +write60_quadtel(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + + switch (dev->command) { + case 0xcf: /*??? - sent by MegaPC BIOS*/ + kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); + return 0; + } + + return 1; +} + +static uint8_t +write64_olivetti(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + + switch (val) { + case 0x80: /* Olivetti-specific command */ + /* + * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) + * bits 4-6: ??? + * bit 3: fast ram check (if inactive keyboard works erratically) + * bit 2: keyboard fuse present + * bits 0-1: ??? + */ + add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); + dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc); + return 0; + } + + return write64_generic(dev, val); +} + +static uint8_t +write64_quadtel(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + + switch (val) { + case 0xaf: + kbd_log("ATkbc: bad KBC command AF\n"); + return 1; + + case 0xcf: /*??? - sent by MegaPC BIOS*/ + kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + return 0; + } + + return write64_generic(dev, val); +} + +static uint8_t +write60_toshiba(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + + switch (dev->command) { + case 0xb6: /* T3100e - set color/mono switch */ + kbd_log("ATkbc: T3100e - set color/mono switch\n"); + t3100e_mono_set(val); + return 0; + } + + return 1; +} + +static uint8_t +write64_toshiba(void *priv, uint8_t val) +{ + atkbd_t *dev = (atkbd_t *) priv; + + switch (val) { + case 0xaf: + kbd_log("ATkbc: bad KBC command AF\n"); + return 1; + + case 0xb0: /* T3100e: Turbo on */ + kbd_log("ATkbc: T3100e: Turbo on\n"); + t3100e_turbo_set(1); + return 0; + + case 0xb1: /* T3100e: Turbo off */ + kbd_log("ATkbc: T3100e: Turbo off\n"); + t3100e_turbo_set(0); + return 0; + + case 0xb2: /* T3100e: Select external display */ + kbd_log("ATkbc: T3100e: Select external display\n"); + t3100e_display_set(0x00); + return 0; + + case 0xb3: /* T3100e: Select internal display */ + kbd_log("ATkbc: T3100e: Select internal display\n"); + t3100e_display_set(0x01); + return 0; + + case 0xb4: /* T3100e: Get configuration / status */ + kbd_log("ATkbc: T3100e: Get configuration / status\n"); + add_to_kbc_queue_front(dev, t3100e_config_get(), 0, 0x00); + return 0; + + case 0xb5: /* T3100e: Get colour / mono byte */ + kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); + add_to_kbc_queue_front(dev, t3100e_mono_get(), 0, 0x00); + return 0; + + case 0xb6: /* T3100e: Set colour / mono byte */ + kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + return 0; + + case 0xb7: /* T3100e: Emulate PS/2 keyboard */ + case 0xb8: /* T3100e: Emulate AT keyboard */ + dev->flags &= ~KBC_TYPE_MASK; + if (val == 0xb7) { + kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); + dev->flags |= KBC_TYPE_PS2_NOREF; + } else { + kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); + dev->flags |= KBC_TYPE_ISA; + } + return 0; + + case 0xbb: /* T3100e: Read 'Fn' key. + Return it for right Ctrl and right Alt; on the real + T3100e, these keystrokes could only be generated + using 'Fn'. */ + kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); + if (keyboard_recv(0xb8) || /* Right Alt */ + keyboard_recv(0x9d)) /* Right Ctrl */ + add_to_kbc_queue_front(dev, 0x04, 0, 0x00); + else + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + return 0; + + case 0xbc: /* T3100e: Reset Fn+Key notification */ + kbd_log("ATkbc: T3100e: Reset Fn+Key notification\n"); + t3100e_notify_set(0x00); + return 0; + + case 0xc0: /*Read input port*/ + kbd_log("ATkbc: read input port\n"); + + /* The T3100e returns all bits set except bit 6 which + * is set by t3100e_mono_set() */ + dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; + add_to_kbc_queue_front(dev, dev->input_port, 0, 0x00); + return 0; + } + + return write64_generic(dev, val); +} + +static void +kbd_key_reset(atkbd_t *dev, int do_fa) +{ + dev->out_new = -1; + kbc_queue_reset(dev, 1); + + dev->kbd_last_scan_code = 0x00; + + /* Set scan code set to 2. */ + keyboard_mode = 0x02; + set_scancode_map(dev); + + /* The BAT enables scanning. */ + keyboard_scan = 1; + + dev->sc_or = 0; + + if (do_fa) + add_data_kbd_front(dev, 0xfa); + add_data_kbd_front(dev, 0xaa); + + if (!do_fa) + dev->kbd_state = DEV_STATE_MAIN_OUT; +} + +static void +kbd_aux_reset(atkbd_t *dev, int do_fa) +{ + dev->out_new_mouse = -1; + kbc_queue_reset(dev, 2); + + /* The BAT enables scanning. */ + mouse_scan = 1; + + if (!do_fa) { + add_data_kbd_front(dev, 0xaa); + add_data_kbd_front(dev, 0x00); + + dev->mouse_state = DEV_STATE_MAIN_OUT; + } +} + +void +keyboard_at_mouse_reset(void) +{ + atkbd_t *dev = SavedKbd; + + kbd_aux_reset(dev, 1); +} + +static void +kbd_process_cmd(void *priv) +{ + atkbd_t *dev = (atkbd_t *) priv; + + dev->kbd_state = DEV_STATE_MAIN_OUT; + + if (dev->key_wantdata) { + dev->key_wantdata = 0; + + /* + * Several system BIOSes and OS device drivers + * mess up with this, and repeat the command + * code many times. Fun! + */ + if (dev->key_dat == dev->key_command) { + /* Respond NAK and ignore it. */ + add_data_kbd_front(dev, 0xfe); + dev->key_command = 0x00; + return; + } + + switch (dev->key_command) { + case 0xed: /* set/reset LEDs */ + add_data_kbd_front(dev, 0xfa); + kbd_log("ATkbd: set LEDs [%02x]\n", dev->key_dat); + break; + + case 0xf0: /* get/set scancode set */ + add_data_kbd_front(dev, 0xfa); + if (dev->key_dat == 0) { + kbd_log("Get scan code set: %02X\n", keyboard_mode); + add_data_kbd_front(dev, keyboard_mode); + } else { + if (dev->key_dat <= 3) { + keyboard_mode = dev->key_dat; + kbd_log("Scan code set now: %02X\n", keyboard_mode); + } + set_scancode_map(dev); + } + break; + + case 0xf3: /* set typematic rate/delay */ + add_data_kbd_front(dev, 0xfa); + break; + + default: + kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", dev->key_dat, dev->key_command); + add_data_kbd_front(dev, 0xfe); + break; + } + + /* Keyboard command is now done. */ + dev->key_command = 0x00; + } else { + /* No keyboard command in progress. */ + dev->key_command = 0x00; + + switch (dev->key_dat) { + case 0x00 ... 0x7f: + kbd_log("ATkbd: invalid command %02X\n", dev->key_dat); + add_data_kbd_front(dev, 0xfe); + break; + + case 0xed: /* set/reset LEDs */ + kbd_log("ATkbd: set/reset leds\n"); + add_data_kbd_front(dev, 0xfa); + + dev->key_wantdata = 1; + dev->kbd_state = DEV_STATE_MAIN_WANT_IN; + break; + + case 0xee: /* diagnostic echo */ + kbd_log("ATkbd: ECHO\n"); + add_data_kbd_front(dev, 0xee); + break; + + case 0xef: /* NOP (reserved for future use) */ + kbd_log("ATkbd: NOP\n"); + break; + + case 0xf0: /* get/set scan code set */ + kbd_log("ATkbd: scan code set\n"); + add_data_kbd_front(dev, 0xfa); + dev->key_wantdata = 1; + dev->kbd_state = DEV_STATE_MAIN_WANT_IN; + break; + + case 0xf2: /* read ID */ + kbd_log("ATkbd: read keyboard id\n"); + /* TODO: After keyboard type selection is implemented, make this + return the correct keyboard ID for the selected type. */ + add_data_kbd_front(dev, 0xfa); + add_data_kbd_front(dev, 0xab); + add_data_kbd_front(dev, 0x83); + break; + + case 0xf3: /* set typematic rate/delay */ + kbd_log("ATkbd: set typematic rate/delay\n"); + add_data_kbd_front(dev, 0xfa); + dev->key_wantdata = 1; + dev->kbd_state = DEV_STATE_MAIN_WANT_IN; + break; + + case 0xf4: /* enable keyboard */ + kbd_log("ATkbd: enable keyboard\n"); + add_data_kbd_front(dev, 0xfa); + keyboard_scan = 1; + break; + + case 0xf5: /* set defaults and disable keyboard */ + case 0xf6: /* set defaults */ + kbd_log("ATkbd: set defaults%s\n", (dev->key_dat == 0xf6) ? "" : " and disable keyboard"); + keyboard_scan = (dev->key_dat == 0xf6); + kbd_log("dev->key_dat = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", + dev->key_dat, keyboard_scan, dev->mem[0]); + add_data_kbd_front(dev, 0xfa); + + keyboard_set3_all_break = 0; + keyboard_set3_all_repeat = 0; + memset(keyboard_set3_flags, 0, 512); + keyboard_mode = 0x02; + set_scancode_map(dev); + break; + + case 0xf7: /* set all keys to repeat */ + kbd_log("ATkbd: set all keys to repeat\n"); + add_data_kbd_front(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf8: /* set all keys to give make/break codes */ + kbd_log("ATkbd: set all keys to give make/break codes\n"); + add_data_kbd_front(dev, 0xfa); + keyboard_set3_all_break = 1; + break; + + case 0xf9: /* set all keys to give make codes only */ + kbd_log("ATkbd: set all keys to give make codes only\n"); + add_data_kbd_front(dev, 0xfa); + keyboard_set3_all_break = 0; + break; + + case 0xfa: /* set all keys to repeat and give make/break codes */ + kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); + add_data_kbd_front(dev, 0xfa); + keyboard_set3_all_repeat = 1; + keyboard_set3_all_break = 1; + break; + + case 0xfe: /* resend last scan code */ + kbd_log("ATkbd: resend last scan code\n"); + add_data_kbd_front(dev, dev->kbd_last_scan_code); + break; + + case 0xff: /* reset */ + kbd_log("ATkbd: kbd reset\n"); + kbd_key_reset(dev, 1); + break; + + default: + kbd_log("ATkbd: bad keyboard command %02X\n", dev->key_dat); + add_data_kbd_front(dev, 0xfe); + } + + /* If command needs data, remember command. */ + if (dev->key_wantdata == 1) + dev->key_command = dev->key_dat; + } +} + +static void +kbc_process_cmd(void *priv) +{ + atkbd_t *dev = (atkbd_t *) priv; + int i = 0, bad = 1; + uint8_t mask, kbc_ven = dev->flags & KBC_VEN_MASK; + uint8_t cmd_ac_conv[16] = { 0x0b, 2, 3, 4, 5, 6, 7, 8, 9, 0x0a, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21 }; + + if (dev->status & STAT_CD) { + /* Controller command. */ + dev->want60 = 0; + dev->kbc_state = KBC_STATE_MAIN_IBF; + + /* Clear the keyboard controller queue. */ + kbc_queue_reset(dev, 0); + + switch (dev->ib) { + /* Read data from KBC memory. */ + case 0x20 ... 0x3f: + add_to_kbc_queue_front(dev, dev->mem[dev->ib], 0, 0x00); + break; + + /* Write data to KBC memory. */ + case 0x60 ... 0x7f: + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + break; + + case 0xaa: /* self-test */ + kbd_log("ATkbc: self-test\n"); + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + if (dev->kbc_state != KBC_STATE_RESET) { + kbd_log("ATkbc: self-test reinitialization\n"); + /* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */ + /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ + dev->input_port = dev->input_port & 0xff; + write_output(dev, 0x4b); + } + + dev->status = (dev->status & 0x0f) | 0x60; + + dev->mem[0x20] = 0x30; + dev->mem[0x21] = 0x01; + dev->mem[0x22] = 0x0b; + dev->mem[0x25] = 0x02; + dev->mem[0x27] = 0xf8; + dev->mem[0x28] = 0xce; + dev->mem[0x29] = 0x0b; + dev->mem[0x2a] = 0x10; + dev->mem[0x2b] = 0x20; + dev->mem[0x2c] = 0x15; + dev->mem[0x30] = 0x0b; + } else { + if (dev->kbc_state != KBC_STATE_RESET) { + kbd_log("ATkbc: self-test reinitialization\n"); + /* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */ + /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ + dev->input_port = dev->input_port & 0xff; + write_output(dev, 0xcf); + } + + dev->status = (dev->status & 0x0f) | 0x60; + + dev->mem[0x20] = 0x10; + dev->mem[0x21] = 0x01; + dev->mem[0x22] = 0x06; + dev->mem[0x25] = 0x01; + dev->mem[0x27] = 0xfb; + dev->mem[0x28] = 0xe0; + dev->mem[0x29] = 0x06; + dev->mem[0x2a] = 0x10; + dev->mem[0x2b] = 0x20; + dev->mem[0x2c] = 0x15; + } + + dev->out_new = dev->out_new_mouse = -1; + kbc_queue_reset(dev, 0); + + // dev->kbc_state = KBC_STATE_MAIN_IBF; + dev->kbc_state = KBC_STATE_KBC_OUT; + + // add_to_kbc_queue_front(dev, 0x55, 0, 0x00); + kbc_queue_add(dev, 0x55, 0); + break; + + case 0xab: /* interface test */ + kbd_log("ATkbc: interface test\n"); + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); /*no error*/ + break; + + case 0xac: /* diagnostic dump */ + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + kbd_log("ATkbc: diagnostic dump\n"); + dev->mem[0x30] = (dev->input_port & 0xf0) | 0x80; + dev->mem[0x31] = dev->output_port; + dev->mem[0x32] = 0x00; /* T0 and T1. */ + dev->mem[0x33] = 0x00; /* PSW - Program Status Word - always return 0x00 because we do not emulate this byte. */ + /* 20 bytes in high nibble in set 1, low nibble in set 1, set 1 space format = 60 bytes. */ + for (i = 0; i < 20; i++) { + kbc_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] >> 4], 0); + kbc_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] & 0x0f], 0); + kbc_queue_add(dev, 0x39, 0); + } + dev->kbc_state = KBC_STATE_KBC_OUT; + } + break; + + case 0xad: /* disable keyboard */ + kbd_log("ATkbc: disable keyboard\n"); + set_enable_kbd(dev, 0); + break; + + case 0xae: /* enable keyboard */ + kbd_log("ATkbc: enable keyboard\n"); + set_enable_kbd(dev, 1); + break; + + case 0xc7: /* set port1 bits */ + kbd_log("ATkbc: Phoenix - set port1 bits\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + break; + + case 0xca: /* read keyboard mode */ + kbd_log("ATkbc: AMI - read keyboard mode\n"); + add_to_kbc_queue_front(dev, dev->ami_flags, 0, 0x00); + break; + + case 0xcb: /* set keyboard mode */ + kbd_log("ATkbc: AMI - set keyboard mode\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + break; + + case 0xd0: /* read output port */ + kbd_log("ATkbc: read output port\n"); + mask = 0xff; + if ((kbc_ven != KBC_VEN_OLIVETTI) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0x20] & 0x10)) + mask &= 0xbf; + add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + break; + + case 0xd2: /* write keyboard output buffer */ + kbd_log("ATkbc: write keyboard output buffer\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + break; + + case 0xdd: /* disable A20 address line */ + case 0xdf: /* enable A20 address line */ + kbd_log("ATkbc: %sable A20\n", (dev->ib == 0xdd) ? "dis" : "en"); + write_output_fast_a20(dev, (dev->output_port & 0xfd) | (dev->ib & 0x02)); + break; + + case 0xe0: /* read test inputs */ + kbd_log("ATkbc: read test inputs\n"); + add_to_kbc_queue_front(dev, 0x00, 0, 0x00); + break; + + default: + /* + * Unrecognized controller command. + * + * If we have a vendor-specific handler, run + * that. Otherwise, or if that handler fails, + * log a bad command. + */ + if (dev->write64_ven) + bad = dev->write64_ven(dev, dev->ib); + + kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib); + } + + /* If the command needs data, remember the command. */ + if (dev->want60) + dev->command = dev->ib; + } else if (dev->want60) { + /* Write data to controller. */ + dev->want60 = 0; + dev->kbc_state = KBC_STATE_MAIN_IBF; + + switch (dev->command) { + case 0x60 ... 0x7f: + dev->mem[(dev->command & 0x1f) + 0x20] = dev->ib; + if (dev->command == 0x60) + write_cmd(dev, dev->ib); + break; + + case 0xc7: /* set port1 bits */ + kbd_log("ATkbc: Phoenix - set port1 bits\n"); + dev->input_port |= dev->ib; + break; + + case 0xd1: /* write output port */ + kbd_log("ATkbc: write output port\n"); + /* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no), + discovered by reverse-engineering the AOpen Vi15G BIOS. */ + if (dev->ami_flags & 0x04) { + /* If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged. */ + dev->ib &= ~0x0c; + dev->ib |= (dev->output_port & 0x0c); + } + write_output(dev, dev->ib | 0x01); + break; + + case 0xd2: /* write to keyboard output buffer */ + kbd_log("ATkbc: write to keyboard output buffer\n"); + add_to_kbc_queue_front(dev, dev->ib, 0, 0x00); + break; + + case 0xd3: /* write to mouse output buffer */ + kbd_log("ATkbc: write to mouse output buffer\n"); + if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) + keyboard_at_adddata_mouse(dev->ib); + break; + + case 0xd4: /* write to mouse */ + kbd_log("ATkbc: write to mouse (%02X)\n", dev->ib); + + if (dev->ib == 0xbb) + break; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + set_enable_mouse(dev, 1); + if (mouse_write) { + dev->mouse_wantcmd = 1; + dev->mouse_dat = dev->ib; + dev->kbc_state = KBC_STATE_SEND_MOUSE; + } else + add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); + } + break; + + default: + /* + * Run the vendor-specific handler + * if we have one. Otherwise, or if + * it returns an error, log a bad + * controller command. + */ + if (dev->write60_ven) + bad = dev->write60_ven(dev, dev->ib); + + if (bad) { + kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib); + } + } + } +} + +static void +kbd_write(uint16_t port, uint8_t val, void *priv) +{ + atkbd_t *dev = (atkbd_t *) priv; + + kbd_log((port == 0x61) ? "" : "[%04X:%08X] ATkbc: write(%04X) = %02X\n", CS, cpu_state.pc, port, val); + + switch (port) { + case 0x60: + dev->status &= ~STAT_CD; + if (dev->want60 && (dev->command == 0xd1)) { + kbd_log("ATkbc: write output port\n"); + + /* Fast A20 - ignore all other bits. */ + val = (val & 0x02) | (dev->output_port & 0xfd); + + /* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no), + discovered by reverse-engineering the AOpeN Vi15G BIOS. */ + if (dev->ami_flags & 0x04) { + /* If keyboard controller lines P22-P23 are blocked, + we force them to remain unchanged. */ + val &= ~0x0c; + val |= (dev->output_port & 0x0c); + } + + write_output_fast_a20(dev, val | 0x01); + + dev->want60 = 0; + dev->kbc_state = KBC_STATE_MAIN_IBF; + return; + } + break; + + case 0x64: + dev->status |= STAT_CD; + if (val == 0xd1) { + kbd_log("ATkbc: write output port\n"); + dev->want60 = 1; + dev->kbc_state = KBC_STATE_KBC_PARAM; + dev->command = 0xd1; + return; + } + break; + } + + dev->ib = val; + dev->status |= STAT_IFULL; +} + +static uint8_t +kbd_read(uint16_t port, void *priv) +{ + atkbd_t *dev = (atkbd_t *) priv; + uint8_t ret = 0xff; + + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) + cycles -= ISA_CYCLES(8); + + switch (port) { + case 0x60: + ret = dev->out; + dev->status &= ~STAT_OFULL; + /* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a bit the + output port (P2). + This also means that in AT mode, the IRQ is level-triggered. */ + if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) + picintc(1 << 1); + break; + + case 0x64: + ret = dev->status; + break; + + default: + kbd_log("ATkbc: read(%04x) invalid!\n",port); + break; + } + + kbd_log((port == 0x61) ? "" : "[%04X:%08X] ATkbc: read (%04X) = %02X\n", CS, cpu_state.pc, port, ret); + + return (ret); +} + +static void +kbd_reset(void *priv) +{ + atkbd_t *dev = (atkbd_t *) priv; + int i; + uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; + + dev->status = STAT_UNLOCKED; + dev->mem[0x20] = 0x01; + dev->mem[0x20] |= CCB_TRANSLATE; + dev->secr_phase = 0; + dev->key_wantdata = 0; + + /* Set up the correct Video Type bits. */ + if (!is286 || (kbc_ven == KBC_VEN_ACER)) + dev->input_port = video_is_mda() ? 0xb0 : 0xf0; + else + dev->input_port = video_is_mda() ? 0xf0 : 0xb0; + kbd_log("ATkbc: input port = %02x\n", dev->input_port); + + /* Enable keyboard, disable mouse. */ + set_enable_kbd(dev, 0); + keyboard_scan = 0; + set_enable_mouse(dev, 0); + mouse_scan = 0; + + dev->out_new = dev->out_new_mouse = -1; + for (i = 0; i < 3; i++) + kbc_queue_reset(dev, i); + dev->kbd_last_scan_code = 0; + + dev->sc_or = 0; + + keyboard_mode = 0x02; + + memset(keyboard_set3_flags, 0, 512); + + set_scancode_map(dev); + + dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00; + dev->ami_stat |= 0x02; + + dev->output_port = 0xcd; + if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + write_output(dev, 0x4b); + } else { + /* The real thing writes CF and then AND's it with BF. */ + write_output(dev, 0x8f); + } + + /* Stage 1. */ + dev->status = (dev->status & 0x0f) | (dev->input_port & 0xf0); + + /* Reset the keyboard. */ + kbd_key_reset(dev, 0); + + /* Reset the mouse. */ + kbd_aux_reset(dev, 0); +} + +/* Reset the AT keyboard - this is needed for the PCI TRC and is done + until a better solution is found. */ +void +keyboard_at_reset(void) +{ + kbd_reset(SavedKbd); +} + +void +kbc_at_a20_reset(void) +{ + if (SavedKbd) { + SavedKbd->output_port = 0xcd; + if ((SavedKbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { + write_output(SavedKbd, 0x4b); + } else { + /* The real thing writes CF and then AND's it with BF. */ + write_output(SavedKbd, 0x8f); + } + } +} + +static void +kbd_close(void *priv) +{ + atkbd_t *dev = (atkbd_t *) priv; + int i, max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 2 : 1; + + kbd_reset(dev); + + /* Stop timers. */ + timer_disable(&dev->send_delay_timer); + + keyboard_scan = 0; + keyboard_send = NULL; + + /* Disable the scancode maps. */ + keyboard_set_table(NULL); + + SavedKbd = NULL; + + for (i = 0; i < max_ports; i++) { + if (kbc_ports[i] != NULL) { + free(kbc_ports[i]); + kbc_ports[i] = NULL; + } + } + + free(dev); +} + +static void * +kbd_init(const device_t *info) +{ + atkbd_t *dev; + int i, max_ports; + + dev = (atkbd_t *) malloc(sizeof(atkbd_t)); + memset(dev, 0x00, sizeof(atkbd_t)); + + dev->flags = info->local; + dev->pci = !!(info->flags & DEVICE_PCI); + + /* We need this, sadly. */ + SavedKbd = dev; + + video_reset(gfxcard[0]); + kbd_reset(dev); + + io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); + keyboard_send = add_data_kbd; + + timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); + timer_add(&dev->pulse_cb, pulse_poll, dev, 0); + + dev->write60_ven = NULL; + dev->write64_ven = NULL; + + switch (dev->flags & KBC_VEN_MASK) { + case KBC_VEN_ACER: + case KBC_VEN_GENERIC: + case KBC_VEN_NCR: + case KBC_VEN_IBM_PS1: + dev->write64_ven = write64_generic; + break; + + case KBC_VEN_OLIVETTI: + dev->write64_ven = write64_olivetti; + break; + + case KBC_VEN_AMI: + case KBC_VEN_INTEL_AMI: + case KBC_VEN_ALI: + case KBC_VEN_TG: + case KBC_VEN_TG_GREEN: + dev->write60_ven = write60_ami; + dev->write64_ven = write64_ami; + break; + + case KBC_VEN_IBM_MCA: + dev->write64_ven = write64_ibm_mca; + break; + + case KBC_VEN_QUADTEL: + dev->write60_ven = write60_quadtel; + dev->write64_ven = write64_quadtel; + break; + + case KBC_VEN_TOSHIBA: + dev->write60_ven = write60_toshiba; + dev->write64_ven = write64_toshiba; + break; + } + + max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 2 : 1; + + for (i = 0; i < max_ports; i++) { + kbc_ports[i] = (kbc_port_t *) malloc(sizeof(kbc_port_t)); + memset(kbc_ports[i], 0x00, sizeof(kbc_port_t)); + } + + return (dev); +} + +const device_t keyboard_at_device = { + .name = "PC/AT Keyboard", + .internal_name = "keyboard_at", + .flags = 0, + .local = KBC_TYPE_ISA | KBC_VEN_GENERIC, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_at_ami_device = { + .name = "PC/AT Keyboard (AMI)", + .internal_name = "keyboard_at_ami", + .flags = 0, + .local = KBC_TYPE_ISA | KBC_VEN_AMI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_at_tg_ami_device = { + .name = "PC/AT Keyboard (TriGem AMI)", + .internal_name = "keyboard_at_tg_ami", + .flags = 0, + .local = KBC_TYPE_ISA | KBC_VEN_TG, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_at_toshiba_device = { + .name = "PC/AT Keyboard (Toshiba)", + .internal_name = "keyboard_at_toshiba", + .flags = 0, + .local = KBC_TYPE_ISA | KBC_VEN_TOSHIBA, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_at_olivetti_device = { + .name = "PC/AT Keyboard (Olivetti)", + .internal_name = "keyboard_at_olivetti", + .flags = 0, + .local = KBC_TYPE_ISA | KBC_VEN_OLIVETTI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_at_ncr_device = { + .name = "PC/AT Keyboard (NCR)", + .internal_name = "keyboard_at_ncr", + .flags = 0, + .local = KBC_TYPE_ISA | KBC_VEN_NCR, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_device = { + .name = "PS/2 Keyboard", + .internal_name = "keyboard_ps2", + .flags = 0, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_ps1_device = { + .name = "PS/2 Keyboard (IBM PS/1)", + .internal_name = "keyboard_ps2_ps1", + .flags = 0, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_ps1_pci_device = { + .name = "PS/2 Keyboard (IBM PS/1)", + .internal_name = "keyboard_ps2_ps1_pci", + .flags = DEVICE_PCI, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_xi8088_device = { + .name = "PS/2 Keyboard (Xi8088)", + .internal_name = "keyboard_ps2_xi8088", + .flags = 0, + .local = KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_ami_device = { + .name = "PS/2 Keyboard (AMI)", + .internal_name = "keyboard_ps2_ami", + .flags = 0, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_tg_ami_device = { + .name = "PS/2 Keyboard (TriGem AMI)", + .internal_name = "keyboard_ps2_tg_ami", + .flags = 0, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_TG, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_mca_device = { + .name = "PS/2 Keyboard", + .internal_name = "keyboard_ps2_mca", + .flags = 0, + .local = KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_mca_2_device = { + .name = "PS/2 Keyboard", + .internal_name = "keyboard_ps2_mca_2", + .flags = 0, + .local = KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_quadtel_device = { + .name = "PS/2 Keyboard (Quadtel/MegaPC)", + .internal_name = "keyboard_ps2_quadtel", + .flags = 0, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_pci_device = { + .name = "PS/2 Keyboard", + .internal_name = "keyboard_ps2_pci", + .flags = DEVICE_PCI, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_ami_pci_device = { + .name = "PS/2 Keyboard (AMI)", + .internal_name = "keyboard_ps2_ami_pci", + .flags = DEVICE_PCI, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_ali_pci_device = { + .name = "PS/2 Keyboard (ALi M5123/M1543C)", + .internal_name = "keyboard_ps2_ali_pci", + .flags = DEVICE_PCI, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_ALI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_intel_ami_pci_device = { + .name = "PS/2 Keyboard (AMI)", + .internal_name = "keyboard_ps2_intel_ami_pci", + .flags = DEVICE_PCI, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_tg_ami_pci_device = { + .name = "PS/2 Keyboard (TriGem AMI)", + .internal_name = "keyboard_ps2_tg_ami_pci", + .flags = DEVICE_PCI, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_TG, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const device_t keyboard_ps2_acer_pci_device = { + .name = "PS/2 Keyboard (Acer 90M002A)", + .internal_name = "keyboard_ps2_acer_pci", + .flags = DEVICE_PCI, + .local = KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, + .init = kbd_init, + .close = kbd_close, + .reset = kbd_reset, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +void +keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) +{ + mouse_write = func; + mouse_p = priv; +} + +void +keyboard_at_adddata_mouse(uint8_t val) +{ + atkbd_t *dev = SavedKbd; + + if (!mouse_scan || (dev->mouse_queue_end >= 16)) { + kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !mouse_scan, (dev->mouse_queue_end >= 16)); + return; + } + kbc_queue_add(dev, val, 2); +} + +void +keyboard_at_adddata_mouse_cmd(uint8_t val) +{ + atkbd_t *dev = SavedKbd; + + if (dev->mouse_cmd_queue_end >= 16) { + kbd_log("ATkbc: Unable to add to queue, dev->mouse_cmd_queue_end >= 16\n"); + return; + } + kbc_queue_add(dev, val, 3); +} + +uint8_t +keyboard_at_mouse_pos(void) +{ + atkbd_t *dev = SavedKbd; + + return ((dev->mouse_queue_end - dev->mouse_queue_start) & 0xf); +} + +void +keyboard_at_set_a20_key(int state) +{ + atkbd_t *dev = SavedKbd; + + write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); +} diff --git a/src/device/mouse_ps2 - Cópia.c b/src/device/mouse_ps2 - Cópia.c new file mode 100644 index 000000000..1c8e0334d --- /dev/null +++ b/src/device/mouse_ps2 - Cópia.c @@ -0,0 +1,404 @@ +/* + * 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. + * + * Implementation of PS/2 series Mouse devices. + * + * + * + * Authors: Fred N. van Kempen, + */ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/keyboard.h> +#include <86box/mouse.h> + +enum { + MODE_STREAM, + MODE_REMOTE, + MODE_ECHO +}; + +typedef struct { + const char *name; /* name of this device */ + int8_t type; /* type of this device */ + + int mode; + + uint16_t flags; + uint8_t resolution; + uint8_t sample_rate; + + uint8_t command; + + int x, y, z, b; + + uint8_t last_data[6]; +} mouse_t; +#define FLAG_5BTN 0x100 /* using Intellimouse Optical mode */ +#define FLAG_INTELLI 0x80 /* device is IntelliMouse */ +#define FLAG_INTMODE 0x40 /* using Intellimouse mode */ +#define FLAG_SCALED 0x20 /* enable delta scaling */ +#define FLAG_ENABLED 0x10 /* dev is enabled for use */ +#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */ + +int mouse_scan = 0; + +#ifdef ENABLE_MOUSE_PS2_LOG +int mouse_ps2_do_log = ENABLE_MOUSE_PS2_LOG; + +static void +mouse_ps2_log(const char *fmt, ...) +{ + va_list ap; + + if (mouse_ps2_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define mouse_ps2_log(fmt, ...) +#endif + +void +mouse_clear_data(void *priv) +{ + mouse_t *dev = (mouse_t *) priv; + + dev->flags &= ~FLAG_CTRLDAT; +} + +static void +ps2_report_coordinates(mouse_t *dev, int cmd) +{ + uint8_t buff[3] = { 0x08, 0x00, 0x00 }; + int temp_z; + + if (dev->x > 255) { + dev->x = 255; + buff[0] |= 0x40; + } + if (dev->x < -256) { + dev->x = -256; + buff[0] |= 0x40; + } + if (dev->y > 255) { + dev->y = 255; + buff[0] |= 0x80; + } + if (dev->y < -256) { + dev->y = -256; + buff[0] |= 0x80; + } + if (dev->z < -8) + dev->z = -8; + if (dev->z > 7) + dev->z = 7; + + if (dev->x < 0) + buff[0] |= 0x10; + if (dev->y < 0) + buff[0] |= 0x20; + if (mouse_buttons & 0x01) + buff[0] |= 0x01; + if (mouse_buttons & 0x02) + buff[0] |= 0x02; + if (dev->flags & FLAG_INTELLI) { + if (mouse_buttons & 0x04) + buff[0] |= 0x04; + } + buff[1] = (dev->x & 0xff); + buff[2] = (dev->y & 0xff); + + if (cmd) { + keyboard_at_adddata_mouse_cmd(buff[0]); + keyboard_at_adddata_mouse_cmd(buff[1]); + keyboard_at_adddata_mouse_cmd(buff[2]); + } else { + keyboard_at_adddata_mouse(buff[0]); + keyboard_at_adddata_mouse(buff[1]); + keyboard_at_adddata_mouse(buff[2]); + } + if (dev->flags & FLAG_INTMODE) { + temp_z = dev->z & 0x0f; + if ((dev->flags & FLAG_5BTN)) { + if (mouse_buttons & 8) + temp_z |= 0x10; + if (mouse_buttons & 16) + temp_z |= 0x20; + } else { + /* The wheel coordinate is sign-extended. */ + if (temp_z & 0x08) + temp_z |= 0xf0; + } + if (cmd) + keyboard_at_adddata_mouse_cmd(temp_z); + else + keyboard_at_adddata_mouse(temp_z); + } + + dev->x = dev->y = dev->z = 0; +} + +static void +ps2_write(uint8_t val, void *priv) +{ + mouse_t *dev = (mouse_t *) priv; + uint8_t temp; + + if (dev->flags & FLAG_CTRLDAT) { + dev->flags &= ~FLAG_CTRLDAT; + + if (val == 0xff) + goto mouse_reset; + + switch (dev->command) { + case 0xe8: /* set mouse resolution */ + dev->resolution = val; + keyboard_at_adddata_mouse_cmd(0xfa); + break; + + case 0xf3: /* set sample rate */ + dev->sample_rate = val; + keyboard_at_adddata_mouse_cmd(0xfa); /* Command response */ + break; + + default: + keyboard_at_adddata_mouse_cmd(0xfc); + } + } else { + dev->command = val; + + switch (dev->command) { + case 0xe6: /* set scaling to 1:1 */ + dev->flags &= ~FLAG_SCALED; + keyboard_at_adddata_mouse_cmd(0xfa); + break; + + case 0xe7: /* set scaling to 2:1 */ + dev->flags |= FLAG_SCALED; + keyboard_at_adddata_mouse_cmd(0xfa); + break; + + case 0xe8: /* set mouse resolution */ + dev->flags |= FLAG_CTRLDAT; + keyboard_at_adddata_mouse_cmd(0xfa); + break; + + case 0xe9: /* status request */ + keyboard_at_adddata_mouse_cmd(0xfa); + temp = (dev->flags & 0x30); + if (mouse_buttons & 1) + temp |= 4; + if (mouse_buttons & 2) + temp |= 1; + if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI)) + temp |= 2; + keyboard_at_adddata_mouse_cmd(temp); + keyboard_at_adddata_mouse_cmd(dev->resolution); + keyboard_at_adddata_mouse_cmd(dev->sample_rate); + break; + + case 0xea: /* set stream */ + dev->flags &= ~FLAG_CTRLDAT; + mouse_scan = 1; + keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */ + break; + + case 0xeb: /* Get mouse data */ + keyboard_at_adddata_mouse_cmd(0xfa); + + ps2_report_coordinates(dev, 1); + break; + + case 0xf2: /* read ID */ + keyboard_at_adddata_mouse_cmd(0xfa); + if (dev->flags & FLAG_INTMODE) + keyboard_at_adddata_mouse_cmd((dev->flags & FLAG_5BTN) ? 0x04 : 0x03); + else + keyboard_at_adddata_mouse_cmd(0x00); + break; + + case 0xf3: /* set command mode */ + dev->flags |= FLAG_CTRLDAT; + keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */ + break; + + case 0xf4: /* enable */ + dev->flags |= FLAG_ENABLED; + mouse_scan = 1; + keyboard_at_adddata_mouse_cmd(0xfa); + break; + + case 0xf5: /* disable */ + dev->flags &= ~FLAG_ENABLED; + mouse_scan = 0; + keyboard_at_adddata_mouse_cmd(0xfa); + break; + + case 0xf6: /* set defaults */ + case 0xff: /* reset */ +mouse_reset: + dev->mode = MODE_STREAM; + dev->flags &= 0x88; + mouse_scan = 1; + keyboard_at_mouse_reset(); + keyboard_at_adddata_mouse_cmd(0xfa); + if (dev->command == 0xff) { + keyboard_at_adddata_mouse_cmd(0xaa); + keyboard_at_adddata_mouse_cmd(0x00); + } + break; + + default: + keyboard_at_adddata_mouse_cmd(0xfe); + } + } + + if (dev->flags & FLAG_INTELLI) { + for (temp = 0; temp < 5; temp++) + dev->last_data[temp] = dev->last_data[temp + 1]; + + dev->last_data[5] = val; + + if ((dev->last_data[0] == 0xf3) && (dev->last_data[1] == 0xc8) && + (dev->last_data[2] == 0xf3) && (dev->last_data[3] == 0x64) && + (dev->last_data[4] == 0xf3) && (dev->last_data[5] == 0x50)) + dev->flags |= FLAG_INTMODE; + + if ((dev->flags & FLAG_INTMODE) && (dev->last_data[0] == 0xf3) && (dev->last_data[1] == 0xc8) && + (dev->last_data[2] == 0xf3) && (dev->last_data[3] == 0xc8) && + (dev->last_data[4] == 0xf3) && (dev->last_data[5] == 0x50)) + dev->flags |= FLAG_5BTN; + } +} + +static int +ps2_poll(int x, int y, int z, int b, double abs_x, double abs_y, void *priv) +{ + mouse_t *dev = (mouse_t *) priv; + + if (!x && !y && !z && (b == dev->b)) + return (0xff); + +#if 0 + if (!(dev->flags & FLAG_ENABLED)) + return(0xff); +#endif + + if (!mouse_scan) + return (0xff); + + dev->x += x; + dev->y -= y; + dev->z -= z; +#if 0 + if ((dev->mode == MODE_STREAM) && (dev->flags & FLAG_ENABLED) && (keyboard_at_mouse_pos() < 13)) { +#else + if ((dev->mode == MODE_STREAM) && (keyboard_at_mouse_pos() < 13)) { +#endif + dev->b = b; + + ps2_report_coordinates(dev, 0); + } + + return (0); +} + +/* + * Initialize the device for use by the user. + * + * We also get called from the various machines. + */ +void * +mouse_ps2_init(const device_t *info) +{ + mouse_t *dev; + int i; + + dev = (mouse_t *) malloc(sizeof(mouse_t)); + memset(dev, 0x00, sizeof(mouse_t)); + dev->name = info->name; + dev->type = info->local; + + dev->mode = MODE_STREAM; + i = device_get_config_int("buttons"); + if (i > 2) + dev->flags |= FLAG_INTELLI; + + if (i == 4) + i = 3; + + /* Hook into the general AT Keyboard driver. */ + keyboard_at_set_mouse(ps2_write, dev); + + mouse_ps2_log("%s: buttons=%d\n", dev->name, i); + + /* Tell them how many buttons we have. */ + mouse_set_buttons(i); + + /* Return our private data to the I/O layer. */ + return (dev); +} + +static void +ps2_close(void *priv) +{ + mouse_t *dev = (mouse_t *) priv; + + /* Unhook from the general AT Keyboard driver. */ + keyboard_at_set_mouse(NULL, NULL); + + free(dev); +} + +static const device_config_t ps2_config[] = { + // clang-format off + { + .name = "buttons", + .description = "Buttons", + .type = CONFIG_SELECTION, + .default_string = "", + .default_int = 2, + .file_filter = "", + .spinner = { 0 }, + .selection = { + { .description = "Two", .value = 2 }, + { .description = "Three", .value = 3 }, + { .description = "Wheel", .value = 4 }, + { .description = "Five + Wheel", .value = 5 }, + { .description = "" } + } + }, + { + .name = "", .description = "", .type = CONFIG_END + } + // clang-format on +}; + +const device_t mouse_ps2_device = { + .name = "Standard PS/2 Mouse", + .internal_name = "ps2", + .flags = DEVICE_PS2, + .local = MOUSE_TYPE_PS2, + .init = mouse_ps2_init, + .close = ps2_close, + .reset = NULL, + { .poll = ps2_poll }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = ps2_config +}; diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index ab9ae53a7..6582f05e4 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -27,25 +27,27 @@ typedef struct usb_t usb_t; /* USB device creation parameters struct */ typedef struct { - void (*raise_interrupt)(usb_t*, void*); + void (*update_interrupt)(usb_t*, void*); /* Handle (but do not raise) SMI. Returns 1 if SMI can be raised, 0 otherwise. */ uint8_t (*smi_handle)(usb_t*, void*); void* parent_priv; } usb_params_t; +typedef union +{ + uint32_t l; + uint16_t w[2]; + uint8_t b[4]; +} ohci_mmio_t; + /* USB Host Controller device struct */ typedef struct usb_t { - union - { - uint8_t ohci_mmio[4096]; - uint16_t ohci_mmio_w[2048]; - uint32_t ohci_mmio_l[1024]; - }; uint8_t uhci_io[32]; + ohci_mmio_t ohci_mmio[1024]; uint16_t uhci_io_base; int uhci_enable, ohci_enable; - uint32_t ohci_mem_base; + uint32_t ohci_mem_base, irq_level; mem_mapping_t ohci_mmio_mapping; pc_timer_t ohci_frame_timer; pc_timer_t ohci_interrupt_desc_poll_timer; diff --git a/src/mem/mem - Cópia.c b/src/mem/mem - Cópia.c new file mode 100644 index 000000000..a8d9e994d --- /dev/null +++ b/src/mem/mem - Cópia.c @@ -0,0 +1,3092 @@ +/* + * 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. + * + * Memory handling and MMU. + * + * Authors: Sarah Walker, + * Miran Grca, + * Fred N. van Kempen, + * + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2017-2020 Fred N. van Kempen. + */ +#include +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/version.h> +#include "cpu.h" +#include "x86_ops.h" +#include "x86.h" +#include <86box/machine.h> +#include <86box/m_xt_xi8088.h> +#include <86box/config.h> +#include <86box/io.h> +#include <86box/mem.h> +#include <86box/plat.h> +#include <86box/rom.h> +#include <86box/gdbstub.h> +#ifdef USE_DYNAREC +# include "codegen_public.h" +#else +# ifdef USE_NEW_DYNAREC +# define PAGE_MASK_SHIFT 6 +# else +# define PAGE_MASK_INDEX_MASK 3 +# define PAGE_MASK_INDEX_SHIFT 10 +# define PAGE_MASK_SHIFT 4 +# endif +# define PAGE_MASK_MASK 63 +#endif +#if (!defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) +# define BLOCK_PC_INVALID 0xffffffff +# define BLOCK_INVALID 0 +#endif + +mem_mapping_t ram_low_mapping, /* 0..640K mapping */ + ram_mid_mapping, /* 640..1024K mapping */ + ram_mid_mapping2, /* 640..1024K mapping, second part, for SiS 471 in relocate mode */ + ram_remapped_mapping, /* 640..1024K mapping */ + ram_remapped_mapping2, /* 640..1024K second mapping, for SiS 471 mode */ + ram_high_mapping, /* 1024K+ mapping */ + ram_2gb_mapping, /* 1024M+ mapping */ + ram_split_mapping, + bios_mapping, + bios_high_mapping; + +page_t *pages, /* RAM page table */ + **page_lookup; /* pagetable lookup */ +uint32_t pages_sz; /* #pages in table */ + +uint8_t *ram, *ram2; /* the virtual RAM */ +uint8_t page_ff[4096]; +uint32_t rammask; +uint32_t addr_space_size; + +uint8_t *rom; /* the virtual ROM */ +uint32_t biosmask, biosaddr; + +uint32_t pccache; +uint8_t *pccache2; + +int readlnext; +int readlookup[256]; +uintptr_t *readlookup2; +uintptr_t old_rl2; +uint8_t uncached = 0; +int writelnext; +int writelookup[256]; +uintptr_t *writelookup2; + +uint32_t mem_logical_addr; + +int shadowbios = 0, + shadowbios_write; +int readlnum = 0, + writelnum = 0; +int cachesize = 256; + +uint32_t get_phys_virt, + get_phys_phys; + +int mem_a20_key = 0, + mem_a20_alt = 0, + mem_a20_state = 0; + +int mmuflush = 0; +int mmu_perm = 4; + +#ifdef USE_NEW_DYNAREC +uint64_t *byte_dirty_mask; +uint64_t *byte_code_present_mask; + +uint32_t purgable_page_list_head = 0; +int purgeable_page_count = 0; +#endif + +uint8_t high_page = 0; /* if a high (> 4 gb) page was detected */ + +/* FIXME: re-do this with a 'mem_ops' struct. */ +static uint8_t *page_lookupp; /* pagetable mmu_perm lookup */ +static uint8_t *readlookupp; +static uint8_t *writelookupp; +static mem_mapping_t *base_mapping, *last_mapping; +static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; +static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; +static mem_mapping_t *read_mapping_bus[MEM_MAPPINGS_NO]; +static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO]; +static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; +static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; +static mem_state_t _mem_state[MEM_MAPPINGS_NO]; +static uint32_t remap_start_addr, remap_start_addr2; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) +static size_t ram_size = 0, ram2_size = 0; +#else +static size_t ram_size = 0; +#endif + +#ifdef ENABLE_MEM_LOG +int mem_do_log = ENABLE_MEM_LOG; + +static void +mem_log(const char *fmt, ...) +{ + va_list ap; + + if (mem_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define mem_log(fmt, ...) +#endif + +int +mem_addr_is_ram(uint32_t addr) +{ + mem_mapping_t *mapping = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || + (mapping == &ram_mid_mapping2) || (mapping == &ram_remapped_mapping); +} + +void +resetreadlookup(void) +{ + int c; + + /* Initialize the page lookup table. */ + memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); + + /* Initialize the tables for lower (<= 1024K) RAM. */ + for (c = 0; c < 256; c++) { + readlookup[c] = 0xffffffff; + writelookup[c] = 0xffffffff; + } + + /* Initialize the tables for high (> 1024K) RAM. */ + memset(readlookup2, 0xff, (1 << 20) * sizeof(uintptr_t)); + memset(readlookupp, 0x04, (1 << 20) * sizeof(uint8_t)); + + memset(writelookup2, 0xff, (1 << 20) * sizeof(uintptr_t)); + memset(writelookupp, 0x04, (1 << 20) * sizeof(uint8_t)); + + readlnext = 0; + writelnext = 0; + pccache = 0xffffffff; + high_page = 0; +} + +void +flushmmucache(void) +{ + int c; + + for (c = 0; c < 256; c++) { + if (readlookup[c] != (int) 0xffffffff) { + readlookup2[readlookup[c]] = LOOKUP_INV; + readlookupp[readlookup[c]] = 4; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != (int) 0xffffffff) { + page_lookup[writelookup[c]] = NULL; + page_lookupp[writelookup[c]] = 4; + writelookup2[writelookup[c]] = LOOKUP_INV; + writelookupp[writelookup[c]] = 4; + writelookup[c] = 0xffffffff; + } + } + mmuflush++; + + pccache = (uint32_t) 0xffffffff; + pccache2 = (uint8_t *) 0xffffffff; + +#ifdef USE_DYNAREC + codegen_flush(); +#endif +} + +void +flushmmucache_nopc(void) +{ + int c; + + for (c = 0; c < 256; c++) { + if (readlookup[c] != (int) 0xffffffff) { + readlookup2[readlookup[c]] = LOOKUP_INV; + readlookupp[readlookup[c]] = 4; + readlookup[c] = 0xffffffff; + } + if (writelookup[c] != (int) 0xffffffff) { + page_lookup[writelookup[c]] = NULL; + page_lookupp[writelookup[c]] = 4; + writelookup2[writelookup[c]] = LOOKUP_INV; + writelookupp[writelookup[c]] = 4; + writelookup[c] = 0xffffffff; + } + } +} + +void +mem_flush_write_page(uint32_t addr, uint32_t virt) +{ + page_t *page_target = &pages[addr >> 12]; + int c; +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + uint32_t a; +#endif + + for (c = 0; c < 256; c++) { + if (writelookup[c] != (int) 0xffffffff) { +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + uintptr_t target = (uintptr_t) &ram[(uintptr_t) (addr & ~0xfff) - (virt & ~0xfff)]; +#else + a = (uintptr_t) (addr & ~0xfff) - (virt & ~0xfff); + uintptr_t target; + + if ((addr & ~0xfff) >= (1 << 30)) + target = (uintptr_t) &ram2[a - (1 << 30)]; + else + target = (uintptr_t) &ram[a]; +#endif + + if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { + writelookup2[writelookup[c]] = LOOKUP_INV; + page_lookup[writelookup[c]] = NULL; + writelookup[c] = 0xffffffff; + } + } + } +} + +#define mmutranslate_read(addr) mmutranslatereal(addr, 0) +#define mmutranslate_write(addr) mmutranslatereal(addr, 1) +#define rammap(x) ((uint32_t *) (_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 2) & MEM_GRANULARITY_QMASK] +#define rammap64(x) ((uint64_t *) (_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 3) & MEM_GRANULARITY_PMASK] + +static __inline uint64_t +mmutranslatereal_normal(uint32_t addr, int rw) +{ + uint32_t temp, temp2, temp3; + uint32_t addr2; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp = temp2 = rammap(addr2); + if (!(temp & 1)) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + + return 0xffffffffffffffffULL; + } + + mmu_perm = temp & 4; + rammap(addr2) |= (rw ? 0x60 : 0x20); + + return (temp & ~0x3fffff) + (addr & 0x3fffff); + } + + temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); + temp3 = temp & temp2; + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + mmu_perm = temp & 4; + rammap(addr2) |= 0x20; + rammap((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) |= (rw ? 0x60 : 0x20); + + return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); +} + +static __inline uint64_t +mmutranslatereal_pae(uint32_t addr, int rw) +{ + uint64_t temp, temp2, temp3, temp4; + uint64_t addr2, addr3, addr4; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); + temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; + if (!(temp & 1)) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); + temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; + temp3 = temp & temp2; + if (!(temp & 1)) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + if (temp & 0x80) { + /*2MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + + return 0xffffffffffffffffULL; + } + mmu_perm = temp & 4; + rammap64(addr3) |= (rw ? 0x60 : 0x20); + + return ((temp & ~0x1fffffULL) + (addr & 0x1fffffULL)) & 0x000000ffffffffffULL; + } + + addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); + temp = rammap64(addr4) & 0x000000ffffffffffULL; + temp3 = temp & temp4; + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { + cr2 = addr; + temp &= 1; + if (CPL == 3) + temp |= 4; + if (rw) + temp |= 2; + cpu_state.abrt = ABRT_PF; + abrt_error = temp; + return 0xffffffffffffffffULL; + } + + mmu_perm = temp & 4; + rammap64(addr3) |= 0x20; + rammap64(addr4) |= (rw ? 0x60 : 0x20); + + return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; +} + +uint64_t +mmutranslatereal(uint32_t addr, int rw) +{ + /* Fast path to return invalid without any call if an exception has occurred beforehand. */ + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + if (cr4 & CR4_PAE) + return mmutranslatereal_pae(addr, rw); + else + return mmutranslatereal_normal(addr, rw); +} + +/* This is needed because the old recompiler calls this to check for page fault. */ +uint32_t +mmutranslatereal32(uint32_t addr, int rw) +{ + /* Fast path to return invalid without any call if an exception has occurred beforehand. */ + if (cpu_state.abrt) + return (uint32_t) 0xffffffffffffffffULL; + + return (uint32_t) mmutranslatereal(addr, rw); +} + +static __inline uint64_t +mmutranslate_noabrt_normal(uint32_t addr, int rw) +{ + uint32_t temp, temp2, temp3; + uint32_t addr2; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); + temp = temp2 = rammap(addr2); + + if (!(temp & 1)) + return 0xffffffffffffffffULL; + + if ((temp & 0x80) && (cr4 & CR4_PSE)) { + /*4MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return (temp & ~0x3fffff) + (addr & 0x3fffff); + } + + temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); + temp3 = temp & temp2; + + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); +} + +static __inline uint64_t +mmutranslate_noabrt_pae(uint32_t addr, int rw) +{ + uint64_t temp, temp2, temp3, temp4; + uint64_t addr2, addr3, addr4; + + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); + temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; + + if (!(temp & 1)) + return 0xffffffffffffffffULL; + + addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); + temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; + temp3 = temp & temp2; + + if (!(temp & 1)) + return 0xffffffffffffffffULL; + + if (temp & 0x80) { + /*2MB page*/ + if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return ((temp & ~0x1fffffULL) + (addr & 0x1fffff)) & 0x000000ffffffffffULL; + } + + addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); + temp = rammap64(addr4) & 0x000000ffffffffffULL; + ; + temp3 = temp & temp4; + + if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) + return 0xffffffffffffffffULL; + + return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; +} + +uint64_t +mmutranslate_noabrt(uint32_t addr, int rw) +{ + /* Fast path to return invalid without any call if an exception has occurred beforehand. */ + if (cpu_state.abrt) + return 0xffffffffffffffffULL; + + if (cr4 & CR4_PAE) + return mmutranslate_noabrt_pae(addr, rw); + else + return mmutranslate_noabrt_normal(addr, rw); +} + +void +mmu_invalidate(uint32_t addr) +{ + flushmmucache_cr3(); +} + +uint8_t +mem_addr_range_match(uint32_t addr, uint32_t start, uint32_t len) +{ + if (addr < start) + return 0; + else if (addr >= (start + len)) + return 0; + else + return 1; +} + +uint32_t +mem_addr_translate(uint32_t addr, uint32_t chunk_start, uint32_t len) +{ + uint32_t mask = len - 1; + + return chunk_start + (addr & mask); +} + +void +addreadlookup(uint32_t virt, uint32_t phys) +{ +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + uint32_t a; +#endif + + if (virt == 0xffffffff) + return; + + if (readlookup2[virt >> 12] != (uintptr_t) LOOKUP_INV) + return; + + if (readlookup[readlnext] != (int) 0xffffffff) { + if ((readlookup[readlnext] == ((es + DI) >> 12)) || (readlookup[readlnext] == ((es + EDI) >> 12))) + uncached = 1; + readlookup2[readlookup[readlnext]] = LOOKUP_INV; + } + +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + readlookup2[virt >> 12] = (uintptr_t) &ram[(uintptr_t) (phys & ~0xFFF) - (uintptr_t) (virt & ~0xfff)]; +#else + a = ((uint32_t) (phys & ~0xfff) - (uint32_t) (virt & ~0xfff)); + + if ((phys & ~0xfff) >= (1 << 30)) + readlookup2[virt >> 12] = (uintptr_t) &ram2[a - (1 << 30)]; + else + readlookup2[virt >> 12] = (uintptr_t) &ram[a]; +#endif + readlookupp[virt >> 12] = mmu_perm; + + readlookup[readlnext++] = virt >> 12; + readlnext &= (cachesize - 1); + + cycles -= 9; +} + +void +addwritelookup(uint32_t virt, uint32_t phys) +{ +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + uint32_t a; +#endif + + if (virt == 0xffffffff) + return; + + if (page_lookup[virt >> 12]) + return; + + if (writelookup[writelnext] != -1) { + page_lookup[writelookup[writelnext]] = NULL; + writelookup2[writelookup[writelnext]] = LOOKUP_INV; + } + +#ifdef USE_NEW_DYNAREC +# ifdef USE_DYNAREC + if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) { +# else + if (pages[phys >> 12].block) { +# endif +#else +# ifdef USE_DYNAREC + if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) { +# else + if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3]) { +# endif +#endif + page_lookup[virt >> 12] = &pages[phys >> 12]; + page_lookupp[virt >> 12] = mmu_perm; + } else { +#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) + writelookup2[virt >> 12] = (uintptr_t) &ram[(uintptr_t) (phys & ~0xFFF) - (uintptr_t) (virt & ~0xfff)]; +#else + a = ((uint32_t) (phys & ~0xfff) - (uint32_t) (virt & ~0xfff)); + + if ((phys & ~0xfff) >= (1 << 30)) + writelookup2[virt >> 12] = (uintptr_t) &ram2[a - (1 << 30)]; + else + writelookup2[virt >> 12] = (uintptr_t) &ram[a]; +#endif + } + writelookupp[virt >> 12] = mmu_perm; + + writelookup[writelnext++] = virt >> 12; + writelnext &= (cachesize - 1); + + cycles -= 9; +} + +uint8_t * +getpccache(uint32_t a) +{ + uint64_t a64 = (uint64_t) a; + uint32_t a2; + + a2 = a; + + if (cr0 >> 31) { + a64 = mmutranslate_read(a64); + + if (a64 == 0xffffffffffffffffULL) + return ram; + } + a64 &= rammask; + + if (_mem_exec[a64 >> MEM_GRANULARITY_BITS]) { + if (is286) { + if (read_mapping[a64 >> MEM_GRANULARITY_BITS] && (read_mapping[a64 >> MEM_GRANULARITY_BITS]->flags & MEM_MAPPING_ROM_WS)) + cpu_prefetch_cycles = cpu_rom_prefetch_cycles; + else + cpu_prefetch_cycles = cpu_mem_prefetch_cycles; + } + + return &_mem_exec[a64 >> MEM_GRANULARITY_BITS][(uintptr_t) (a64 & MEM_GRANULARITY_PAGE) - (uintptr_t) (a2 & ~0xfff)]; + } + + mem_log("Bad getpccache %08X%08X\n", (uint32_t) (a64 >> 32), (uint32_t) (a64 & 0xffffffffULL)); + + return (uint8_t *) &ff_pccache; +} + +uint8_t +read_mem_b(uint32_t addr) +{ + mem_mapping_t *map; + uint8_t ret = 0xff; + int old_cycles = cycles; + + mem_logical_addr = addr; + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_b) + ret = map->read_b(addr, map->p); + + resub_cycles(old_cycles); + + return ret; +} + +uint16_t +read_mem_w(uint32_t addr) +{ + mem_mapping_t *map; + uint16_t ret = 0xffff; + int old_cycles = cycles; + + mem_logical_addr = addr; + addr &= rammask; + + if (addr & 1) + ret = read_mem_b(addr) | (read_mem_b(addr + 1) << 8); + else { + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + ret = map->read_w(addr, map->p); + else if (map && map->read_b) + ret = map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); + } + + resub_cycles(old_cycles); + + return ret; +} + +void +write_mem_b(uint32_t addr, uint8_t val) +{ + mem_mapping_t *map; + int old_cycles = cycles; + + mem_logical_addr = addr; + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->write_b) + map->write_b(addr, val, map->p); + + resub_cycles(old_cycles); +} + +void +write_mem_w(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map; + int old_cycles = cycles; + + mem_logical_addr = addr; + addr &= rammask; + + if (addr & 1) { + write_mem_b(addr, val); + write_mem_b(addr + 1, val >> 8); + } else { + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map) { + if (map->write_w) + map->write_w(addr, val, map->p); + else if (map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + } + } + } + + resub_cycles(old_cycles); +} + +uint8_t +readmembl(uint32_t addr) +{ + mem_mapping_t *map; + uint64_t a; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[RB ] %08X\n", addr); + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + + addr64 = (uint64_t) addr; + mem_logical_addr = addr; + + high_page = 0; + + if (cr0 >> 31) { + a = mmutranslate_read(addr); + addr64 = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xff; + } + addr = (uint32_t) (addr64 & rammask); + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_b) + return map->read_b(addr, map->p); + + return 0xff; +} + +void +writemembl(uint32_t addr, uint8_t val) +{ + mem_mapping_t *map; + uint64_t a; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[WB ] %08X = %02X\n", addr, val); + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); + + addr64 = (uint64_t) addr; + mem_logical_addr = addr; + + high_page = 0; + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { + page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); + return; + } + + if (cr0 >> 31) { + a = mmutranslate_write(addr); + addr64 = (uint32_t) a; + + if (a > 0xffffffffULL) + return; + } + addr = (uint32_t) (addr64 & rammask); + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->write_b) + map->write_b(addr, val, map->p); +} + +/* Read a byte from memory without MMU translation - result of previous MMU translation passed as value. */ +uint8_t +readmembl_no_mmut(uint32_t addr, uint32_t a64) +{ + mem_mapping_t *map; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[RBN] %08X\n", addr); + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); + + mem_logical_addr = addr; + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xff; + + addr = a64 & rammask; + } else + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_b) + return map->read_b(addr, map->p); + + return 0xff; +} + +/* Write a byte to memory without MMU translation - result of previous MMU translation passed as value. */ +void +writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val) +{ + mem_mapping_t *map; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[WBN] %08X = %02X\n", addr, val); + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); + + mem_logical_addr = addr; + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { + page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); + return; + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + + addr = a64 & rammask; + } else + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->write_b) + map->write_b(addr, val, map->p); +} + +uint16_t +readmemwl(uint32_t addr) +{ + mem_mapping_t *map; + int i; + uint64_t a; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[RW ] %08X\n", addr); + + addr64a[0] = addr; + addr64a[1] = addr + 1; + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + for (i = 0; i < 2; i++) { + a = mmutranslate_read(addr + i); + addr64a[i] = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xffff; + } + } + + return readmembl_no_mmut(addr, addr64a[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint16_t *) (readlookup2[addr >> 12] + addr); + } + } + + if (cr0 >> 31) { + a = mmutranslate_read(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xffff; + } else + addr64a[0] = (uint64_t) addr; + + addr = addr64a[0] & rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr, map->p); + + if (map && map->read_b) { + return map->read_b(addr, map->p) | ((uint16_t) (map->read_b(addr + 1, map->p)) << 8); + } + + return 0xffff; +} + +void +writememwl(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map; + int i; + uint64_t a; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[WW ] %08X = %04X\n", addr, val); + + addr64a[0] = addr; + addr64a[1] = addr + 1; + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + for (i = 0; i < 2; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + a = mmutranslate_write(addr + i); + addr64a[i] = (uint32_t) a; + + if (a > 0xffffffffULL) + return; + } + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writemembl_no_mmut(addr, addr64a[0], val); + writemembl_no_mmut(addr + 1, addr64a[1], val >> 8); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint16_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } + } + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { + page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); + mmu_perm = page_lookupp[addr >> 12]; + return; + } + + if (cr0 >> 31) { + a = mmutranslate_write(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return; + } + + addr = addr64a[0] & rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_w) { + map->write_w(addr, val, map->p); + return; + } + + if (map && map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + return; + } +} + +/* Read a word from memory without MMU translation - results of previous MMU translation passed as array. */ +uint16_t +readmemwl_no_mmut(uint32_t addr, uint32_t *a64) +{ + mem_mapping_t *map; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[RWN] %08X\n", addr); + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffff; + } + + return readmembl_no_mmut(addr, a64[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint16_t *) (readlookup2[addr >> 12] + addr); + } + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffff; + + addr = (uint32_t) (a64[0] & rammask); + } else + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_w) + return map->read_w(addr, map->p); + + if (map && map->read_b) { + return map->read_b(addr, map->p) | ((uint16_t) (map->read_b(addr + 1, map->p)) << 8); + } + + return 0xffff; +} + +/* Write a word to memory without MMU translation - results of previous MMU translation passed as array. */ +void +writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) +{ + mem_mapping_t *map; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[WWN] %08X = %04X\n", addr, val); + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); + + mem_logical_addr = addr; + + if (addr & 1) { + if (!cpu_cyrix_alignment || (addr & 7) == 7) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffe) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + } + + writemembl_no_mmut(addr, a64[0], val); + writemembl_no_mmut(addr + 1, a64[1], val >> 8); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint16_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } + } + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { + mmu_perm = page_lookupp[addr >> 12]; + page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); + return; + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + + addr = (uint32_t) (a64[0] & rammask); + } else + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_w) { + map->write_w(addr, val, map->p); + return; + } + + if (map && map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + return; + } +} + +uint32_t +readmemll(uint32_t addr) +{ + mem_mapping_t *map; + int i; + uint64_t a = 0x0000000000000000ULL; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[RL ] %08X\n", addr); + + for (i = 0; i < 4; i++) + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + for (i = 0; i < 4; i++) { + if (i == 0) { + a = mmutranslate_read(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_read(addr + 3); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + + if (a > 0xffffffffULL) + return 0xffff; + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + return readmemwl_no_mmut(addr, addr64a) | (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint32_t *) (readlookup2[addr >> 12] + addr); + } + } + + if (cr0 >> 31) { + a = mmutranslate_read(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xffffffff; + } + + addr = addr64a[0] & rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_l) + return map->read_l(addr, map->p); + + if (map && map->read_w) + return map->read_w(addr, map->p) | ((uint32_t) (map->read_w(addr + 2, map->p)) << 16); + + if (map && map->read_b) + return map->read_b(addr, map->p) | ((uint32_t) (map->read_b(addr + 1, map->p)) << 8) | ((uint32_t) (map->read_b(addr + 2, map->p)) << 16) | ((uint32_t) (map->read_b(addr + 3, map->p)) << 24); + + return 0xffffffff; +} + +void +writememll(uint32_t addr, uint32_t val) +{ + mem_mapping_t *map; + int i; + uint64_t a = 0x0000000000000000ULL; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[WL ] %08X = %08X\n", addr, val); + + for (i = 0; i < 4; i++) + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + for (i = 0; i < 4; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + if (i == 0) { + a = mmutranslate_write(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_write(addr + 3); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + + if (a > 0xffffffffULL) + return; + } + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writememwl_no_mmut(addr, &(addr64a[0]), val); + writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint32_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } + } + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { + mmu_perm = page_lookupp[addr >> 12]; + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); + return; + } + + if (cr0 >> 31) { + a = mmutranslate_write(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return; + } + + addr = addr64a[0] & rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[WL ] map = %08X\n", map); + + if (map && map->write_l) { + map->write_l(addr, val, map->p); + return; + } + if (map && map->write_w) { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + return; + } + if (map && map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + return; + } +} + +/* Read a long from memory without MMU translation - results of previous MMU translation passed as array. */ +uint32_t +readmemll_no_mmut(uint32_t addr, uint32_t *a64) +{ + mem_mapping_t *map; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[RLN] %08X\n", addr); + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); + + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffffffff; + } + + return readmemwl_no_mmut(addr, a64) | ((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint32_t *) (readlookup2[addr >> 12] + addr); + } + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return 0xffffffff; + + addr = (uint32_t) (a64[0] & rammask); + } else + addr &= rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->read_l) + return map->read_l(addr, map->p); + + if (map && map->read_w) + return map->read_w(addr, map->p) | ((uint32_t) (map->read_w(addr + 2, map->p)) << 16); + + if (map && map->read_b) + return map->read_b(addr, map->p) | ((uint32_t) (map->read_b(addr + 1, map->p)) << 8) | ((uint32_t) (map->read_b(addr + 2, map->p)) << 16) | ((uint32_t) (map->read_b(addr + 3, map->p)) << 24); + + return 0xffffffff; +} + +/* Write a long to memory without MMU translation - results of previous MMU translation passed as array. */ +void +writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val) +{ + mem_mapping_t *map; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[WLN] %08X = %08X\n", addr, val); + + GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); + + mem_logical_addr = addr; + + if (addr & 3) { + if (!cpu_cyrix_alignment || (addr & 7) > 4) + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xffc) { + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + } + + writememwl_no_mmut(addr, &(a64[0]), val); + writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint32_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } + } + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { + mmu_perm = page_lookupp[addr >> 12]; + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); + return; + } + + if (cr0 >> 31) { + if (cpu_state.abrt || high_page) + return; + + addr = (uint32_t) (a64[0] & rammask); + } else + addr &= rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_l) { + map->write_l(addr, val, map->p); + return; + } + if (map && map->write_w) { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + return; + } + if (map && map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + return; + } +} + +uint64_t +readmemql(uint32_t addr) +{ + mem_mapping_t *map; + int i; + uint64_t a = 0x0000000000000000ULL; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[RQ ] %08X\n", addr); + + for (i = 0; i < 8; i++) + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 7) { + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xff8) { + if (cr0 >> 31) { + for (i = 0; i < 8; i++) { + if (i == 0) { + a = mmutranslate_read(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_read(addr + 7); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + + if (a > 0xffffffffULL) + return 0xffff; + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + return readmemll_no_mmut(addr, addr64a) | (((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32); + } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = readlookupp[addr >> 12]; + return *(uint64_t *) (readlookup2[addr >> 12] + addr); + } + } + + if (cr0 >> 31) { + a = mmutranslate_read(addr); + addr64a[0] = (uint32_t) a; + + if (a > 0xffffffffULL) + return 0xffffffffffffffffULL; + } + + addr = addr64a[0] & rammask; + + map = read_mapping[addr >> MEM_GRANULARITY_BITS]; + if (map && map->read_l) + return map->read_l(addr, map->p) | ((uint64_t) map->read_l(addr + 4, map->p) << 32); + + return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32); +} + +void +writememql(uint32_t addr, uint64_t val) +{ + mem_mapping_t *map; + int i; + uint64_t a = 0x0000000000000000ULL; + + if ((addr >= 0xec000000) && (addr <= 0xecffffff)) + pclog("[WQ ] %08X = %016" PRIX64 "\n", addr, val); + + for (i = 0; i < 8; i++) + addr64a[i] = (uint64_t) (addr + i); + GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); + + mem_logical_addr = addr; + + high_page = 0; + + if (addr & 7) { + cycles -= timing_misaligned; + if ((addr & 0xfff) > 0xff8) { + if (cr0 >> 31) { + for (i = 0; i < 8; i++) { + /* Do not translate a page that has a valid lookup, as that is by definition valid + and the whole purpose of the lookup is to avoid repeat identical translations. */ + if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { + if (i == 0) { + a = mmutranslate_write(addr + i); + addr64a[i] = (uint32_t) a; + } else if (!((addr + i) & 0xfff)) { + a = mmutranslate_write(addr + 7); + addr64a[i] = (uint32_t) a; + if (!cpu_state.abrt) { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + } else { + a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); + addr64a[i] = (uint32_t) a; + } + + if (addr64a[i] > 0xffffffffULL) + return; + } + } + } + + /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass + their result as a parameter to be used if needed. */ + writememll_no_mmut(addr, addr64a, val); + writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32); + return; + } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { + mmu_perm = writelookupp[addr >> 12]; + *(uint64_t *) (writelookup2[addr >> 12] + addr) = val; + return; + } + } + + if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { + mmu_perm = page_lookupp[addr >> 12]; + page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); + page_lookup[addr >> 12]->write_l(addr + 4, val >> 32, page_lookup[addr >> 12]); + return; + } + + if (cr0 >> 31) { + addr64a[0] = mmutranslate_write(addr); + if (addr64a[0] > 0xffffffffULL) + return; + } + + addr = addr64a[0] & rammask; + + map = write_mapping[addr >> MEM_GRANULARITY_BITS]; + + if (map && map->write_l) { + map->write_l(addr, val, map->p); + map->write_l(addr + 4, val >> 32, map->p); + return; + } + if (map && map->write_w) { + map->write_w(addr, val, map->p); + map->write_w(addr + 2, val >> 16, map->p); + map->write_w(addr + 4, val >> 32, map->p); + map->write_w(addr + 6, val >> 48, map->p); + return; + } + if (map && map->write_b) { + map->write_b(addr, val, map->p); + map->write_b(addr + 1, val >> 8, map->p); + map->write_b(addr + 2, val >> 16, map->p); + map->write_b(addr + 3, val >> 24, map->p); + map->write_b(addr + 4, val >> 32, map->p); + map->write_b(addr + 5, val >> 40, map->p); + map->write_b(addr + 6, val >> 48, map->p); + map->write_b(addr + 7, val >> 56, map->p); + return; + } +} + +void +do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) +{ + int i, cond = 1; + uint32_t last_addr = addr + (num - 1); + uint64_t a = 0x0000000000000000ULL; + + for (i = 0; i < num; i++) + a64[i] = (uint64_t) addr; + + for (i = 0; i < num; i++) { + if (cr0 >> 31) { + if (write && ((i == 0) || !(addr & 0xfff))) + cond = (!page_lookup[addr >> 12] || !page_lookup[addr >> 12]->write_b); + + if (cond) { + /* If we have encountered at least one page fault, mark all subsequent addresses as + having page faulted, prevents false negatives in readmem*l_no_mmut. */ + if ((i > 0) && cpu_state.abrt && !high_page) + a64[i] = a64[i - 1]; + /* If we are on the same page, there is no need to translate again, as we can just + reuse the previous result. */ + else if (i == 0) { + a = mmutranslatereal(addr, write); + a64[i] = (uint32_t) a; + + high_page = high_page || (!cpu_state.abrt && (a > 0xffffffffULL)); + } else if (!(addr & 0xfff)) { + a = mmutranslatereal(last_addr, write); + a64[i] = (uint32_t) a; + + high_page = high_page || (!cpu_state.abrt && (a64[i] > 0xffffffffULL)); + + if (!cpu_state.abrt) { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; + } + } else { + a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); + a64[i] = (uint32_t) a; + } + } else + mmu_perm = page_lookupp[addr >> 12]; + } + + addr++; + } +} + +uint8_t +mem_readb_phys(uint32_t addr) +{ + mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; + uint8_t ret = 0xff; + + mem_logical_addr = 0xffffffff; + + if (map) { + if (map->exec) + ret = map->exec[(addr - map->base) & map->mask]; + else if (map->read_b) + ret = map->read_b(addr, map->p); + } + + return ret; +} + +uint16_t +mem_readw_phys(uint32_t addr) +{ + mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; + uint16_t ret, *p; + + mem_logical_addr = 0xffffffff; + + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { + p = (uint16_t *) &(map->exec[(addr - map->base) & map->mask]); + ret = *p; + } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) + ret = map->read_w(addr, map->p); + else { + ret = mem_readb_phys(addr + 1) << 8; + ret |= mem_readb_phys(addr); + } + + return ret; +} + +uint32_t +mem_readl_phys(uint32_t addr) +{ + mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; + uint32_t ret, *p; + + mem_logical_addr = 0xffffffff; + + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { + p = (uint32_t *) &(map->exec[(addr - map->base) & map->mask]); + ret = *p; + } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) + ret = map->read_l(addr, map->p); + else { + ret = mem_readw_phys(addr + 2) << 16; + ret |= mem_readw_phys(addr); + } + + return ret; +} + +void +mem_read_phys(void *dest, uint32_t addr, int transfer_size) +{ + uint8_t *pb; + uint16_t *pw; + uint32_t *pl; + + if (transfer_size == 4) { + pl = (uint32_t *) dest; + *pl = mem_readl_phys(addr); + } else if (transfer_size == 2) { + pw = (uint16_t *) dest; + *pw = mem_readw_phys(addr); + } else if (transfer_size == 1) { + pb = (uint8_t *) dest; + *pb = mem_readb_phys(addr); + } +} + +void +mem_writeb_phys(uint32_t addr, uint8_t val) +{ + mem_mapping_t *map = write_mapping_bus[addr >> MEM_GRANULARITY_BITS]; + + mem_logical_addr = 0xffffffff; + + if (map) { + if (map->exec) + map->exec[(addr - map->base) & map->mask] = val; + else if (map->write_b) + map->write_b(addr, val, map->p); + } +} + +void +mem_writew_phys(uint32_t addr, uint16_t val) +{ + mem_mapping_t *map = write_mapping_bus[addr >> MEM_GRANULARITY_BITS]; + uint16_t *p; + + mem_logical_addr = 0xffffffff; + + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { + p = (uint16_t *) &(map->exec[(addr - map->base) & map->mask]); + *p = val; + } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->write_w)) + map->write_w(addr, val, map->p); + else { + mem_writeb_phys(addr, val & 0xff); + mem_writeb_phys(addr + 1, (val >> 8) & 0xff); + } +} + +void +mem_writel_phys(uint32_t addr, uint32_t val) +{ + mem_mapping_t *map = write_mapping_bus[addr >> MEM_GRANULARITY_BITS]; + uint32_t *p; + + mem_logical_addr = 0xffffffff; + + if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { + p = (uint32_t *) &(map->exec[(addr - map->base) & map->mask]); + *p = val; + } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) + map->write_l(addr, val, map->p); + else { + mem_writew_phys(addr, val & 0xffff); + mem_writew_phys(addr + 2, (val >> 16) & 0xffff); + } +} + +void +mem_write_phys(void *src, uint32_t addr, int transfer_size) +{ + uint8_t *pb; + uint16_t *pw; + uint32_t *pl; + + if (transfer_size == 4) { + pl = (uint32_t *) src; + mem_writel_phys(addr, *pl); + } else if (transfer_size == 2) { + pw = (uint16_t *) src; + mem_writew_phys(addr, *pw); + } else if (transfer_size == 1) { + pb = (uint8_t *) src; + mem_writeb_phys(addr, *pb); + } +} + +uint8_t +mem_read_ram(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read B %02X from %08X\n", ram[addr], addr); +#endif + + if (is286) + addreadlookup(mem_logical_addr, addr); + + return ram[addr]; +} + +uint16_t +mem_read_ramw(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read W %04X from %08X\n", *(uint16_t *) &ram[addr], addr); +#endif + + if (is286) + addreadlookup(mem_logical_addr, addr); + + return *(uint16_t *) &ram[addr]; +} + +uint32_t +mem_read_raml(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read L %08X from %08X\n", *(uint32_t *) &ram[addr], addr); +#endif + + if (is286) + addreadlookup(mem_logical_addr, addr); + + return *(uint32_t *) &ram[addr]; +} + +uint8_t +mem_read_ram_2gb(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read B %02X from %08X\n", ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return ram2[addr - (1 << 30)]; +} + +uint16_t +mem_read_ram_2gbw(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read W %04X from %08X\n", *(uint16_t *) &ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return *(uint16_t *) &ram2[addr - (1 << 30)]; +} + +uint32_t +mem_read_ram_2gbl(uint32_t addr, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Read L %08X from %08X\n", *(uint32_t *) &ram[addr], addr); +#endif + + addreadlookup(mem_logical_addr, addr); + + return *(uint32_t *) &ram2[addr - (1 << 30)]; +} + +#ifdef USE_NEW_DYNAREC +static inline int +page_index(page_t *p) +{ + return ((uintptr_t) p - (uintptr_t) pages) / sizeof(page_t); +} + +void +page_add_to_evict_list(page_t *p) +{ + pages[purgable_page_list_head].evict_prev = page_index(p); + p->evict_next = purgable_page_list_head; + p->evict_prev = 0; + purgable_page_list_head = pages[purgable_page_list_head].evict_prev; + purgeable_page_count++; +} + +void +page_remove_from_evict_list(page_t *p) +{ + if (!page_in_evict_list(p)) + fatal("page_remove_from_evict_list: not in evict list!\n"); + if (p->evict_prev) + pages[p->evict_prev].evict_next = p->evict_next; + else + purgable_page_list_head = p->evict_next; + if (p->evict_next) + pages[p->evict_next].evict_prev = p->evict_prev; + p->evict_prev = EVICT_NOT_IN_LIST; + purgeable_page_count--; +} + +void +mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) +{ + if (p == NULL) + return; + +# ifdef USE_DYNAREC + if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t) 1 << (addr & PAGE_BYTE_MASK_MASK); + + p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + p->byte_dirty_mask[byte_offset] |= byte_mask; + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } +} + +void +mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) +{ + if (p == NULL) + return; + +# ifdef USE_DYNAREC + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *) &p->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *) &p->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t) 1 << (addr & PAGE_BYTE_MASK_MASK); + + if ((addr & 0xf) == 0xf) + mask |= (mask << 1); + *(uint16_t *) &p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + if ((p->code_present_mask & mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) { + p->byte_dirty_mask[byte_offset + 1] |= 1; + if ((p->byte_code_present_mask[byte_offset + 1] & 1) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } else + byte_mask |= (byte_mask << 1); + + p->byte_dirty_mask[byte_offset] |= byte_mask; + + if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } +} + +void +mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) +{ + if (p == NULL) + return; + +# ifdef USE_DYNAREC + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *) &p->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *) &p->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = (uint64_t) 0xf << (addr & PAGE_BYTE_MASK_MASK); + + if ((addr & 0xf) >= 0xd) + mask |= (mask << 1); + *(uint32_t *) &p->mem[addr & 0xfff] = val; + p->dirty_mask |= mask; + p->byte_dirty_mask[byte_offset] |= byte_mask; + if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) + page_add_to_evict_list(p); + if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK - 3)) { + uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); + + p->byte_dirty_mask[byte_offset + 1] |= byte_mask_2; + if ((p->byte_code_present_mask[byte_offset + 1] & byte_mask_2) && !page_in_evict_list(p)) + page_add_to_evict_list(p); + } + } +} +#else +void +mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) +{ + if (p == NULL) + return; + +# ifdef USE_DYNAREC + if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + p->mem[addr & 0xfff] = val; + } +} + +void +mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) +{ + if (p == NULL) + return; + +# ifdef USE_DYNAREC + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *) &p->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *) &p->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + if ((addr & 0xf) == 0xf) + mask |= (mask << 1); + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + *(uint16_t *) &p->mem[addr & 0xfff] = val; + } +} + +void +mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) +{ + if (p == NULL) + return; + +# ifdef USE_DYNAREC + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *) &p->mem[addr & 0xfff]) || codegen_in_recompile) { +# else + if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *) &p->mem[addr & 0xfff])) { +# endif + uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + if ((addr & 0xf) >= 0xd) + mask |= (mask << 1); + p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; + *(uint32_t *) &p->mem[addr & 0xfff] = val; + } +} +#endif + +void +mem_write_ram(uint32_t addr, uint8_t val, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Write B %02X to %08X\n", val, addr); +#endif + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[addr >> 12]); + } else + ram[addr] = val; +} + +void +mem_write_ramw(uint32_t addr, uint16_t val, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Write W %04X to %08X\n", val, addr); +#endif + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[addr >> 12]); + } else + *(uint16_t *) &ram[addr] = val; +} + +void +mem_write_raml(uint32_t addr, uint32_t val, void *priv) +{ +#ifdef ENABLE_MEM_LOG + if ((addr >= 0xa0000) && (addr <= 0xbffff)) + mem_log("Write L %08X to %08X\n", val, addr); +#endif + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[addr >> 12]); + } else + *(uint32_t *) &ram[addr] = val; +} + +static uint8_t +mem_read_remapped(uint32_t addr, void *priv) +{ + addr = 0xA0000 + (addr - remap_start_addr); + if (is286) + addreadlookup(mem_logical_addr, addr); + return ram[addr]; +} + +static uint16_t +mem_read_remappedw(uint32_t addr, void *priv) +{ + addr = 0xA0000 + (addr - remap_start_addr); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint16_t *) &ram[addr]; +} + +static uint32_t +mem_read_remappedl(uint32_t addr, void *priv) +{ + addr = 0xA0000 + (addr - remap_start_addr); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint32_t *) &ram[addr]; +} + +static uint8_t +mem_read_remapped2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return ram[addr]; +} + +static uint16_t +mem_read_remappedw2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint16_t *) &ram[addr]; +} + +static uint32_t +mem_read_remappedl2(uint32_t addr, void *priv) +{ + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) + addreadlookup(mem_logical_addr, addr); + return *(uint32_t *) &ram[addr]; +} + +static void +mem_write_remapped(uint32_t addr, uint8_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xA0000 + (addr - remap_start_addr); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); + } else + ram[addr] = val; +} + +static void +mem_write_remappedw(uint32_t addr, uint16_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xA0000 + (addr - remap_start_addr); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint16_t *) &ram[addr] = val; +} + +static void +mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xA0000 + (addr - remap_start_addr); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint32_t *) &ram[addr] = val; +} + +static void +mem_write_remapped2(uint32_t addr, uint8_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); + } else + ram[addr] = val; +} + +static void +mem_write_remappedw2(uint32_t addr, uint16_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint16_t *) &ram[addr] = val; +} + +static void +mem_write_remappedl2(uint32_t addr, uint32_t val, void *priv) +{ + uint32_t oldaddr = addr; + addr = 0xD0000 + (addr - remap_start_addr2); + if (is286) { + addwritelookup(mem_logical_addr, addr); + mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); + } else + *(uint32_t *) &ram[addr] = val; +} + +void +mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) +{ +#ifdef USE_NEW_DYNAREC + page_t *p; + + start_addr &= ~PAGE_MASK_MASK; + end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + + for (; start_addr <= end_addr; start_addr += 0x1000) { + if ((start_addr >> 12) >= pages_sz) + continue; + + p = &pages[start_addr >> 12]; + if (p) { + p->dirty_mask = 0xffffffffffffffffULL; + + if (p->byte_dirty_mask) + memset(p->byte_dirty_mask, 0xff, 64 * sizeof(uint64_t)); + + if (!page_in_evict_list(p)) + page_add_to_evict_list(p); + } + } +#else + uint32_t cur_addr; + start_addr &= ~PAGE_MASK_MASK; + end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; + + for (; start_addr <= end_addr; start_addr += 0x1000) { + /* Do nothing if the pages array is empty or DMA reads/writes to/from PCI device memory addresses + may crash the emulator. */ + cur_addr = (start_addr >> 12); + if (cur_addr < pages_sz) + memset(pages[cur_addr].dirty_mask, 0xff, sizeof(pages[cur_addr].dirty_mask)); + } +#endif +} + +static __inline int +mem_mapping_access_allowed(uint32_t flags, uint16_t access) +{ + int ret = 0; + + if (!(access & ACCESS_DISABLED)) { + if (access & ACCESS_CACHE) + ret = (flags & MEM_MAPPING_CACHE); + else if (access & ACCESS_SMRAM) + ret = (flags & MEM_MAPPING_SMRAM); + else if (!(access & ACCESS_INTERNAL)) { + if (flags & MEM_MAPPING_IS_ROM) { + if (access & ACCESS_ROMCS) + ret = (flags & MEM_MAPPING_ROMCS); + else + ret = !(flags & MEM_MAPPING_ROMCS); + } else + ret = 1; + + ret = ret && !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); + } else + ret = !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); + } else { + /* Still allow SMRAM if access is DISABLED but also has CACHE and/or SMRAM flags set. */ + if (access & ACCESS_CACHE) + ret = (flags & MEM_MAPPING_CACHE); + else if (access & ACCESS_SMRAM) + ret = (flags & MEM_MAPPING_SMRAM); + } + + return ret; +} + +void +mem_mapping_recalc(uint64_t base, uint64_t size) +{ + mem_mapping_t *map; + int n; + uint64_t c; + + if ((base >= 0xec000000) && (base <= 0xecffffff)) + pclog("mem_mapping_recalc(%016" PRIX64 ", %016" PRIX64 ")\n", base, size); + + if (!size || (base_mapping == NULL)) + return; + + map = base_mapping; + + /* Clear out old mappings. */ + for (c = base; c < base + size; c += MEM_GRANULARITY_SIZE) { + _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; + write_mapping[c >> MEM_GRANULARITY_BITS] = NULL; + read_mapping[c >> MEM_GRANULARITY_BITS] = NULL; + write_mapping_bus[c >> MEM_GRANULARITY_BITS] = NULL; + read_mapping_bus[c >> MEM_GRANULARITY_BITS] = NULL; + } + + /* Walk mapping list. */ + while (map != NULL) { + /* In range? */ + if (map->enable && (uint64_t) map->base < ((uint64_t) base + (uint64_t) size) && ((uint64_t) map->base + (uint64_t) map->size) > (uint64_t) base) { + uint64_t start = (map->base < base) ? map->base : base; + uint64_t end = (((uint64_t) map->base + (uint64_t) map->size) < (base + size)) ? ((uint64_t) map->base + (uint64_t) map->size) : (base + size); + if (start < map->base) + start = map->base; + + for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { + /* CPU */ + n = !!in_smm; + if ((c >= 0xec000000) && (c <= 0xecffffff)) + pclog("mem_mapping_recalc(): map = %08X (%02X) (%02X, %02X, %02X)\n", map, map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].x); + if (map->exec && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].x)) + _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); + if ((map->write_b || map->write_w || map->write_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) + write_mapping[c >> MEM_GRANULARITY_BITS] = map; + if ((map->read_b || map->read_w || map->read_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) + read_mapping[c >> MEM_GRANULARITY_BITS] = map; + + /* Bus */ + n |= STATE_BUS; + if ((map->write_b || map->write_w || map->write_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) + write_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; + if ((map->read_b || map->read_w || map->read_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) + read_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; + } + } + map = map->next; + } + + flushmmucache_cr3(); + +#ifdef ENABLE_MEM_LOG + pclog("\nMemory map:\n"); + mem_mapping_t *write = (mem_mapping_t *) -1, *read = (mem_mapping_t *) -1, *write_bus = (mem_mapping_t *) -1, *read_bus = (mem_mapping_t *) -1; + for (c = 0; c < (sizeof(write_mapping) / sizeof(write_mapping[0])); c++) { + if ((write_mapping[c] == write) && (read_mapping[c] == read) && (write_mapping_bus[c] == write_bus) && (read_mapping_bus[c] == read_bus)) + continue; + write = write_mapping[c]; + read = read_mapping[c]; + write_bus = write_mapping_bus[c]; + read_bus = read_mapping_bus[c]; + + pclog("%08X | ", c << MEM_GRANULARITY_BITS); + if (read) { + pclog("R%c%c%c %08X+% 8X", + read->read_b ? 'b' : ' ', read->read_w ? 'w' : ' ', read->read_l ? 'l' : ' ', + read->base, read->size); + } else { + pclog(" "); + } + if (write) { + pclog(" | W%c%c%c %08X+% 8X", + write->write_b ? 'b' : ' ', write->write_w ? 'w' : ' ', write->write_l ? 'l' : ' ', + write->base, write->size); + } else { + pclog(" | "); + } + pclog(" | %c\n", _mem_exec[c] ? 'X' : ' '); + + if ((write != write_bus) || (read != read_bus)) { + pclog(" ^ bus | "); + if (read_bus) { + pclog("R%c%c%c %08X+% 8X", + read_bus->read_b ? 'b' : ' ', read_bus->read_w ? 'w' : ' ', read_bus->read_l ? 'l' : ' ', + read_bus->base, read_bus->size); + } else { + pclog(" "); + } + if (write_bus) { + pclog(" | W%c%c%c %08X+% 8X", + write_bus->write_b ? 'b' : ' ', write_bus->write_w ? 'w' : ' ', write_bus->write_l ? 'l' : ' ', + write_bus->base, write_bus->size); + } else { + pclog(" | "); + } + pclog(" |\n"); + } + } + pclog("\n"); +#endif +} + +void +mem_mapping_set(mem_mapping_t *map, + uint32_t base, + uint32_t size, + uint8_t (*read_b)(uint32_t addr, void *p), + uint16_t (*read_w)(uint32_t addr, void *p), + uint32_t (*read_l)(uint32_t addr, void *p), + void (*write_b)(uint32_t addr, uint8_t val, void *p), + void (*write_w)(uint32_t addr, uint16_t val, void *p), + void (*write_l)(uint32_t addr, uint32_t val, void *p), + uint8_t *exec, + uint32_t fl, + void *p) +{ + if (size != 0x00000000) + map->enable = 1; + else + map->enable = 0; + map->base = base; + map->size = size; + map->mask = (map->size ? 0xffffffff : 0x00000000); + map->read_b = read_b; + map->read_w = read_w; + map->read_l = read_l; + map->write_b = write_b; + map->write_w = write_w; + map->write_l = write_l; + map->exec = exec; + map->flags = fl; + map->p = p; + map->next = NULL; + mem_log("mem_mapping_add(): Linked list structure: %08X -> %08X -> %08X\n", map->prev, map, map->next); + + /* If the mapping is disabled, there is no need to recalc anything. */ + if (size != 0x00000000) + mem_mapping_recalc(map->base, map->size); +} + +void +mem_mapping_add(mem_mapping_t *map, + uint32_t base, + uint32_t size, + uint8_t (*read_b)(uint32_t addr, void *p), + uint16_t (*read_w)(uint32_t addr, void *p), + uint32_t (*read_l)(uint32_t addr, void *p), + void (*write_b)(uint32_t addr, uint8_t val, void *p), + void (*write_w)(uint32_t addr, uint16_t val, void *p), + void (*write_l)(uint32_t addr, uint32_t val, void *p), + uint8_t *exec, + uint32_t fl, + void *p) +{ + /* Do a sanity check */ + if ((base_mapping == NULL) && (last_mapping != NULL)) { + fatal("mem_mapping_add(): NULL base mapping with non-NULL last mapping\n"); + return; + } else if ((base_mapping != NULL) && (last_mapping == NULL)) { + fatal("mem_mapping_add(): Non-NULL base mapping with NULL last mapping\n"); + return; + } else if ((base_mapping != NULL) && (base_mapping->prev != NULL)) { + fatal("mem_mapping_add(): Base mapping with a preceding mapping\n"); + return; + } else if ((last_mapping != NULL) && (last_mapping->next != NULL)) { + fatal("mem_mapping_add(): Last mapping with a following mapping\n"); + return; + } + + /* Add mapping to the beginning of the list if necessary.*/ + if (base_mapping == NULL) + base_mapping = map; + + /* Add mapping to the end of the list.*/ + if (last_mapping == NULL) + map->prev = NULL; + else { + map->prev = last_mapping; + last_mapping->next = map; + } + last_mapping = map; + + mem_mapping_set(map, base, size, read_b, read_w, read_l, + write_b, write_w, write_l, exec, fl, p); +} + +void +mem_mapping_do_recalc(mem_mapping_t *map) +{ + mem_mapping_recalc(map->base, map->size); +} + +void +mem_mapping_set_handler(mem_mapping_t *map, + uint8_t (*read_b)(uint32_t addr, void *p), + uint16_t (*read_w)(uint32_t addr, void *p), + uint32_t (*read_l)(uint32_t addr, void *p), + void (*write_b)(uint32_t addr, uint8_t val, void *p), + void (*write_w)(uint32_t addr, uint16_t val, void *p), + void (*write_l)(uint32_t addr, uint32_t val, void *p)) +{ + map->read_b = read_b; + map->read_w = read_w; + map->read_l = read_l; + map->write_b = write_b; + map->write_w = write_w; + map->write_l = write_l; + + mem_mapping_recalc(map->base, map->size); +} + +void +mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) +{ + if ((base >= 0xec000000) && (base <= 0xecffffff)) + pclog("[0] mem_mapping_set_addr(%08X, %08X)\n", base, size); + + /* Remove old mapping. */ + map->enable = 0; + mem_mapping_recalc(map->base, map->size); + + if ((base >= 0xec000000) && (base <= 0xecffffff)) + pclog("[1] mem_mapping_set_addr(%08X, %08X)\n", base, size); + + /* Set new mapping. */ + map->enable = 1; + map->base = base; + map->size = size; + + if ((base >= 0xec000000) && (base <= 0xecffffff)) + pclog("[2] mem_mapping_set_addr(%08X, %08X)\n", base, size); + + mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); +} + +void +mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) +{ + map->exec = exec; + + mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); +} + +void +mem_mapping_set_mask(mem_mapping_t *map, uint32_t mask) +{ + map->mask = mask; + + mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); +} + +void +mem_mapping_set_p(mem_mapping_t *map, void *p) +{ + map->p = p; +} + +void +mem_mapping_disable(mem_mapping_t *map) +{ + map->enable = 0; + + mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); +} + +void +mem_mapping_enable(mem_mapping_t *map) +{ + map->enable = 1; + + mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); +} + +void +mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t access) +{ + uint32_t c; + uint16_t mask, smstate = 0x0000; + const uint16_t smstates[4] = { 0x0000, (MEM_READ_SMRAM | MEM_WRITE_SMRAM), + MEM_READ_SMRAM_EX, (MEM_READ_DISABLED_EX | MEM_WRITE_DISABLED_EX) }; + + int i; + + if (mode) + mask = 0x2d6b; + else + mask = 0x1084; + + if (mode) { + if (mode == 1) + access = !!access; + + if (mode == 3) { + if (access & ACCESS_SMRAM_X) + smstate |= MEM_EXEC_SMRAM; + if (access & ACCESS_SMRAM_R) + smstate |= MEM_READ_SMRAM_2; + if (access & ACCESS_SMRAM_W) + smstate |= MEM_WRITE_SMRAM; + } else + smstate = smstates[access & 0x07]; + } else + smstate = access & 0x6f7b; + + for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { + for (i = 0; i < 4; i++) { + if (bitmap & (1 << i)) { + _mem_state[(c + base) >> MEM_GRANULARITY_BITS].vals[i] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS].vals[i] & mask) | smstate; + } + } + +#ifdef ENABLE_MEM_LOG + if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) { + mem_log("Set mem state for block at %08X to %04X with bitmap %02X\n", + c + base, smstate, bitmap); + } +#endif + } + + mem_mapping_recalc(base, size); +} + +void +mem_a20_init(void) +{ + if (is286) { + mem_a20_key = mem_a20_alt = mem_a20_state = 0; + rammask = cpu_16bitbus ? 0xffffff : 0xffffffff; + if (is6117) + rammask |= 0x03000000; + flushmmucache(); + // mem_a20_state = mem_a20_key | mem_a20_alt; + } else { + rammask = 0xfffff; + flushmmucache(); + mem_a20_key = mem_a20_alt = mem_a20_state = 0; + } +} + +/* Close all the memory mappings. */ +void +mem_close(void) +{ + mem_mapping_t *map = base_mapping, *next; + + while (map != NULL) { + next = map->next; + map->prev = map->next = NULL; + map = next; + } + + base_mapping = last_mapping = 0; +} + +static void +mem_add_ram_mapping(mem_mapping_t *mapping, uint32_t base, uint32_t size) +{ + mem_mapping_add(mapping, base, size, + mem_read_ram, mem_read_ramw, mem_read_raml, + mem_write_ram, mem_write_ramw, mem_write_raml, + ram + base, MEM_MAPPING_INTERNAL, NULL); +} + +static void +mem_init_ram_mapping(mem_mapping_t *mapping, uint32_t base, uint32_t size) +{ + mem_set_mem_state_both(base, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_add_ram_mapping(mapping, base, size); +} + +/* Reset the memory state. */ +void +mem_reset(void) +{ + uint32_t c; + size_t m; + + memset(page_ff, 0xff, sizeof(page_ff)); + +#ifdef USE_NEW_DYNAREC + if (byte_dirty_mask) { + free(byte_dirty_mask); + byte_dirty_mask = NULL; + } + + if (byte_code_present_mask) { + free(byte_code_present_mask); + byte_code_present_mask = NULL; + } +#endif + + /* Free the old pages array, if necessary. */ + if (pages) { + free(pages); + pages = NULL; + } + + if (ram != NULL) { + plat_munmap(ram, ram_size); + ram = NULL; + ram_size = 0; + } +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (ram2 != NULL) { + plat_munmap(ram2, ram2_size); + ram2 = NULL; + ram2_size = 0; + } + + if (mem_size > 2097152) + mem_size = 2097152; +#endif + + m = 1024UL * (size_t) mem_size; + +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (mem_size > 1048576) { + ram_size = 1 << 30; + ram = (uint8_t *) plat_mmap(ram_size, 0); /* allocate and clear the RAM block of the first 1 GB */ + if (ram == NULL) { + fatal("Failed to allocate primary RAM block. Make sure you have enough RAM available.\n"); + return; + } + memset(ram, 0x00, ram_size); + ram2_size = m - (1 << 30); + ram2 = (uint8_t *) plat_mmap(ram2_size, 0); /* allocate and clear the RAM block above 1 GB */ + if (ram2 == NULL) { + if (config_changed == 2) + fatal(EMU_NAME " must be restarted for the memory amount change to be applied.\n"); + else + fatal("Failed to allocate secondary RAM block. Make sure you have enough RAM available.\n"); + return; + } + memset(ram2, 0x00, ram2_size); + } else +#endif + { + ram_size = m; + ram = (uint8_t *) plat_mmap(ram_size, 0); /* allocate and clear the RAM block */ + if (ram == NULL) { + fatal("Failed to allocate RAM block. Make sure you have enough RAM available.\n"); + return; + } + memset(ram, 0x00, ram_size); + if (mem_size > 1048576) + ram2 = &(ram[1 << 30]); + } + + /* + * Allocate the page table based on how much RAM we have. + * We re-allocate the table on each (hard) reset, as the + * memory amount could have changed. + */ + if (is286) { + if (cpu_16bitbus) { + /* 80286/386SX; maximum address space is 16MB. */ + m = 4096; + /* ALi M6117; maximum address space is 64MB. */ + if (is6117) + m <<= 2; + } else { + /* 80386DX+; maximum address space is 4GB. */ + m = 1048576; + } + } else { + /* 8088/86; maximum address space is 1MB. */ + m = 256; + } + + addr_space_size = m; + + /* + * Allocate and initialize the (new) page table. + */ + pages_sz = m; + pages = (page_t *) malloc(m * sizeof(page_t)); + + memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); + memset(page_lookupp, 0x04, (1 << 20) * sizeof(uint8_t)); + + memset(pages, 0x00, pages_sz * sizeof(page_t)); + +#ifdef USE_NEW_DYNAREC + byte_dirty_mask = malloc((mem_size * 1024) / 8); + memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); + + byte_code_present_mask = malloc((mem_size * 1024) / 8); + memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); +#endif + + for (c = 0; c < pages_sz; c++) { + if ((c << 12) >= (mem_size << 10)) + pages[c].mem = page_ff; + else { +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (mem_size > 1048576) { + if ((c << 12) < (1 << 30)) + pages[c].mem = &ram[c << 12]; + else + pages[c].mem = &ram2[(c << 12) - (1 << 30)]; + } else + pages[c].mem = &ram[c << 12]; +#else + pages[c].mem = &ram[c << 12]; +#endif + } + if (c < m) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; + } +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; +#endif + } + + memset(_mem_exec, 0x00, sizeof(_mem_exec)); + memset(write_mapping, 0x00, sizeof(write_mapping)); + memset(read_mapping, 0x00, sizeof(read_mapping)); + memset(write_mapping_bus, 0x00, sizeof(write_mapping_bus)); + memset(read_mapping_bus, 0x00, sizeof(read_mapping_bus)); + + base_mapping = last_mapping = NULL; + + /* Set the entire memory space as external. */ + memset(_mem_state, 0x00, sizeof(_mem_state)); + + /* Set the low RAM space as internal. */ + mem_init_ram_mapping(&ram_low_mapping, 0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024); + + if (mem_size > 1024) { + if (cpu_16bitbus && !is6117 && mem_size > 16256) + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (16256 - 1024) * 1024); + else if (cpu_16bitbus && is6117 && mem_size > 65408) + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (65408 - 1024) * 1024); + else { + if (mem_size > 1048576) { + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (1048576 - 1024) * 1024); + + mem_set_mem_state_both((1 << 30), (mem_size - 1048576) * 1024, + MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); + mem_mapping_add(&ram_2gb_mapping, (1 << 30), + ((mem_size - 1048576) * 1024), + mem_read_ram_2gb, mem_read_ram_2gbw, mem_read_ram_2gbl, + mem_write_ram, mem_write_ramw, mem_write_raml, + ram2, MEM_MAPPING_INTERNAL, NULL); + } else + mem_init_ram_mapping(&ram_high_mapping, 0x100000, (mem_size - 1024) * 1024); + } + } + + if (mem_size > 768) { + mem_add_ram_mapping(&ram_mid_mapping, 0xa0000, 0x60000); + + mem_add_ram_mapping(&ram_mid_mapping2, 0xa0000, 0x60000); + mem_mapping_disable(&ram_mid_mapping2); + } + + mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, + mem_read_remapped, mem_read_remappedw, mem_read_remappedl, + mem_write_remapped, mem_write_remappedw, mem_write_remappedl, + ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&ram_remapped_mapping); + + /* Mapping for SiS 471 relocation which relocates A0000-BFFFF, D0000-EFFFF, which is non-contiguous. */ + mem_mapping_add(&ram_remapped_mapping2, mem_size * 1024, 256 * 1024, + mem_read_remapped2, mem_read_remappedw2, mem_read_remappedl2, + mem_write_remapped2, mem_write_remappedw2, mem_write_remappedl2, + ram + 0xd0000, MEM_MAPPING_INTERNAL, NULL); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_a20_init(); + +#ifdef USE_NEW_DYNAREC + purgable_page_list_head = 0; + purgeable_page_count = 0; +#endif +} + +void +mem_init(void) +{ + /* Perform a one-time init. */ + ram = rom = NULL; + ram2 = NULL; + pages = NULL; + + /* Allocate the lookup tables. */ + page_lookup = (page_t **) malloc((1 << 20) * sizeof(page_t *)); + page_lookupp = (uint8_t *) malloc((1 << 20) * sizeof(uint8_t)); + readlookup2 = malloc((1 << 20) * sizeof(uintptr_t)); + readlookupp = malloc((1 << 20) * sizeof(uint8_t)); + writelookup2 = malloc((1 << 20) * sizeof(uintptr_t)); + writelookupp = malloc((1 << 20) * sizeof(uint8_t)); +} + +void +mem_remap_top(int kb) +{ + uint32_t c; + uint32_t start = (mem_size >= 1024) ? mem_size : 1024; + int offset, size = mem_size - 640; + int set = 1; + static int old_kb = 0; + int sis_mode = 0; + uint32_t start_addr = 0, addr = 0; + + mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); + if (mem_size <= 640) + return; + + /* SiS 471 special mode. */ + if (kb == -256) { + kb = 256; + sis_mode = 1; + } + + /* Do not remap if we're have more than (16 MB - RAM) memory. */ + if ((kb != 0) && (mem_size >= (16384 - kb))) + return; + + if (kb == 0) { + kb = old_kb; + set = 0; + } else + old_kb = kb; + + if (size > kb) + size = kb; + + remap_start_addr = start << 10; + remap_start_addr2 = (start << 10) + 0x00020000; + + for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { + offset = c - ((start * 1024) >> 12); + /* Use A0000-BFFFF, D0000-EFFFF instead of C0000-DFFFF, E0000-FFFFF. */ + addr = 0xa0000 + (offset << 12); + if (sis_mode) { + /* A0000-DFFFF -> A0000-BFFFF, D0000-EFFFF */ + if (addr >= 0x000c0000) + addr += 0x00010000; + } + if (start_addr == 0) + start_addr = addr; + pages[c].mem = set ? &ram[addr] : page_ff; + pages[c].write_b = set ? mem_write_ramb_page : NULL; + pages[c].write_w = set ? mem_write_ramw_page : NULL; + pages[c].write_l = set ? mem_write_raml_page : NULL; +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[(addr >> 12) * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[(addr >> 12) * 64]; +#endif + } + + mem_set_mem_state_both(start * 1024, size * 1024, set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + + for (c = 0xa0; c < 0xf0; c++) { + if ((c >= 0xc0) && (c <= 0xcf)) + continue; + + if (sis_mode || ((c << 12) >= (mem_size << 10))) + pages[c].mem = page_ff; + else { +#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) + if (mem_size > 1048576) { + if ((c << 12) < (1 << 30)) + pages[c].mem = &ram[c << 12]; + else + pages[c].mem = &ram2[(c << 12) - (1 << 30)]; + } else + pages[c].mem = &ram[c << 12]; +#else + pages[c].mem = &ram[c << 12]; +#endif + } + if (!sis_mode && (c < addr_space_size)) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; + } else { + pages[c].write_b = NULL; + pages[c].write_w = NULL; + pages[c].write_l = NULL; + } +#ifdef USE_NEW_DYNAREC + pages[c].evict_prev = EVICT_NOT_IN_LIST; + pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; + pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; +#endif + } + + if (set) { + if (sis_mode) { + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, 0x00020000); + mem_mapping_set_exec(&ram_remapped_mapping, ram + 0x000a0000); + mem_mapping_set_addr(&ram_remapped_mapping2, (start * 1024) + 0x00020000, 0x00020000); + mem_mapping_set_exec(&ram_remapped_mapping2, ram + 0x000d0000); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000c0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000c0000); + mem_mapping_set_addr(&ram_mid_mapping2, 0x000f0000, 0x00010000); + mem_mapping_set_exec(&ram_mid_mapping2, ram + 0x000f0000); + } else { + mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); + mem_mapping_set_exec(&ram_remapped_mapping, ram + start_addr); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } + } else { + mem_mapping_disable(&ram_remapped_mapping); + mem_mapping_disable(&ram_remapped_mapping2); + + mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); + mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); + mem_mapping_disable(&ram_mid_mapping2); + } + + flushmmucache(); +} + +void +mem_reset_page_blocks(void) +{ + uint32_t c; + + if (pages == NULL) + return; + + for (c = 0; c < pages_sz; c++) { + pages[c].write_b = mem_write_ramb_page; + pages[c].write_w = mem_write_ramw_page; + pages[c].write_l = mem_write_raml_page; +#ifdef USE_NEW_DYNAREC + pages[c].block = BLOCK_INVALID; + pages[c].block_2 = BLOCK_INVALID; + pages[c].head = BLOCK_INVALID; +#else + pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL; + pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL; + pages[c].head = NULL; +#endif + } +} + +void +mem_a20_recalc(void) +{ + int state; + + if (!is286) { + rammask = 0xfffff; + flushmmucache(); + mem_a20_key = mem_a20_alt = mem_a20_state = 0; + + return; + } + + state = mem_a20_key | mem_a20_alt; + if (state && !mem_a20_state) { + rammask = (cpu_16bitbus) ? 0xffffff : 0xffffffff; + if (is6117) + rammask |= 0x03000000; + flushmmucache(); + } else if (!state && mem_a20_state) { + rammask = (cpu_16bitbus) ? 0xefffff : 0xffefffff; + if (is6117) + rammask |= 0x03000000; + flushmmucache(); + } + + mem_a20_state = state; +} diff --git a/src/mouse.patch b/src/mouse.patch new file mode 100644 index 000000000..4d9d67d2a --- /dev/null +++ b/src/mouse.patch @@ -0,0 +1,69 @@ +diff --git a/src/86box.c b/src/86box.c +index a14f51c41..3c96d88a4 100644 +--- a/src/86box.c ++++ b/src/86box.c +@@ -1263,9 +1263,9 @@ pc_run(void) + startblit(); + cpu_exec(cpu_s->rspeed / 100); + #ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ +- if (gdbstub_step == GDBSTUB_EXEC) ++ // if (gdbstub_step == GDBSTUB_EXEC) + #endif +- mouse_process(); ++ // mouse_process(); + joystick_process(); + endblit(); + +diff --git a/src/device/mouse.c b/src/device/mouse.c +index 7eb6a08a9..329397d43 100644 +--- a/src/device/mouse.c ++++ b/src/device/mouse.c +@@ -27,6 +27,8 @@ + #define HAVE_STDARG_H + #include <86box/86box.h> + #include <86box/device.h> ++#include <86box/timer.h> ++#include <86box/gdbstub.h> + #include <86box/mouse.h> + + typedef struct { +@@ -45,6 +47,8 @@ int mouse_x, + double mouse_x_abs, + mouse_y_abs; + ++pc_timer_t mouse_timer; /* mouse event timer */ ++ + static const device_t mouse_none_device = { + .name = "None", + .internal_name = "none", +@@ -141,6 +145,20 @@ mouse_close(void) + mouse_priv = NULL; + mouse_nbut = 0; + mouse_dev_poll = NULL; ++ ++ timer_stop(&mouse_timer); ++} ++ ++static void ++mouse_timer_poll(void *priv) ++{ ++ // timer_on_auto(&mouse_timer, 1388.0 + (8.0 / 9.0)); ++ timer_on_auto(&mouse_timer, 277.0 + (7.0 / 9.0)); ++ ++#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ ++ if (gdbstub_step == GDBSTUB_EXEC) ++#endif ++ mouse_process(); + } + + void +@@ -165,6 +183,9 @@ mouse_reset(void) + + if (mouse_curr != NULL) + mouse_priv = device_add(mouse_curr); ++ ++ timer_add(&mouse_timer, mouse_timer_poll, NULL, 0); ++ timer_on_auto(&mouse_timer, 10000.0); + } + + /* Callback from the hardware driver. */ diff --git a/src/pic - Cópia.c b/src/pic - Cópia.c new file mode 100644 index 000000000..70a8a7805 --- /dev/null +++ b/src/pic - Cópia.c @@ -0,0 +1,838 @@ +/* + * 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. + * + * Implementation of the Intel PIC chip emulation, partially + * ported from reenigne's XTCE. + * + * + * + * Authors: Andrew Jenner, + * Miran Grca, + * + * Copyright 2015-2020 Andrew Jenner. + * Copyright 2016-2020 Miran Grca. + */ +#include +#include +#include +#include +#include +#include + +#define HAVE_STDARG_H +#include <86box/86box.h> +#include "cpu.h" +#include <86box/machine.h> +#include <86box/io.h> +#include <86box/pci.h> +#include <86box/pic.h> +#include <86box/timer.h> +#include <86box/pit.h> +#include <86box/device.h> +#include <86box/apm.h> +#include <86box/nvr.h> +#include <86box/acpi.h> + +enum { + STATE_NONE = 0, + STATE_ICW2, + STATE_ICW3, + STATE_ICW4 +}; + +pic_t pic, pic2; + +static pc_timer_t pic_timer; + +static int shadow = 0, elcr_enabled = 0, + tmr_inited = 0, latched = 0, + pic_pci = 0, kbd_latch = 0, + mouse_latch = 0; + +static uint16_t smi_irq_mask = 0x0000, + smi_irq_status = 0x0000; + +static uint16_t latched_irqs = 0x0000; + +static void (*update_pending)(void); + +#ifdef ENABLE_PIC_LOG +int pic_do_log = ENABLE_PIC_LOG; + +static void +pic_log(const char *fmt, ...) +{ + va_list ap; + + if (pic_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define pic_log(fmt, ...) +#endif + +void +pic_reset_smi_irq_mask(void) +{ + smi_irq_mask = 0x0000; +} + +void +pic_set_smi_irq_mask(int irq, int set) +{ + if ((irq >= 0) && (irq <= 15)) { + if (set) + smi_irq_mask |= (1 << irq); + else + smi_irq_mask &= ~(1 << irq); + } +} + +uint16_t +pic_get_smi_irq_status(void) +{ + return smi_irq_status; +} + +void +pic_clear_smi_irq_status(int irq) +{ + if ((irq >= 0) && (irq <= 15)) + smi_irq_status &= ~(1 << irq); +} + +void +pic_elcr_write(uint16_t port, uint8_t val, void *priv) +{ + pic_t *dev = (pic_t *) priv; + + pic_log("ELCR%i: WRITE %02X\n", port & 1, val); + + if (port & 1) + val &= 0xde; + else + val &= 0xf8; + + dev->elcr = val; + + pic_log("ELCR %i: %c %c %c %c %c %c %c %c\n", + port & 1, + (val & 1) ? 'L' : 'E', + (val & 2) ? 'L' : 'E', + (val & 4) ? 'L' : 'E', + (val & 8) ? 'L' : 'E', + (val & 0x10) ? 'L' : 'E', + (val & 0x20) ? 'L' : 'E', + (val & 0x40) ? 'L' : 'E', + (val & 0x80) ? 'L' : 'E'); +} + +uint8_t +pic_elcr_read(uint16_t port, void *priv) +{ + pic_t *dev = (pic_t *) priv; + + pic_log("ELCR%i: READ %02X\n", port & 1, dev->elcr); + + return dev->elcr; +} + +int +pic_elcr_get_enabled(void) +{ + return elcr_enabled; +} + +void +pic_elcr_set_enabled(int enabled) +{ + elcr_enabled = enabled; +} + +void +pic_elcr_io_handler(int set) +{ + io_handler(set, 0x04d0, 0x0001, + pic_elcr_read, NULL, NULL, + pic_elcr_write, NULL, NULL, &pic); + io_handler(set, 0x04d1, 0x0001, + pic_elcr_read, NULL, NULL, + pic_elcr_write, NULL, NULL, &pic2); +} + +static uint8_t +pic_cascade_mode(pic_t *dev) +{ + return !(dev->icw1 & 2); +} + +static __inline uint8_t +pic_slave_on(pic_t *dev, int channel) +{ + pic_log("pic_slave_on(%i): %i, %02X, %02X\n", channel, pic_cascade_mode(dev), dev->icw4 & 0x0c, dev->icw3 & (1 << channel)); + + return pic_cascade_mode(dev) && (dev->is_master || ((dev->icw4 & 0x0c) == 0x0c)) && (dev->icw3 & (1 << channel)); +} + +static __inline int +find_best_interrupt(pic_t *dev) +{ + uint8_t b; + uint8_t intr; + int i, j; + int ret = -1; + + for (i = 0; i < 8; i++) { + j = (i + dev->priority) & 7; + b = 1 << j; + + if (dev->isr & b) + break; + else if ((dev->state == 0) && ((dev->irr & ~dev->imr) & b)) { + ret = j; + break; + } + } + + intr = dev->interrupt = (ret == -1) ? 0x17 : ret; + + if (dev->at && (ret != -1)) { + if (dev == &pic2) + intr += 8; + + if (cpu_fast_off_flags & (1u << intr)) + cpu_fast_off_advance(); + } + + return ret; +} + +static __inline void +pic_update_pending_xt(void) +{ + if (find_best_interrupt(&pic) != -1) { + latched++; + if (latched == 1) + timer_on_auto(&pic_timer, 0.35); + } else if (latched == 0) + pic.int_pending = 0; +} + +static __inline void +pic_update_pending_at(void) +{ + pic2.int_pending = (find_best_interrupt(&pic2) != -1); + + if (pic2.int_pending) + pic.irr |= (1 << pic2.icw3); + else + pic.irr &= ~(1 << pic2.icw3); + + pic.int_pending = (find_best_interrupt(&pic) != -1); +} + +static void +pic_callback(void *priv) +{ + pic_t *dev = (pic_t *) priv; + + dev->int_pending = 1; + + latched--; + if (latched > 0) + timer_on_auto(&pic_timer, 0.35); +} + +void +pic_reset(void) +{ + int is_at = IS_AT(machine); + is_at = is_at || !strcmp(machine_get_internal_name(), "xi8088"); + + memset(&pic, 0, sizeof(pic_t)); + memset(&pic2, 0, sizeof(pic_t)); + + pic.is_master = 1; + pic.interrupt = pic2.interrupt = 0x17; + + if (is_at) + pic.slaves[2] = &pic2; + + if (tmr_inited) + timer_on_auto(&pic_timer, 0.0); + memset(&pic_timer, 0x00, sizeof(pc_timer_t)); + timer_add(&pic_timer, pic_callback, &pic, 0); + tmr_inited = 1; + + update_pending = is_at ? pic_update_pending_at : pic_update_pending_xt; + pic.at = pic2.at = is_at; + + smi_irq_mask = smi_irq_status = 0x0000; + + shadow = 0; + pic_pci = 0; +} + +void +pic_set_shadow(int sh) +{ + shadow = sh; +} + +int +pic_get_pci_flag(void) +{ + return pic_pci; +} + +void +pic_set_pci_flag(int pci) +{ + pic_pci = pci; +} + +static uint8_t +pic_level_triggered(pic_t *dev, int irq) +{ + if (elcr_enabled) + return !!(dev->elcr & (1 << irq)); + else + return !!(dev->icw1 & 8); +} + +int +picint_is_level(int irq) +{ + return pic_level_triggered(((irq > 7) ? &pic2 : &pic), irq & 7); +} + +static void +pic_acknowledge(pic_t *dev) +{ + int pic_int = dev->interrupt & 7; + int pic_int_num = 1 << pic_int; + + dev->isr |= pic_int_num; + if (!pic_level_triggered(dev, pic_int) || !(dev->lines & pic_int_num)) + dev->irr &= ~pic_int_num; +} + +/* Find IRQ for non-specific EOI (either by command or automatic) by finding the highest IRQ + priority with ISR bit set, that is also not masked if the PIC is in special mask mode. */ +static uint8_t +pic_non_specific_find(pic_t *dev) +{ + int i, j; + uint8_t b, irq = 0xff; + + for (i = 0; i < 8; i++) { + j = (i + dev->priority) & 7; + b = (1 << j); + + if ((dev->isr & b) && (!dev->special_mask_mode || !(dev->imr & b))) { + irq = j; + break; + } + } + + return irq; +} + +/* Do the EOI and rotation, if either is requested, on the given IRQ. */ +static void +pic_action(pic_t *dev, uint8_t irq, uint8_t eoi, uint8_t rotate) +{ + uint8_t b = (1 << irq); + + if (irq != 0xff) { + if (eoi) + dev->isr &= ~b; + if (rotate) + dev->priority = (irq + 1) & 7; + + update_pending(); + } +} + +/* Automatic non-specific EOI. */ +static __inline void +pic_auto_non_specific_eoi(pic_t *dev) +{ + uint8_t irq; + + if (dev->icw4 & 2) { + irq = pic_non_specific_find(dev); + + pic_action(dev, irq, 1, dev->auto_eoi_rotate); + } +} + +/* Do the PIC command specified by bits 7-5 of the value written to the OCW2 register. */ +static void +pic_command(pic_t *dev) +{ + uint8_t irq = 0xff; + + if (dev->ocw2 & 0x60) { /* SL and/or EOI set */ + if (dev->ocw2 & 0x40) /* SL set, specific priority level */ + irq = (dev->ocw2 & 0x07); + else /* SL clear, non-specific priority level (find highest with ISR set) */ + irq = pic_non_specific_find(dev); + + pic_action(dev, irq, dev->ocw2 & 0x20, dev->ocw2 & 0x80); + } else /* SL and EOI clear */ + dev->auto_eoi_rotate = !!(dev->ocw2 & 0x80); +} + +uint8_t +pic_latch_read(uint16_t addr, void *priv) +{ + uint8_t ret = 0xff; + + pic_log("pic_latch_read(%i, %i): %02X%02X\n", kbd_latch, mouse_latch, pic2.lines & 0x10, pic.lines & 0x02); + + if (kbd_latch && (latched_irqs & 0x0002)) + picintc(0x0002); + + if (mouse_latch && (latched_irqs & 0x1000)) + picintc(0x1000); + + /* Return FF - we just lower IRQ 1 and IRQ 12. */ + return ret; +} + +uint8_t +pic_read(uint16_t addr, void *priv) +{ + pic_t *dev = (pic_t *) priv; + + if (shadow) { + /* VIA PIC shadow read */ + if (addr & 0x0001) + dev->data_bus = ((dev->icw2 & 0xf8) >> 3) << 0; + else { + dev->data_bus = ((dev->ocw3 & 0x20) >> 5) << 4; + dev->data_bus |= ((dev->ocw2 & 0x80) >> 7) << 3; + dev->data_bus |= ((dev->icw4 & 0x10) >> 4) << 2; + dev->data_bus |= ((dev->icw4 & 0x02) >> 1) << 1; + dev->data_bus |= ((dev->icw4 & 0x08) >> 3) << 0; + } + } else { + /* Standard 8259 PIC read */ +#ifndef UNDEFINED_READ + /* Put the IRR on to the data bus by default until the real PIC is probed. */ + dev->data_bus = dev->irr; +#endif + if (dev->ocw3 & 0x04) { + dev->interrupt &= ~0x20; /* Freeze the interrupt until the poll is over. */ + if (dev->int_pending) { + dev->data_bus = 0x80 | (dev->interrupt & 7); + pic_acknowledge(dev); + dev->int_pending = 0; + update_pending(); + } else + dev->data_bus = 0x00; + dev->ocw3 &= ~0x04; + } else if (addr & 0x0001) + dev->data_bus = dev->imr; + else if (dev->ocw3 & 0x02) { + if (dev->ocw3 & 0x01) + dev->data_bus = dev->isr; +#ifdef UNDEFINED_READ + else + dev->data_bus = 0x00; +#endif + } + /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, + simply read whatever is currently on the data bus. */ + } + + pic_log("pic_read(%04X, %08X) = %02X\n", addr, priv, dev->data_bus); + + return dev->data_bus; +} + +static void +pic_write(uint16_t addr, uint8_t val, void *priv) +{ + pic_t *dev = (pic_t *) priv; + + pic_log("pic_write(%04X, %02X, %08X)\n", addr, val, priv); + + dev->data_bus = val; + + if (addr & 0x0001) { + switch (dev->state) { + case STATE_ICW2: + dev->icw2 = val; + if (pic_cascade_mode(dev)) + dev->state = STATE_ICW3; + else + dev->state = (dev->icw1 & 1) ? STATE_ICW4 : STATE_NONE; + break; + case STATE_ICW3: + dev->icw3 = val; + dev->state = (dev->icw1 & 1) ? STATE_ICW4 : STATE_NONE; + break; + case STATE_ICW4: + dev->icw4 = val; + dev->state = STATE_NONE; + break; + case STATE_NONE: + dev->imr = val; + update_pending(); + break; + } + } else { + if (val & 0x10) { + /* Treat any write with any of the bits 7 to 5 set as invalid if PCI. */ + if (pic_pci && (val & 0xe0)) + return; + + dev->icw1 = val; + dev->icw2 = dev->icw3 = 0x00; + if (!(dev->icw1 & 1)) + dev->icw4 = 0x00; + dev->ocw2 = dev->ocw3 = 0x00; + dev->irr = dev->lines; + dev->imr = dev->isr = 0x00; + dev->ack_bytes = dev->priority = 0x00; + dev->auto_eoi_rotate = dev->special_mask_mode = 0x00; + dev->interrupt = 0x17; + dev->int_pending = 0x00; + dev->state = STATE_ICW2; + update_pending(); + } else if (val & 0x08) { + dev->ocw3 = val; + if (dev->ocw3 & 0x04) + dev->interrupt |= 0x20; /* Freeze the interrupt until the poll is over. */ + if (dev->ocw3 & 0x40) + dev->special_mask_mode = !!(dev->ocw3 & 0x20); + } else { + dev->ocw2 = val; + pic_command(dev); + } + } +} + +void +pic_set_pci(void) +{ + int i; + + for (i = 0x0024; i < 0x0040; i += 4) { + io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); + io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); + } + + for (i = 0x1120; i < 0x1140; i += 4) { + io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); + io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); + } +} + +void +pic_kbd_latch(int enable) +{ + pic_log("PIC keyboard latch now %sabled\n", enable ? "en" : "dis"); + + if (!!(enable | mouse_latch) != !!(kbd_latch | mouse_latch)) + io_handler(!!(enable | mouse_latch), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); + + kbd_latch = !!enable; + + if (!enable) + picintc(0x0002); +} + +void +pic_mouse_latch(int enable) +{ + pic_log("PIC mouse latch now %sabled\n", enable ? "en" : "dis"); + + if (!!(kbd_latch | enable) != !!(kbd_latch | mouse_latch)) + io_handler(!!(kbd_latch | enable), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); + + mouse_latch = !!enable; + + if (!enable) + picintc(0x1000); +} + +static void +pic_reset_hard(void) +{ + pic_reset(); + + /* Explicitly reset the latches. */ + kbd_latch = mouse_latch = 0; + + /* The situation is as follows: There is a giant mess when it comes to these latches on real hardware, + to the point that there's even boards with board-level latched that get used in place of the latches + on the chipset, therefore, I'm just doing this here for the sake of simplicity. */ + if (machine_has_bus(machine, MACHINE_BUS_PS2)) { + pic_kbd_latch(0x01); + pic_mouse_latch(0x01); + } else { + pic_kbd_latch(0x00); + pic_mouse_latch(0x00); + } +} + +void +pic_init(void) +{ + pic_reset_hard(); + + shadow = 0; + io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); +} + +void +pic_init_pcjr(void) +{ + pic_reset_hard(); + + shadow = 0; + io_sethandler(0x0020, 0x0008, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); +} + +void +pic2_init(void) +{ + io_sethandler(0x00a0, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); + pic.slaves[2] = &pic2; +} + +void +picint_common(uint16_t num, int level, int set) +{ + int i, raise; + uint8_t b, slaves = 0; + + /* Make sure to ignore all slave IRQ's, and in case of AT+, + translate IRQ 2 to IRQ 9. */ + for (i = 0; i < 8; i++) { + b = (1 << i); + raise = num & b; + + if (pic.icw3 & b) { + slaves++; + + if (raise) { + num &= ~b; + if (pic.at && (i == 2)) + num |= (1 << 9); + } + } + } + + if (!slaves) + num &= 0x00ff; + + if (!num) { + pic_log("Attempting to %s null IRQ\n", set ? "raise" : "lower"); + return; + } + + if (num & 0x0100) + acpi_rtc_status = !!set; + + if (set) { + if (smi_irq_mask & num) { + smi_raise(); + smi_irq_status |= num; + } + + if (num & 0xff00) { + if (level) + pic2.lines |= (num >> 8); + + /* Latch IRQ 12 if the mouse latch is enabled. */ + if ((num & 0x1000) && mouse_latch) + latched_irqs |= 0x1000; + + pic2.irr |= (num >> 8); + } + + if (num & 0x00ff) { + if (level) + pic.lines |= (num & 0x00ff); + + /* Latch IRQ 1 if the keyboard latch is enabled. */ + if (kbd_latch && (num & 0x0002)) + latched_irqs |= 0x0002; + + pic.irr |= (num & 0x00ff); + } + } else { + smi_irq_status &= ~num; + + if (num & 0xff00) { + pic2.lines &= ~(num >> 8); + + /* Unlatch IRQ 12 if the mouse latch is enabled. */ + if ((num & 0x1000) && mouse_latch) + latched_irqs &= 0xefff; + + pic2.irr &= ~(num >> 8); + } + + if (num & 0x00ff) { + pic.lines &= ~(num & 0x00ff); + + /* Unlatch IRQ 1 if the keyboard latch is enabled. */ + if (kbd_latch && (num & 0x0002)) + latched_irqs &= 0xfffd; + + pic.irr &= ~(num & 0x00ff); + } + } + + if (!(pic.interrupt & 0x20) && !(pic2.interrupt & 0x20)) + update_pending(); +} + +void +picint(uint16_t num) +{ + picint_common(num, 0, 1); +} + +void +picintlevel(uint16_t num) +{ + picint_common(num, 1, 1); +} + +void +picintc(uint16_t num) +{ + picint_common(num, 0, 0); +} + +static uint8_t +pic_i86_mode(pic_t *dev) +{ + return !!(dev->icw4 & 1); +} + +static uint8_t +pic_irq_ack_read(pic_t *dev, int phase) +{ + uint8_t intr = dev->interrupt & 0x47; + uint8_t slave = intr & 0x40; + intr &= 0x07; + pic_log(" pic_irq_ack_read(%08X, %i)\n", dev, phase); + + if (dev != NULL) { + if (phase == 0) { + dev->interrupt |= 0x20; /* Freeze it so it still takes interrupts but they do not + override the one currently being processed. */ + pic_acknowledge(dev); + if (slave) + dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); + else + dev->data_bus = pic_i86_mode(dev) ? 0xff : 0xcd; + } else if (pic_i86_mode(dev)) { + dev->int_pending = 0; + if (slave) + dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); + else + dev->data_bus = intr + (dev->icw2 & 0xf8); + pic_auto_non_specific_eoi(dev); + } else if (phase == 1) { + if (slave) + dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); + else if (dev->icw1 & 0x04) + dev->data_bus = (intr << 2) + (dev->icw1 & 0xe0); + else + dev->data_bus = (intr << 3) + (dev->icw1 & 0xc0); + } else if (phase == 2) { + dev->int_pending = 0; + if (slave) + dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); + else + dev->data_bus = dev->icw2; + pic_auto_non_specific_eoi(dev); + } + } + + return dev->data_bus; +} + +uint8_t +pic_irq_ack(void) +{ + int ret; + + /* Needed for Xi8088. */ + if ((pic.ack_bytes == 0) && pic.int_pending && pic_slave_on(&pic, pic.interrupt)) { + if (!pic.slaves[pic.interrupt]->int_pending) { + /* If we are on AT, IRQ 2 is pending, and we cannot find a pending IRQ on PIC 2, fatal out. */ + fatal("IRQ %i pending on AT without a pending IRQ on PIC %i (normal)\n", pic.interrupt, pic.interrupt); + exit(-1); + return -1; + } + + pic.interrupt |= 0x40; /* Mark slave pending. */ + } + + ret = pic_irq_ack_read(&pic, pic.ack_bytes); + pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3); + + if (pic.ack_bytes == 0) { + /* Needed for Xi8088. */ + if (pic.interrupt & 0x40) + pic2.interrupt = 0x17; + pic.interrupt = 0x17; + update_pending(); + } + + return ret; +} + +int +picinterrupt(void) +{ + int i, ret = -1; + + if (pic.int_pending) { + if (pic_slave_on(&pic, pic.interrupt)) { + if (!pic.slaves[pic.interrupt]->int_pending) { + /* If we are on AT, IRQ 2 is pending, and we cannot find a pending IRQ on PIC 2, fatal out. */ + fatal("IRQ %i pending on AT without a pending IRQ on PIC %i (normal)\n", pic.interrupt, pic.interrupt); + exit(-1); + return -1; + } + + pic.interrupt |= 0x40; /* Mark slave pending. */ + } + + if ((pic.interrupt == 0) && (pit_devs[1].data != NULL)) + pit_devs[1].set_gate(pit_devs[1].data, 0, 0); + + /* Two ACK's - do them in a loop to avoid potential compiler misoptimizations. */ + for (i = 0; i < 2; i++) { + ret = pic_irq_ack_read(&pic, pic.ack_bytes); + pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3); + + if (pic.ack_bytes == 0) { + if (pic.interrupt & 0x40) + pic2.interrupt = 0x17; + pic.interrupt = 0x17; + update_pending(); + } + } + } + + return ret; +} diff --git a/src/usb.c b/src/usb.c index f0c7113b7..e45f82ae8 100644 --- a/src/usb.c +++ b/src/usb.c @@ -51,30 +51,58 @@ usb_log(const char *fmt, ...) /* OHCI registers */ enum { - OHCI_HcRevision = 0x00, - OHCI_HcControl = 0x04, - OHCI_HcCommandStatus = 0x08, - OHCI_HcInterruptStatus = 0x0C, - OHCI_HcInterruptEnable = 0x10, - OHCI_HcInterruptDisable = 0x14, - OHCI_HcHCCA = 0x18, - OHCI_HcPeriodCurrentED = 0x1C, - OHCI_HcControlHeadED = 0x20, - OHCI_HcControlCurrentED = 0x24, - OHCI_HcBulkHeadED = 0x28, - OHCI_HcBulkCurrentED = 0x2C, - OHCI_HcDoneHead = 0x30, - OHCI_HcFmInterval = 0x34, - OHCI_HcFmRemaining = 0x38, - OHCI_HcFmNumber = 0x3C, - OHCI_HcPeriodicStart = 0x40, - OHCI_HcLSThreshold = 0x44, - OHCI_HcRhDescriptorA = 0x48, - OHCI_HcRhDescriptorB = 0x4C, - OHCI_HcRhStatus = 0x50, - OHCI_HcRhPortStatus1 = 0x54, - OHCI_HcRhPortStatus2 = 0x58, - OHCI_HcRhPortStatus3 = 0x5C + OHCI_HcRevision = 0x00 /* 0x00 */, + OHCI_HcControl = 0x01 /* 0x04 */, + OHCI_HcCommandStatus = 0x02 /* 0x08 */, + OHCI_HcInterruptStatus = 0x03 /* 0x0c */, + OHCI_HcInterruptEnable = 0x04 /* 0x10 */, + OHCI_HcInterruptDisable = 0x05 /* 0x14 */, + OHCI_HcHCCA = 0x06 /* 0x18 */, + OHCI_HcPeriodCurrentED = 0x07 /* 0x1c */, + OHCI_HcControlHeadED = 0x08 /* 0x20 */, + OHCI_HcControlCurrentED = 0x09 /* 0x24 */, + OHCI_HcBulkHeadED = 0x0a /* 0x28 */, + OHCI_HcBulkCurrentED = 0x0b /* 0x2c */, + OHCI_HcDoneHead = 0x0c /* 0x30 */, + OHCI_HcFmInterval = 0x0d /* 0x34 */, + OHCI_HcFmRemaining = 0x0e /* 0x38 */, + OHCI_HcFmNumber = 0x0f /* 0x3c */, + OHCI_HcPeriodicStart = 0x10 /* 0x40 */, + OHCI_HcLSThreshold = 0x11 /* 0x44 */, + OHCI_HcRhDescriptorA = 0x12 /* 0x48 */, + OHCI_HcRhDescriptorB = 0x13 /* 0x4c */, + OHCI_HcRhStatus = 0x14 /* 0x50 */, + OHCI_HcRhPortStatus1 = 0x15 /* 0x54 */, + OHCI_HcRhPortStatus2 = 0x16 /* 0x58 */, + OHCI_HcRhPortStatus3 = 0x17 /* 0x5c */ +}; + +enum +{ + OHCI_aHcRevision = 0x00, + OHCI_aHcControl = 0x04, + OHCI_aHcCommandStatus = 0x08, + OHCI_aHcInterruptStatus = 0x0c, + OHCI_aHcInterruptEnable = 0x10, + OHCI_aHcInterruptDisable = 0x14, + OHCI_aHcHCCA = 0x18, + OHCI_aHcPeriodCurrentED = 0x1c, + OHCI_aHcControlHeadED = 0x20, + OHCI_aHcControlCurrentED = 0x24, + OHCI_aHcBulkHeadED = 0x28, + OHCI_aHcBulkCurrentED = 0x2c, + OHCI_aHcDoneHead = 0x30, + OHCI_aHcFmInterval = 0x34, + OHCI_aHcFmRemaining = 0x38, + OHCI_aHcFmNumber = 0x3c, + OHCI_aHcPeriodicStart = 0x40, + OHCI_aHcLSThreshold = 0x44, + OHCI_aHcRhDescriptorA = 0x48, + OHCI_aHcRhDescriptorB = 0x4c, + OHCI_aHcRhStatus = 0x50, + OHCI_aHcRhPortStatus1 = 0x54, + OHCI_aHcRhPortStatus2 = 0x58, + OHCI_aHcRhPortStatus3 = 0x5c }; /* OHCI HcInterruptEnable/Disable bits */ @@ -90,18 +118,17 @@ enum }; static void -usb_interrupt_ohci(usb_t* usb) +usb_interrupt_ohci(usb_t *dev, uint32_t level) { - if (usb->ohci_mmio[OHCI_HcControl + 1] & 1) { - if (usb->usb_params && usb->usb_params->smi_handle && !usb->usb_params->smi_handle(usb, usb->usb_params->parent_priv)) + if (dev->ohci_mmio[OHCI_HcControl].b[1] & 1) { + if (dev->usb_params && dev->usb_params->smi_handle && !dev->usb_params->smi_handle(dev, dev->usb_params->parent_priv)) return; - smi_raise(); - } - else if (usb->usb_params != NULL) { - if (usb->usb_params->parent_priv != NULL && usb->usb_params->raise_interrupt != NULL) { - usb->usb_params->raise_interrupt(usb, usb->usb_params->parent_priv); - } + if (level) + smi_raise(); + } else if (dev->usb_params != NULL) { + if ((dev->usb_params->parent_priv != NULL) && (dev->usb_params->update_interrupt != NULL)) + dev->usb_params->update_interrupt(dev, dev->usb_params->parent_priv); } } @@ -194,26 +221,28 @@ ohci_mmio_read(uint32_t addr, void *p) { usb_t *dev = (usb_t *) p; uint8_t ret = 0x00; +#ifdef ENABLE_USB_LOG + uint32_t old_addr = addr; +#endif addr &= 0x00000fff; - ret = dev->ohci_mmio[addr]; + ret = dev->ohci_mmio[addr >> 2].b[addr & 3]; switch (addr) { case 0x101: ret = (ret & 0xfe) | (!!mem_a20_key); break; - case OHCI_HcRhPortStatus1 + 1: - case OHCI_HcRhPortStatus2 + 1: - case OHCI_HcRhPortStatus3 + 1: + case OHCI_aHcRhPortStatus1 + 1: + case OHCI_aHcRhPortStatus2 + 1: + case OHCI_aHcRhPortStatus3 + 1: ret |= 0x1; break; - case OHCI_HcInterruptDisable: - case OHCI_HcInterruptDisable + 1: - case OHCI_HcInterruptDisable + 2: - case OHCI_HcInterruptDisable + 3: - ret = dev->ohci_mmio[OHCI_HcInterruptEnable + (addr - OHCI_HcInterruptDisable)]; - break; + case OHCI_aHcInterruptDisable: + case OHCI_aHcInterruptDisable + 1: + case OHCI_aHcInterruptDisable + 2: + case OHCI_aHcInterruptDisable + 3: + ret = dev->ohci_mmio[OHCI_HcInterruptEnable].b[addr & 3]; default: break; } @@ -221,30 +250,58 @@ ohci_mmio_read(uint32_t addr, void *p) if (addr == 0x101) ret = (ret & 0xfe) | (!!mem_a20_key); +#ifdef ENABLE_USB_LOG + usb_log("[R] %08X = %04X\n", old_addr, ret); +#endif + return ret; } -void -ohci_set_interrupt(usb_t* usb, uint8_t bit) +static uint16_t +ohci_mmio_readw(uint32_t addr, void *p) { - if (!(usb->ohci_mmio[OHCI_HcInterruptEnable + 3] & 0x80)) + return ohci_mmio_read(addr, p) | (ohci_mmio_read(addr + 1, p) << 8); +} + +static uint32_t +ohci_mmio_readl(uint32_t addr, void *p) +{ + return ohci_mmio_readw(addr, p) | (ohci_mmio_readw(addr + 2, p) << 16); +} + +static void +ohci_update_irq(usb_t *dev) +{ + uint32_t level = !!(dev->ohci_mmio[OHCI_HcInterruptStatus].l & dev->ohci_mmio[OHCI_HcInterruptEnable].l); + + if (level != dev->irq_level) { + dev->irq_level = level; + usb_interrupt_ohci(dev, level); + } +} + +void +ohci_set_interrupt(usb_t *dev, uint8_t bit) +{ + if (!(dev->ohci_mmio[OHCI_HcInterruptEnable].b[3] & 0x80)) return; - if (!(usb->ohci_mmio[OHCI_HcInterruptEnable] & bit)) + if (!(dev->ohci_mmio[OHCI_HcInterruptEnable].b[0] & bit)) return; - if (usb->ohci_mmio[OHCI_HcInterruptDisable] & bit) + if (dev->ohci_mmio[OHCI_HcInterruptDisable].b[0] & bit) return; - usb->ohci_mmio[OHCI_HcInterruptStatus] |= bit; - usb_interrupt_ohci(usb); + dev->ohci_mmio[OHCI_HcInterruptStatus].b[0] |= bit; + + ohci_update_irq(dev); } void ohci_end_of_frame(usb_t* dev) { /* TODO: Put endpoint and transfer descriptor processing here. */ - dev->ohci_mmio_w[OHCI_HcFmNumber / 2]++; + dev->ohci_mmio[OHCI_HcFmNumber].w[0]++; } void @@ -258,17 +315,17 @@ ohci_update_frame_counter(void* priv) { usb_t *dev = (usb_t *) priv; - dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] &= 0x3fff; - if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] == 0) { + dev->ohci_mmio[OHCI_HcFmRemaining].w[0] &= 0x3fff; + if (dev->ohci_mmio[OHCI_HcFmRemaining].w[0] == 0) { ohci_end_of_frame(dev); - dev->ohci_mmio_w[OHCI_HcFmRemaining / 2] = dev->ohci_mmio_w[OHCI_HcFmInterval / 2] & 0x3fff; - dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] &= ~(1 << 31); - dev->ohci_mmio_l[OHCI_HcFmRemaining / 4] |= dev->ohci_mmio_l[OHCI_HcFmInterval / 4] & (1 << 31); + dev->ohci_mmio[OHCI_HcFmRemaining].w[0] = dev->ohci_mmio[OHCI_HcFmInterval].w[0] & 0x3fff; + dev->ohci_mmio[OHCI_HcFmRemaining].l &= ~(1 << 31); + dev->ohci_mmio[OHCI_HcFmRemaining].l |= dev->ohci_mmio[OHCI_HcFmInterval].l & (1 << 31); ohci_start_of_frame(dev); timer_on_auto(&dev->ohci_frame_timer, 1. / (12. * 1000. * 1000.)); return; } - if (dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]) dev->ohci_mmio_w[OHCI_HcFmRemaining / 2]--; + if (dev->ohci_mmio[OHCI_HcFmRemaining].w[0]) dev->ohci_mmio[OHCI_HcFmRemaining].w[0]--; timer_on_auto(&dev->ohci_frame_timer, 1. / (12. * 1000. * 1000.)); } @@ -288,8 +345,8 @@ ohci_port_reset_callback(void* priv) { usb_t *dev = (usb_t *) priv; - dev->ohci_mmio[OHCI_HcRhPortStatus1] &= ~0x10; - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 2] |= 0x10; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[0] &= ~0x10; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[2] |= 0x10; } void @@ -297,244 +354,260 @@ ohci_port_reset_callback_2(void* priv) { usb_t *dev = (usb_t *) priv; - dev->ohci_mmio[OHCI_HcRhPortStatus2] &= ~0x10; - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] |= 0x10; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[0] &= ~0x10; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[2] |= 0x10; } + static void ohci_mmio_write(uint32_t addr, uint8_t val, void *p) { usb_t *dev = (usb_t *) p; uint8_t old; +#ifdef ENABLE_USB_LOG + usb_log("[W] %08X = %04X\n", addr, val); +#endif + addr &= 0x00000fff; switch (addr) { - case OHCI_HcControl: + case OHCI_aHcControl: if ((val & 0xc0) == 0x00) { /* UsbReset */ - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 2] = dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] = 0x16; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[2] = dev->ohci_mmio[OHCI_HcRhPortStatus2].b[2] = 0x16; } break; - case OHCI_HcCommandStatus: + case OHCI_aHcCommandStatus: /* bit OwnershipChangeRequest triggers an ownership change (SMM <-> OS) */ if (val & 0x08) { - dev->ohci_mmio[OHCI_HcInterruptStatus + 3] = 0x40; - if ((dev->ohci_mmio[OHCI_HcInterruptEnable + 3] & 0xc0) == 0xc0) + dev->ohci_mmio[OHCI_HcInterruptStatus].b[3] = 0x40; + if ((dev->ohci_mmio[OHCI_HcInterruptEnable].b[3] & 0xc0) == 0xc0) smi_raise(); } /* bit HostControllerReset must be cleared for the controller to be seen as initialized */ if (val & 0x01) { memset(dev->ohci_mmio, 0x00, 4096); - dev->ohci_mmio[OHCI_HcRevision] = 0x10; - dev->ohci_mmio[OHCI_HcRevision + 1] = 0x01; - dev->ohci_mmio[OHCI_HcRhDescriptorA] = 0x02; + dev->ohci_mmio[OHCI_HcRevision].b[0] = 0x10; + dev->ohci_mmio[OHCI_HcRevision].b[1] = 0x01; + dev->ohci_mmio[OHCI_HcRhDescriptorA].b[0] = 0x02; val &= ~0x01; } break; - case OHCI_HcHCCA: + case OHCI_aHcHCCA: return; - case OHCI_HcInterruptEnable: - dev->ohci_mmio[addr] = (val & 0x7f); - dev->ohci_mmio[OHCI_HcInterruptDisable] &= ~(val & 0x7f); + case OHCI_aHcInterruptEnable: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0x7f); + dev->ohci_mmio[OHCI_HcInterruptDisable].b[0] &= ~(val & 0x7f); + ohci_update_irq(dev); return; - case OHCI_HcInterruptEnable + 1: - case OHCI_HcInterruptEnable + 2: + case OHCI_aHcInterruptEnable + 1: + case OHCI_aHcInterruptEnable + 2: return; - case OHCI_HcInterruptEnable + 3: - dev->ohci_mmio[addr] = (val & 0x40); - dev->ohci_mmio[addr] |= (val & 0x80); - if (val & 0x80) - dev->ohci_mmio[OHCI_HcInterruptDisable + 3] &= ~0x80; - if (val & 0x40) - dev->ohci_mmio[OHCI_HcInterruptDisable + 3] &= ~0x40; + case OHCI_aHcInterruptEnable + 3: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0xc0); + dev->ohci_mmio[OHCI_HcInterruptDisable].b[3] &= ~(val & 0xc0); + ohci_update_irq(dev); return; - case OHCI_HcInterruptDisable: - dev->ohci_mmio[addr] = (val & 0x7f); - dev->ohci_mmio[OHCI_HcInterruptEnable] &= ~(val & 0x7f); + case OHCI_aHcInterruptDisable: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0x7f); + dev->ohci_mmio[OHCI_HcInterruptEnable].b[0] &= ~(val & 0x7f); + ohci_update_irq(dev); return; - case OHCI_HcInterruptDisable + 1: - case OHCI_HcInterruptDisable + 2: + case OHCI_aHcInterruptDisable + 1: + case OHCI_aHcInterruptDisable + 2: return; - case OHCI_HcInterruptDisable + 3: - dev->ohci_mmio[addr] = (val & 0x40); - dev->ohci_mmio[addr] |= (val & 0x80); - if (val & 0x80) - dev->ohci_mmio[OHCI_HcInterruptEnable + 3] &= ~0x80; - if (val & 0x40) - dev->ohci_mmio[OHCI_HcInterruptEnable + 3] &= ~0x40; + case OHCI_aHcInterruptDisable + 3: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0xc0); + dev->ohci_mmio[OHCI_HcInterruptEnable].b[3] &= ~(val & 0xc0); + ohci_update_irq(dev); return; - case OHCI_HcInterruptStatus: - dev->ohci_mmio[addr] &= ~(val & 0x7f); + case OHCI_aHcInterruptStatus: + dev->ohci_mmio[addr >> 2].b[addr & 3] &= ~(val & 0x7f); return; - case OHCI_HcInterruptStatus + 1: - case OHCI_HcInterruptStatus + 2: + case OHCI_aHcInterruptStatus + 1: + case OHCI_aHcInterruptStatus + 2: return; - case OHCI_HcInterruptStatus + 3: - dev->ohci_mmio[addr] &= ~(val & 0x40); + case OHCI_aHcInterruptStatus + 3: + dev->ohci_mmio[addr >> 2].b[addr & 3] &= ~(val & 0x40); return; - case OHCI_HcFmRemaining + 3: - dev->ohci_mmio[addr] = (val & 0x80); + case OHCI_aHcFmRemaining + 3: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0x80); return; - case OHCI_HcFmRemaining + 1: - case OHCI_HcPeriodicStart + 1: - dev->ohci_mmio[addr] = (val & 0x3f); + case OHCI_aHcFmRemaining + 1: + case OHCI_aHcPeriodicStart + 1: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0x3f); return; - case OHCI_HcLSThreshold + 1: - dev->ohci_mmio[addr] = (val & 0x0f); + case OHCI_aHcLSThreshold + 1: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0x0f); return; - case OHCI_HcFmRemaining + 2: - case OHCI_HcFmNumber + 2: - case OHCI_HcFmNumber + 3: - case OHCI_HcPeriodicStart + 2: - case OHCI_HcPeriodicStart + 3: - case OHCI_HcLSThreshold + 2: - case OHCI_HcLSThreshold + 3: - case OHCI_HcRhDescriptorA: - case OHCI_HcRhDescriptorA + 2: + case OHCI_aHcFmRemaining + 2: + case OHCI_aHcFmNumber + 2: + case OHCI_aHcFmNumber + 3: + case OHCI_aHcPeriodicStart + 2: + case OHCI_aHcPeriodicStart + 3: + case OHCI_aHcLSThreshold + 2: + case OHCI_aHcLSThreshold + 3: + case OHCI_aHcRhDescriptorA: + case OHCI_aHcRhDescriptorA + 2: return; - case OHCI_HcRhDescriptorA + 1: - dev->ohci_mmio[addr] = (val & 0x1b); + case OHCI_aHcRhDescriptorA + 1: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0x1b); if (val & 0x02) { - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 1] |= 0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 1] |= 0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[1] |= 0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[1] |= 0x01; } return; - case OHCI_HcRhDescriptorA + 3: - dev->ohci_mmio[addr] = (val & 0x03); + case OHCI_aHcRhDescriptorA + 3: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0x03); return; - case OHCI_HcRhDescriptorB: - case OHCI_HcRhDescriptorB + 2: - dev->ohci_mmio[addr] = (val & 0x06); + case OHCI_aHcRhDescriptorB: + case OHCI_aHcRhDescriptorB + 2: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0x06); if ((addr == OHCI_HcRhDescriptorB) && !(val & 0x04)) { - if (!(dev->ohci_mmio[OHCI_HcRhPortStatus2] & 0x01)) - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] |= 0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus2] |= 0x01; + if (!(dev->ohci_mmio[OHCI_HcRhPortStatus2].b[0] & 0x01)) + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[2] |= 0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[0] |= 0x01; } if ((addr == OHCI_HcRhDescriptorB) && !(val & 0x02)) { - if (!(dev->ohci_mmio[OHCI_HcRhPortStatus1] & 0x01)) - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 2] |= 0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus1] |= 0x01; + if (!(dev->ohci_mmio[OHCI_HcRhPortStatus1].b[0] & 0x01)) + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[2] |= 0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[0] |= 0x01; } return; - case OHCI_HcRhDescriptorB + 1: - case OHCI_HcRhDescriptorB + 3: + case OHCI_aHcRhDescriptorB + 1: + case OHCI_aHcRhDescriptorB + 3: return; - case OHCI_HcRhStatus: + case OHCI_aHcRhStatus: if (val & 0x01) { - if ((dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] & 0x03) == 0x00) { - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 1] &= ~0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus1] &= ~0x17; - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 2] &= ~0x17; - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 1] &= ~0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus2] &= ~0x17; - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] &= ~0x17; - } else if ((dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] & 0x03) == 0x01) { - if (!(dev->ohci_mmio[OHCI_HcRhDescriptorB + 2] & 0x02)) { - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 1] &= ~0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus1] &= ~0x17; - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 2] &= ~0x17; + if ((dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] & 0x03) == 0x00) { + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[1] &= ~0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[0] &= ~0x17; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[2] &= ~0x17; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[1] &= ~0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[0] &= ~0x17; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[2] &= ~0x17; + } else if ((dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] & 0x03) == 0x01) { + if (!(dev->ohci_mmio[OHCI_HcRhDescriptorB].b[2] & 0x02)) { + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[1] &= ~0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[0] &= ~0x17; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[2] &= ~0x17; } - if (!(dev->ohci_mmio[OHCI_HcRhDescriptorB + 2] & 0x04)) { - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 1] &= ~0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus2] &= ~0x17; - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] &= ~0x17; + if (!(dev->ohci_mmio[OHCI_HcRhDescriptorB].b[2] & 0x04)) { + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[1] &= ~0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[0] &= ~0x17; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[2] &= ~0x17; } } } return; - case OHCI_HcRhStatus + 1: + case OHCI_aHcRhStatus + 1: if (val & 0x80) - dev->ohci_mmio[addr] |= 0x80; + dev->ohci_mmio[addr >> 2].b[addr & 3] |= 0x80; return; - case OHCI_HcRhStatus + 2: - dev->ohci_mmio[addr] &= ~(val & 0x02); + case OHCI_aHcRhStatus + 2: + dev->ohci_mmio[addr >> 2].b[addr & 3] &= ~(val & 0x02); if (val & 0x01) { - if ((dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] & 0x03) == 0x00) { - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 1] |= 0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 1] |= 0x01; - } else if ((dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] & 0x03) == 0x01) { - if (!(dev->ohci_mmio[OHCI_HcRhDescriptorB + 2] & 0x02)) - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 1] |= 0x01; - if (!(dev->ohci_mmio[OHCI_HcRhDescriptorB + 2] & 0x04)) - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 1] |= 0x01; + if ((dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] & 0x03) == 0x00) { + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[1] |= 0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[1] |= 0x01; + } else if ((dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] & 0x03) == 0x01) { + if (!(dev->ohci_mmio[OHCI_HcRhDescriptorB].b[2] & 0x02)) + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[1] |= 0x01; + if (!(dev->ohci_mmio[OHCI_HcRhDescriptorB].b[2] & 0x04)) + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[1] |= 0x01; } } return; - case OHCI_HcRhStatus + 3: + case OHCI_aHcRhStatus + 3: if (val & 0x80) - dev->ohci_mmio[OHCI_HcRhStatus + 1] &= ~0x80; + dev->ohci_mmio[OHCI_HcRhStatus].b[1] &= ~0x80; return; - case OHCI_HcRhPortStatus1: - case OHCI_HcRhPortStatus2: - old = dev->ohci_mmio[addr]; + case OHCI_aHcRhPortStatus1: + case OHCI_aHcRhPortStatus2: + old = dev->ohci_mmio[addr >> 2].b[addr & 3]; if (val & 0x10) { if (old & 0x01) { - dev->ohci_mmio[addr] |= 0x10; - timer_on_auto(&dev->ohci_port_reset_timer[(addr - OHCI_HcRhPortStatus1) / 4], 10000.); + dev->ohci_mmio[addr >> 2].b[addr & 3] |= 0x10; + timer_on_auto(&dev->ohci_port_reset_timer[(addr - OHCI_aHcRhPortStatus1) / 4], 10000.); } else - dev->ohci_mmio[addr + 2] |= 0x01; + dev->ohci_mmio[(addr + 2) >> 2].b[(addr + 2) & 3] |= 0x01; } if (val & 0x08) - dev->ohci_mmio[addr] &= ~0x04; + dev->ohci_mmio[addr >> 2].b[addr & 3] &= ~0x04; if (val & 0x04) - dev->ohci_mmio[addr] |= 0x04; + dev->ohci_mmio[addr >> 2].b[addr & 3] |= 0x04; if (val & 0x02) { if (old & 0x01) - dev->ohci_mmio[addr] |= 0x02; + dev->ohci_mmio[addr >> 2].b[addr & 3] |= 0x02; else - dev->ohci_mmio[addr + 2] |= 0x01; + dev->ohci_mmio[(addr + 2) >> 2].b[(addr + 2) & 3] |= 0x01; } if (val & 0x01) { if (old & 0x01) - dev->ohci_mmio[addr] &= ~0x02; + dev->ohci_mmio[addr >> 2].b[addr & 3] &= ~0x02; else - dev->ohci_mmio[addr + 2] |= 0x01; + dev->ohci_mmio[(addr + 2) >> 2].b[(addr + 2) & 3] |= 0x01; } - if (!(dev->ohci_mmio[addr] & 0x04) && (old & 0x04)) - dev->ohci_mmio[addr + 2] |= 0x04; - /* if (!(dev->ohci_mmio[addr] & 0x02)) - dev->ohci_mmio[addr + 2] |= 0x02; */ + if (!(dev->ohci_mmio[addr >> 2].b[addr & 3] & 0x04) && (old & 0x04)) + dev->ohci_mmio[(addr + 2) >> 2].b[(addr + 2) & 3] |= 0x04; + /* if (!(dev->ohci_mmio[addr >> 2].b[addr & 3] & 0x02)) + dev->ohci_mmio[(addr + 2) >> 2].b[(addr + 2) & 3] |= 0x02; */ return; - case OHCI_HcRhPortStatus1 + 1: - if ((val & 0x02) && ((dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] & 0x03) == 0x00) && (dev->ohci_mmio[OHCI_HcRhDescriptorB + 2] & 0x02)) { - dev->ohci_mmio[addr] &= ~0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus1] &= ~0x17; - dev->ohci_mmio[OHCI_HcRhPortStatus1 + 2] &= ~0x17; + case OHCI_aHcRhPortStatus1 + 1: + if ((val & 0x02) && ((dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] & 0x03) == 0x00) && (dev->ohci_mmio[OHCI_HcRhDescriptorB].b[2] & 0x02)) { + dev->ohci_mmio[addr >> 2].b[addr & 3] &= ~0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[0] &= ~0x17; + dev->ohci_mmio[OHCI_HcRhPortStatus1].b[2] &= ~0x17; } - if ((val & 0x01) && ((dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] & 0x03) == 0x00) && (dev->ohci_mmio[OHCI_HcRhDescriptorB + 2] & 0x02)) { - dev->ohci_mmio[addr] |= 0x01; - dev->ohci_mmio[OHCI_HcRhPortStatus2] &= ~0x17; - dev->ohci_mmio[OHCI_HcRhPortStatus2 + 2] &= ~0x17; + if ((val & 0x01) && ((dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] & 0x03) == 0x00) && (dev->ohci_mmio[OHCI_HcRhDescriptorB].b[2] & 0x02)) { + dev->ohci_mmio[addr >> 2].b[addr & 3] |= 0x01; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[0] &= ~0x17; + dev->ohci_mmio[OHCI_HcRhPortStatus2].b[2] &= ~0x17; } return; - case OHCI_HcRhPortStatus2 + 1: - if ((val & 0x02) && ((dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] & 0x03) == 0x00) && (dev->ohci_mmio[OHCI_HcRhDescriptorB + 2] & 0x04)) - dev->ohci_mmio[addr] &= ~0x01; - if ((val & 0x01) && ((dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] & 0x03) == 0x00) && (dev->ohci_mmio[OHCI_HcRhDescriptorB + 2] & 0x04)) - dev->ohci_mmio[addr] |= 0x01; + case OHCI_aHcRhPortStatus2 + 1: + if ((val & 0x02) && ((dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] & 0x03) == 0x00) && (dev->ohci_mmio[OHCI_HcRhDescriptorB].b[2] & 0x04)) + dev->ohci_mmio[addr >> 2].b[addr & 3] &= ~0x01; + if ((val & 0x01) && ((dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] & 0x03) == 0x00) && (dev->ohci_mmio[OHCI_HcRhDescriptorB].b[2] & 0x04)) + dev->ohci_mmio[addr >> 2].b[addr & 3] |= 0x01; return; - case OHCI_HcRhPortStatus1 + 2: - case OHCI_HcRhPortStatus2 + 2: - dev->ohci_mmio[addr] &= ~(val & 0x1f); + case OHCI_aHcRhPortStatus1 + 2: + case OHCI_aHcRhPortStatus2 + 2: + dev->ohci_mmio[addr >> 2].b[addr & 3] &= ~(val & 0x1f); return; - case OHCI_HcRhPortStatus1 + 3: - case OHCI_HcRhPortStatus2 + 3: + case OHCI_aHcRhPortStatus1 + 3: + case OHCI_aHcRhPortStatus2 + 3: return; - case OHCI_HcDoneHead: - case OHCI_HcBulkCurrentED: - case OHCI_HcBulkHeadED: - case OHCI_HcControlCurrentED: - case OHCI_HcControlHeadED: - case OHCI_HcPeriodCurrentED: - dev->ohci_mmio[addr] = (val & 0xf0); + case OHCI_aHcDoneHead: + case OHCI_aHcBulkCurrentED: + case OHCI_aHcBulkHeadED: + case OHCI_aHcControlCurrentED: + case OHCI_aHcControlHeadED: + case OHCI_aHcPeriodCurrentED: + dev->ohci_mmio[addr >> 2].b[addr & 3] = (val & 0xf0); return; } - dev->ohci_mmio[addr] = val; + dev->ohci_mmio[addr >> 2].b[addr & 3] = val; } + +static void +ohci_mmio_writew(uint32_t addr, uint16_t val, void *p) +{ + ohci_mmio_write(addr, val & 0xff, p); + ohci_mmio_write(addr + 1, val >> 8, p); +} + +static void +ohci_mmio_writel(uint32_t addr, uint32_t val, void *p) +{ + ohci_mmio_writew(addr, val & 0xffff, p); + ohci_mmio_writew(addr + 2, val >> 16, p); +} + void ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, int enable) { @@ -544,8 +617,13 @@ ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, dev->ohci_mem_base = ((base1 << 8) | (base2 << 16) | (base3 << 24)) & 0xfffff000; dev->ohci_enable = enable; - if (dev->ohci_enable && (dev->ohci_mem_base != 0x00000000)) + if (dev->ohci_enable && (dev->ohci_mem_base != 0x00000000)) { + dev->ohci_mmio_mapping.flags = MEM_MAPPING_EXTERNAL; mem_mapping_set_addr(&dev->ohci_mmio_mapping, dev->ohci_mem_base, 0x1000); + mem_mapping_enable(&dev->ohci_mmio_mapping); + } + + usb_log("ohci_update_mem_mapping(): OHCI %sabled at %08X\n", dev->ohci_enable ? "en" : "dis", dev->ohci_mem_base); } uint8_t @@ -565,21 +643,24 @@ usb_reset(void *priv) { usb_t *dev = (usb_t *) priv; - memset(dev->uhci_io, 0x00, 128); + memset(dev->uhci_io, 0x00, sizeof(dev->uhci_io)); dev->uhci_io[0x0c] = 0x40; dev->uhci_io[0x10] = dev->uhci_io[0x12] = 0x80; - memset(dev->ohci_mmio, 0x00, 4096); - dev->ohci_mmio[OHCI_HcRevision] = 0x10; - dev->ohci_mmio[OHCI_HcRevision + 1] = 0x01; - dev->ohci_mmio[OHCI_HcRhDescriptorA] = 0x02; - dev->ohci_mmio[OHCI_HcRhDescriptorA + 1] = 0x02; + memset(dev->ohci_mmio, 0x00, sizeof(dev->ohci_mmio)); + dev->ohci_mmio[OHCI_HcRevision].b[0] = 0x10; + dev->ohci_mmio[OHCI_HcRevision].b[1] = 0x01; + dev->ohci_mmio[OHCI_HcRhDescriptorA].b[0] = 0x02; + dev->ohci_mmio[OHCI_HcRhDescriptorA].b[1] = 0x02; io_removehandler(dev->uhci_io_base, 0x20, uhci_reg_read, NULL, NULL, uhci_reg_write, uhci_reg_writew, NULL, dev); dev->uhci_enable = 0; mem_mapping_disable(&dev->ohci_mmio_mapping); dev->ohci_enable = 0; + + usb_log("usb_reset(): OHCI %sabled at %08X\n", dev->ohci_enable ? "en" : "dis", dev->ohci_mem_base); + usb_log("usb_reset(): map = %08X\n", &dev->ohci_mmio_mapping); } static void @@ -591,7 +672,7 @@ usb_close(void *priv) } static void * -usb_init_ext(const device_t *info, void* params) +usb_init_ext(const device_t *info, void *params) { usb_t *dev; @@ -600,16 +681,20 @@ usb_init_ext(const device_t *info, void* params) return (NULL); memset(dev, 0x00, sizeof(usb_t)); - dev->usb_params = (usb_params_t*)params; + dev->usb_params = (usb_params_t *) params; - mem_mapping_add(&dev->ohci_mmio_mapping, 0, 0, - ohci_mmio_read, NULL, NULL, - ohci_mmio_write, NULL, NULL, + mem_mapping_add(&dev->ohci_mmio_mapping, 0, 0x1000, + ohci_mmio_read, ohci_mmio_readw, ohci_mmio_readl, + ohci_mmio_write, ohci_mmio_writew, ohci_mmio_writel, NULL, MEM_MAPPING_EXTERNAL, dev); + + mem_mapping_disable(&dev->ohci_mmio_mapping); + timer_add(&dev->ohci_frame_timer, ohci_update_frame_counter, dev, 0); /* Unused for now, to be used for frame counting. */ timer_add(&dev->ohci_port_reset_timer[0], ohci_port_reset_callback, dev, 0); timer_add(&dev->ohci_port_reset_timer[1], ohci_port_reset_callback_2, dev, 0); timer_add(&dev->ohci_interrupt_desc_poll_timer, ohci_poll_interrupt_descriptors, dev, 0); + usb_reset(dev); return dev; From 69f76176fe522353727167d9f172a97db1c5294c Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 7 May 2023 03:30:42 +0200 Subject: [PATCH 30/34] Removed unncessary files. --- src/device/keyboard_at - Cópia.c | 3258 ------------------------------ src/device/mouse_ps2 - Cópia.c | 404 ---- src/mem/mem - Cópia.c | 3092 ---------------------------- src/mouse.patch | 69 - src/pic - Cópia.c | 838 -------- 5 files changed, 7661 deletions(-) delete mode 100644 src/device/keyboard_at - Cópia.c delete mode 100644 src/device/mouse_ps2 - Cópia.c delete mode 100644 src/mem/mem - Cópia.c delete mode 100644 src/mouse.patch delete mode 100644 src/pic - Cópia.c diff --git a/src/device/keyboard_at - Cópia.c b/src/device/keyboard_at - Cópia.c deleted file mode 100644 index 3a841ad91..000000000 --- a/src/device/keyboard_at - Cópia.c +++ /dev/null @@ -1,3258 +0,0 @@ -/* - * 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. - * - * Intel 8042 (AT keyboard controller) emulation. - * - * - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * EngiNerd, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - * Copyright 2020 EngiNerd. - */ -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include -#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> - -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_MFULL 0x20 -#define STAT_UNLOCKED 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 - -#define CCB_UNUSED 0x80 -#define CCB_TRANSLATE 0x40 -#define CCB_PCMODE 0x20 -#define CCB_ENABLEKBD 0x10 -#define CCB_IGNORELOCK 0x08 -#define CCB_SYSTEM 0x04 -#define CCB_ENABLEMINT 0x02 -#define CCB_ENABLEKINT 0x01 - -#define CCB_MASK 0x68 -#define MODE_MASK 0x6c - -#define KBC_TYPE_ISA 0x00 /* AT ISA-based chips */ -#define KBC_TYPE_PS2_NOREF 0x01 /* PS2 type, no refresh */ -#define KBC_TYPE_PS2_1 0x02 /* PS2 on PS/2, type 1 */ -#define KBC_TYPE_PS2_2 0x03 /* PS2 on PS/2, type 2 */ -#define KBC_TYPE_MASK 0x03 - -#define KBC_VEN_GENERIC 0x00 -#define KBC_VEN_AMI 0x04 -#define KBC_VEN_IBM_MCA 0x08 -#define KBC_VEN_QUADTEL 0x0c -#define KBC_VEN_TOSHIBA 0x10 -#define KBC_VEN_IBM_PS1 0x14 -#define KBC_VEN_ACER 0x18 -#define KBC_VEN_INTEL_AMI 0x1c -#define KBC_VEN_OLIVETTI 0x20 -#define KBC_VEN_NCR 0x24 -#define KBC_VEN_PHOENIX 0x28 -#define KBC_VEN_ALI 0x2c -#define KBC_VEN_TG 0x30 -#define KBC_VEN_TG_GREEN 0x34 -#define KBC_VEN_MASK 0x3c - -enum { - KBC_STATE_RESET = 0, - KBC_STATE_MAIN_IBF, - KBC_STATE_MAIN_KBD, - KBC_STATE_MAIN_MOUSE, - KBC_STATE_MAIN_BOTH, - KBC_STATE_KBC_OUT, - KBC_STATE_KBC_PARAM, - KBC_STATE_SEND_KBD, - KBC_STATE_KBD, - KBC_STATE_SEND_MOUSE, - KBC_STATE_MOUSE -}; -#define KBC_STATE_SCAN_KBD KBC_STATE_KBD -#define KBC_STATE_SCAN_MOUSE KBC_STATE_MOUSE - -enum { - DEV_STATE_MAIN_1 = 0, - DEV_STATE_MAIN_2, - DEV_STATE_MAIN_CMD, - DEV_STATE_MAIN_OUT, - DEV_STATE_MAIN_WANT_IN, - DEV_STATE_MAIN_IN -}; - -typedef struct { - /* Controller. */ - uint8_t pci, kbc_state, command, want60, - status, ib, out, old_out, - sc_or, secr_phase, mem_addr, input_port, - output_port, old_output_port, output_locked, ami_stat, - ami_flags, key_ctrl_queue_start, key_ctrl_queue_end; - - /* Keyboard. */ - uint8_t key_command, key_wantdata, kbd_last_scan_code, - kbd_state, key_wantcmd, key_dat, key_cmd_queue_start, - key_cmd_queue_end, key_queue_start, key_queue_end; - - /* Mouse. */ - uint8_t mouse_state, mouse_wantcmd, mouse_dat, mouse_cmd_queue_start, - mouse_cmd_queue_end, mouse_queue_start, mouse_queue_end; - - /* Controller. */ - uint8_t mem[0x100]; - - /* Controller - internal FIFO for the purpose of commands with multi-byte output. */ - uint8_t key_ctrl_queue[64]; - - /* Keyboard - command response FIFO. */ - uint8_t key_cmd_queue[16]; - - /* Keyboard - scan FIFO. */ - uint8_t key_queue[16]; - - /* Mouse - command response FIFO. */ - uint8_t mouse_cmd_queue[16]; - - /* Mouse - scan FIFO. */ - uint8_t mouse_queue[16]; - - /* Keyboard. */ - int out_new; - - /* Mouse. */ - int out_new_mouse; - - /* Controller. */ - uint32_t flags; - - /* Controller (main timer). */ - pc_timer_t send_delay_timer; - - /* Controller (P2 pulse callback timer). */ - pc_timer_t pulse_cb; - - uint8_t (*write60_ven)(void *p, uint8_t val); - uint8_t (*write64_ven)(void *p, uint8_t val); -} atkbd_t; - -/* Global keyboard flags for scan code set 3: - bit 0 = repeat, bit 1 = makes break code? */ -uint8_t keyboard_set3_flags[512]; -uint8_t keyboard_set3_all_repeat; -uint8_t keyboard_set3_all_break; - -/* Global keyboard mode: - Bits 0 - 1 = scan code set. */ -uint8_t keyboard_mode = 0x02; - -/* Keyboard controller ports. */ -kbc_port_t *kbc_ports[2] = { NULL, NULL }; - -static void (*mouse_write)(uint8_t val, void *priv) = NULL; -static void *mouse_p = NULL; -static atkbd_t *SavedKbd = NULL; // FIXME: remove!!! --FvK - -/* Non-translated to translated scan codes. */ -static const uint8_t nont_to_t[256] = { - 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, - 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59, - 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, - 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b, - 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, - 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d, - 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, - 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f, - 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, - 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61, - 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, - 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76, - 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, - 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f, - 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, - 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54, - 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -static const scancode scancode_set1[512] = { - // clang-format off - { { 0},{ 0} }, { { 0x01,0},{ 0x81,0} }, { { 0x02,0},{ 0x82,0} }, { { 0x03,0},{ 0x83,0} }, /*000*/ - { { 0x04,0},{ 0x84,0} }, { { 0x05,0},{ 0x85,0} }, { { 0x06,0},{ 0x86,0} }, { { 0x07,0},{ 0x87,0} }, /*004*/ - { { 0x08,0},{ 0x88,0} }, { { 0x09,0},{ 0x89,0} }, { { 0x0a,0},{ 0x8a,0} }, { { 0x0b,0},{ 0x8b,0} }, /*008*/ - { { 0x0c,0},{ 0x8c,0} }, { { 0x0d,0},{ 0x8d,0} }, { { 0x0e,0},{ 0x8e,0} }, { { 0x0f,0},{ 0x8f,0} }, /*00c*/ - { { 0x10,0},{ 0x90,0} }, { { 0x11,0},{ 0x91,0} }, { { 0x12,0},{ 0x92,0} }, { { 0x13,0},{ 0x93,0} }, /*010*/ - { { 0x14,0},{ 0x94,0} }, { { 0x15,0},{ 0x95,0} }, { { 0x16,0},{ 0x96,0} }, { { 0x17,0},{ 0x97,0} }, /*014*/ - { { 0x18,0},{ 0x98,0} }, { { 0x19,0},{ 0x99,0} }, { { 0x1a,0},{ 0x9a,0} }, { { 0x1b,0},{ 0x9b,0} }, /*018*/ - { { 0x1c,0},{ 0x9c,0} }, { { 0x1d,0},{ 0x9d,0} }, { { 0x1e,0},{ 0x9e,0} }, { { 0x1f,0},{ 0x9f,0} }, /*01c*/ - { { 0x20,0},{ 0xa0,0} }, { { 0x21,0},{ 0xa1,0} }, { { 0x22,0},{ 0xa2,0} }, { { 0x23,0},{ 0xa3,0} }, /*020*/ - { { 0x24,0},{ 0xa4,0} }, { { 0x25,0},{ 0xa5,0} }, { { 0x26,0},{ 0xa6,0} }, { { 0x27,0},{ 0xa7,0} }, /*024*/ - { { 0x28,0},{ 0xa8,0} }, { { 0x29,0},{ 0xa9,0} }, { { 0x2a,0},{ 0xaa,0} }, { { 0x2b,0},{ 0xab,0} }, /*028*/ - { { 0x2c,0},{ 0xac,0} }, { { 0x2d,0},{ 0xad,0} }, { { 0x2e,0},{ 0xae,0} }, { { 0x2f,0},{ 0xaf,0} }, /*02c*/ - { { 0x30,0},{ 0xb0,0} }, { { 0x31,0},{ 0xb1,0} }, { { 0x32,0},{ 0xb2,0} }, { { 0x33,0},{ 0xb3,0} }, /*030*/ - { { 0x34,0},{ 0xb4,0} }, { { 0x35,0},{ 0xb5,0} }, { { 0x36,0},{ 0xb6,0} }, { { 0x37,0},{ 0xb7,0} }, /*034*/ - { { 0x38,0},{ 0xb8,0} }, { { 0x39,0},{ 0xb9,0} }, { { 0x3a,0},{ 0xba,0} }, { { 0x3b,0},{ 0xbb,0} }, /*038*/ - { { 0x3c,0},{ 0xbc,0} }, { { 0x3d,0},{ 0xbd,0} }, { { 0x3e,0},{ 0xbe,0} }, { { 0x3f,0},{ 0xbf,0} }, /*03c*/ - { { 0x40,0},{ 0xc0,0} }, { { 0x41,0},{ 0xc1,0} }, { { 0x42,0},{ 0xc2,0} }, { { 0x43,0},{ 0xc3,0} }, /*040*/ - { { 0x44,0},{ 0xc4,0} }, { { 0x45,0},{ 0xc5,0} }, { { 0x46,0},{ 0xc6,0} }, { { 0x47,0},{ 0xc7,0} }, /*044*/ - { { 0x48,0},{ 0xc8,0} }, { { 0x49,0},{ 0xc9,0} }, { { 0x4a,0},{ 0xca,0} }, { { 0x4b,0},{ 0xcb,0} }, /*048*/ - { { 0x4c,0},{ 0xcc,0} }, { { 0x4d,0},{ 0xcd,0} }, { { 0x4e,0},{ 0xce,0} }, { { 0x4f,0},{ 0xcf,0} }, /*04c*/ - { { 0x50,0},{ 0xd0,0} }, { { 0x51,0},{ 0xd1,0} }, { { 0x52,0},{ 0xd2,0} }, { { 0x53,0},{ 0xd3,0} }, /*050*/ - { { 0x54,0},{ 0xd4,0} }, { { 0x55,0},{ 0xd5,0} }, { { 0x56,0},{ 0xd6,0} }, { { 0x57,0},{ 0xd7,0} }, /*054*/ - { { 0x58,0},{ 0xd8,0} }, { { 0x59,0},{ 0xd9,0} }, { { 0x5a,0},{ 0xda,0} }, { { 0x5b,0},{ 0xdb,0} }, /*058*/ - { { 0x5c,0},{ 0xdc,0} }, { { 0x5d,0},{ 0xdd,0} }, { { 0x5e,0},{ 0xde,0} }, { { 0x5f,0},{ 0xdf,0} }, /*05c*/ - { { 0x60,0},{ 0xe0,0} }, { { 0x61,0},{ 0xe1,0} }, { { 0x62,0},{ 0xe2,0} }, { { 0x63,0},{ 0xe3,0} }, /*060*/ - { { 0x64,0},{ 0xe4,0} }, { { 0x65,0},{ 0xe5,0} }, { { 0x66,0},{ 0xe6,0} }, { { 0x67,0},{ 0xe7,0} }, /*064*/ - { { 0x68,0},{ 0xe8,0} }, { { 0x69,0},{ 0xe9,0} }, { { 0x6a,0},{ 0xea,0} }, { { 0x6b,0},{ 0xeb,0} }, /*068*/ - { { 0x6c,0},{ 0xec,0} }, { { 0x6d,0},{ 0xed,0} }, { { 0x6e,0},{ 0xee,0} }, { { 0x6f,0},{ 0xef,0} }, /*06c*/ - { { 0x70,0},{ 0xf0,0} }, { { 0x71,0},{ 0xf1,0} }, { { 0x72,0},{ 0xf2,0} }, { { 0x73,0},{ 0xf3,0} }, /*070*/ - { { 0x74,0},{ 0xf4,0} }, { { 0x75,0},{ 0xf5,0} }, { { 0x76,0},{ 0xf6,0} }, { { 0x77,0},{ 0xf7,0} }, /*074*/ - { { 0x78,0},{ 0xf8,0} }, { { 0x79,0},{ 0xf9,0} }, { { 0x7a,0},{ 0xfa,0} }, { { 0x7b,0},{ 0xfb,0} }, /*078*/ - { { 0x7c,0},{ 0xfc,0} }, { { 0x7d,0},{ 0xfd,0} }, { { 0x7e,0},{ 0xfe,0} }, { { 0x7f,0},{ 0xff,0} }, /*07c*/ - - { { 0x80,0},{ 0} }, { { 0x81,0},{ 0} }, { { 0x82,0},{ 0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0} }, { { 0x86,0},{ 0} }, { { 0x87,0},{ 0} }, /*084*/ - { { 0x88,0},{ 0} }, { { 0x89,0},{ 0} }, { { 0x8a,0},{ 0} }, { { 0x8b,0},{ 0} }, /*088*/ - { { 0x8c,0},{ 0} }, { { 0x8d,0},{ 0} }, { { 0x8e,0},{ 0} }, { { 0x8f,0},{ 0} }, /*08c*/ - { { 0x90,0},{ 0} }, { { 0x91,0},{ 0} }, { { 0x92,0},{ 0} }, { { 0x93,0},{ 0} }, /*090*/ - { { 0x94,0},{ 0} }, { { 0x95,0},{ 0} }, { { 0x96,0},{ 0} }, { { 0x97,0},{ 0} }, /*094*/ - { { 0x98,0},{ 0} }, { { 0x99,0},{ 0} }, { { 0x9a,0},{ 0} }, { { 0x9b,0},{ 0} }, /*098*/ - { { 0x9c,0},{ 0} }, { { 0x9d,0},{ 0} }, { { 0x9e,0},{ 0} }, { { 0x9f,0},{ 0} }, /*09c*/ - { { 0xa0,0},{ 0} }, { { 0xa1,0},{ 0} }, { { 0xa2,0},{ 0} }, { { 0xa3,0},{ 0} }, /*0a0*/ - { { 0xa4,0},{ 0} }, { { 0xa5,0},{ 0} }, { { 0xa6,0},{ 0} }, { { 0xa7,0},{ 0} }, /*0a4*/ - { { 0xa8,0},{ 0} }, { { 0xa9,0},{ 0} }, { { 0xaa,0},{ 0} }, { { 0xab,0},{ 0} }, /*0a8*/ - { { 0xac,0},{ 0} }, { { 0xad,0},{ 0} }, { { 0xae,0},{ 0} }, { { 0xaf,0},{ 0} }, /*0ac*/ - { { 0xb0,0},{ 0} }, { { 0xb1,0},{ 0} }, { { 0xb2,0},{ 0} }, { { 0xb3,0},{ 0} }, /*0b0*/ - { { 0xb4,0},{ 0} }, { { 0xb5,0},{ 0} }, { { 0xb6,0},{ 0} }, { { 0xb7,0},{ 0} }, /*0b4*/ - { { 0xb8,0},{ 0} }, { { 0xb9,0},{ 0} }, { { 0xba,0},{ 0} }, { { 0xbb,0},{ 0} }, /*0b8*/ - { { 0xbc,0},{ 0} }, { { 0xbd,0},{ 0} }, { { 0xbe,0},{ 0} }, { { 0xbf,0},{ 0} }, /*0bc*/ - { { 0xc0,0},{ 0} }, { { 0xc1,0},{ 0} }, { { 0xc2,0},{ 0} }, { { 0xc3,0},{ 0} }, /*0c0*/ - { { 0xc4,0},{ 0} }, { { 0xc5,0},{ 0} }, { { 0xc6,0},{ 0} }, { { 0xc7,0},{ 0} }, /*0c4*/ - { { 0xc8,0},{ 0} }, { { 0xc9,0},{ 0} }, { { 0xca,0},{ 0} }, { { 0xcb,0},{ 0} }, /*0c8*/ - { { 0xcc,0},{ 0} }, { { 0xcd,0},{ 0} }, { { 0xce,0},{ 0} }, { { 0xcf,0},{ 0} }, /*0cc*/ - { { 0xd0,0},{ 0} }, { { 0xd1,0},{ 0} }, { { 0xd2,0},{ 0} }, { { 0xd3,0},{ 0} }, /*0d0*/ - { { 0xd4,0},{ 0} }, { { 0xd5,0},{ 0} }, { { 0xd6,0},{ 0} }, { { 0xd7,0},{ 0} }, /*0d4*/ - { { 0xd8,0},{ 0} }, { { 0xd9,0},{ 0} }, { { 0xda,0},{ 0} }, { { 0xdb,0},{ 0} }, /*0d8*/ - { { 0xdc,0},{ 0} }, { { 0xdd,0},{ 0} }, { { 0xde,0},{ 0} }, { { 0xdf,0},{ 0} }, /*0dc*/ - { { 0xe0,0},{ 0} }, { { 0xe1,0},{ 0} }, { { 0xe2,0},{ 0} }, { { 0xe3,0},{ 0} }, /*0e0*/ - { { 0xe4,0},{ 0} }, { { 0xe5,0},{ 0} }, { { 0xe6,0},{ 0} }, { { 0xe7,0},{ 0} }, /*0e4*/ - { { 0xe8,0},{ 0} }, { { 0xe9,0},{ 0} }, { { 0xea,0},{ 0} }, { { 0xeb,0},{ 0} }, /*0e8*/ - { { 0xec,0},{ 0} }, { { 0xed,0},{ 0} }, { { 0xee,0},{ 0} }, { { 0xef,0},{ 0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0} }, { { 0xf2,0},{ 0} }, { { 0xf3,0},{ 0} }, /*0f0*/ - { { 0xf4,0},{ 0} }, { { 0xf5,0},{ 0} }, { { 0xf6,0},{ 0} }, { { 0xf7,0},{ 0} }, /*0f4*/ - { { 0xf8,0},{ 0} }, { { 0xf9,0},{ 0} }, { { 0xfa,0},{ 0} }, { { 0xfb,0},{ 0} }, /*0f8*/ - { { 0xfc,0},{ 0} }, { { 0xfd,0},{ 0} }, { { 0xfe,0},{ 0} }, { { 0xff,0},{ 0} }, /*0fc*/ - - { {0xe1,0x1d,0},{0xe1, 0x9d,0} }, { {0xe0,0x01,0},{0xe0, 0x81,0} }, { {0xe0,0x02,0},{0xe0, 0x82,0} }, { {0xe0,0x03,0},{0xe0, 0x83,0} }, /*100*/ - { {0xe0,0x04,0},{0xe0, 0x84,0} }, { {0xe0,0x05,0},{0xe0, 0x85,0} }, { {0xe0,0x06,0},{0xe0, 0x86,0} }, { {0xe0,0x07,0},{0xe0, 0x87,0} }, /*104*/ - { {0xe0,0x08,0},{0xe0, 0x88,0} }, { {0xe0,0x09,0},{0xe0, 0x89,0} }, { {0xe0,0x0a,0},{0xe0, 0x8a,0} }, { {0xe0,0x0b,0},{0xe0, 0x8b,0} }, /*108*/ - { {0xe0,0x0c,0},{0xe0, 0x8c,0} }, { { 0},{ 0} }, { {0xe0,0x0e,0},{0xe0, 0x8e,0} }, { {0xe0,0x0f,0},{0xe0, 0x8f,0} }, /*10c*/ - { {0xe0,0x10,0},{0xe0, 0x90,0} }, { {0xe0,0x11,0},{0xe0, 0x91,0} }, { {0xe0,0x12,0},{0xe0, 0x92,0} }, { {0xe0,0x13,0},{0xe0, 0x93,0} }, /*110*/ - { {0xe0,0x14,0},{0xe0, 0x94,0} }, { {0xe0,0x15,0},{0xe0, 0x95,0} }, { {0xe0,0x16,0},{0xe0, 0x96,0} }, { {0xe0,0x17,0},{0xe0, 0x97,0} }, /*114*/ - { {0xe0,0x18,0},{0xe0, 0x98,0} }, { {0xe0,0x19,0},{0xe0, 0x99,0} }, { {0xe0,0x1a,0},{0xe0, 0x9a,0} }, { {0xe0,0x1b,0},{0xe0, 0x9b,0} }, /*118*/ - { {0xe0,0x1c,0},{0xe0, 0x9c,0} }, { {0xe0,0x1d,0},{0xe0, 0x9d,0} }, { {0xe0,0x1e,0},{0xe0, 0x9e,0} }, { {0xe0,0x1f,0},{0xe0, 0x9f,0} }, /*11c*/ - { {0xe0,0x20,0},{0xe0, 0xa0,0} }, { {0xe0,0x21,0},{0xe0, 0xa1,0} }, { {0xe0,0x22,0},{0xe0, 0xa2,0} }, { {0xe0,0x23,0},{0xe0, 0xa3,0} }, /*120*/ - { {0xe0,0x24,0},{0xe0, 0xa4,0} }, { {0xe0,0x25,0},{0xe0, 0xa5,0} }, { {0xe0,0x26,0},{0xe0, 0xa6,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x2c,0},{0xe0, 0xac,0} }, { {0xe0,0x2d,0},{0xe0, 0xad,0} }, { {0xe0,0x2e,0},{0xe0, 0xae,0} }, { {0xe0,0x2f,0},{0xe0, 0xaf,0} }, /*12c*/ - { {0xe0,0x30,0},{0xe0, 0xb0,0} }, { {0xe0,0x31,0},{0xe0, 0xb1,0} }, { {0xe0,0x32,0},{0xe0, 0xb2,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x34,0},{0xe0, 0xb4,0} }, { {0xe0,0x35,0},{0xe0, 0xb5,0} }, { { 0},{ 0} }, { {0xe0,0x37,0},{0xe0, 0xb7,0} }, /*134*/ - { {0xe0,0x38,0},{0xe0, 0xb8,0} }, { { 0},{ 0} }, { {0xe0,0x3a,0},{0xe0, 0xba,0} }, { {0xe0,0x3b,0},{0xe0, 0xbb,0} }, /*138*/ - { {0xe0,0x3c,0},{0xe0, 0xbc,0} }, { {0xe0,0x3d,0},{0xe0, 0xbd,0} }, { {0xe0,0x3e,0},{0xe0, 0xbe,0} }, { {0xe0,0x3f,0},{0xe0, 0xbf,0} }, /*13c*/ - { {0xe0,0x40,0},{0xe0, 0xc0,0} }, { {0xe0,0x41,0},{0xe0, 0xc1,0} }, { {0xe0,0x42,0},{0xe0, 0xc2,0} }, { {0xe0,0x43,0},{0xe0, 0xc3,0} }, /*140*/ - { {0xe0,0x44,0},{0xe0, 0xc4,0} }, { { 0},{ 0} }, { {0xe0,0x46,0},{0xe0, 0xc6,0} }, { {0xe0,0x47,0},{0xe0, 0xc7,0} }, /*144*/ - { {0xe0,0x48,0},{0xe0, 0xc8,0} }, { {0xe0,0x49,0},{0xe0, 0xc9,0} }, { { 0},{ 0} }, { {0xe0,0x4b,0},{0xe0, 0xcb,0} }, /*148*/ - { {0xe0,0x4c,0},{0xe0, 0xcc,0} }, { {0xe0,0x4d,0},{0xe0, 0xcd,0} }, { {0xe0,0x4e,0},{0xe0, 0xce,0} }, { {0xe0,0x4f,0},{0xe0, 0xcf,0} }, /*14c*/ - { {0xe0,0x50,0},{0xe0, 0xd0,0} }, { {0xe0,0x51,0},{0xe0, 0xd1,0} }, { {0xe0,0x52,0},{0xe0, 0xd2,0} }, { {0xe0,0x53,0},{0xe0, 0xd3,0} }, /*150*/ - { { 0},{ 0} }, { {0xe0,0x55,0},{0xe0, 0xd5,0} }, { { 0},{ 0} }, { {0xe0,0x57,0},{0xe0, 0xd7,0} }, /*154*/ - { {0xe0,0x58,0},{0xe0, 0xd8,0} }, { {0xe0,0x59,0},{0xe0, 0xd9,0} }, { {0xe0,0x5a,0},{0xe0, 0xaa,0} }, { {0xe0,0x5b,0},{0xe0, 0xdb,0} }, /*158*/ - { {0xe0,0x5c,0},{0xe0, 0xdc,0} }, { {0xe0,0x5d,0},{0xe0, 0xdd,0} }, { {0xe0,0x5e,0},{0xe0, 0xee,0} }, { {0xe0,0x5f,0},{0xe0, 0xdf,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x61,0},{0xe0, 0xe1,0} }, { {0xe0,0x62,0},{0xe0, 0xe2,0} }, { {0xe0,0x63,0},{0xe0, 0xe3,0} }, /*160*/ - { {0xe0,0x64,0},{0xe0, 0xe4,0} }, { {0xe0,0x65,0},{0xe0, 0xe5,0} }, { {0xe0,0x66,0},{0xe0, 0xe6,0} }, { {0xe0,0x67,0},{0xe0, 0xe7,0} }, /*164*/ - { {0xe0,0x68,0},{0xe0, 0xe8,0} }, { {0xe0,0x69,0},{0xe0, 0xe9,0} }, { {0xe0,0x6a,0},{0xe0, 0xea,0} }, { {0xe0,0x6b,0},{0xe0, 0xeb,0} }, /*168*/ - { {0xe0,0x6c,0},{0xe0, 0xec,0} }, { {0xe0,0x6d,0},{0xe0, 0xed,0} }, { {0xe0,0x6e,0},{0xe0, 0xee,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x70,0},{0xe0, 0xf0,0} }, { {0xe0,0x71,0},{0xe0, 0xf1,0} }, { {0xe0,0x72,0},{0xe0, 0xf2,0} }, { {0xe0,0x73,0},{0xe0, 0xf3,0} }, /*170*/ - { {0xe0,0x74,0},{0xe0, 0xf4,0} }, { {0xe0,0x75,0},{0xe0, 0xf5,0} }, { { 0},{ 0} }, { {0xe0,0x77,0},{0xe0, 0xf7,0} }, /*174*/ - { {0xe0,0x78,0},{0xe0, 0xf8,0} }, { {0xe0,0x79,0},{0xe0, 0xf9,0} }, { {0xe0,0x7a,0},{0xe0, 0xfa,0} }, { {0xe0,0x7b,0},{0xe0, 0xfb,0} }, /*178*/ - { {0xe0,0x7c,0},{0xe0, 0xfc,0} }, { {0xe0,0x7d,0},{0xe0, 0xfd,0} }, { {0xe0,0x7e,0},{0xe0, 0xfe,0} }, { {0xe0,0x7f,0},{0xe0, 0xff,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{ 0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{ 0} }, { {0xe0,0xff,0},{ 0} } /*1fc*/ - // clang-format on -}; - -static const scancode scancode_set2[512] = { - // clang-format off - { { 0},{ 0} }, { { 0x76,0},{ 0xF0,0x76,0} }, { { 0x16,0},{ 0xF0,0x16,0} }, { { 0x1E,0},{ 0xF0,0x1E,0} }, /*000*/ - { { 0x26,0},{ 0xF0,0x26,0} }, { { 0x25,0},{ 0xF0,0x25,0} }, { { 0x2E,0},{ 0xF0,0x2E,0} }, { { 0x36,0},{ 0xF0,0x36,0} }, /*004*/ - { { 0x3D,0},{ 0xF0,0x3D,0} }, { { 0x3E,0},{ 0xF0,0x3E,0} }, { { 0x46,0},{ 0xF0,0x46,0} }, { { 0x45,0},{ 0xF0,0x45,0} }, /*008*/ - { { 0x4E,0},{ 0xF0,0x4E,0} }, { { 0x55,0},{ 0xF0,0x55,0} }, { { 0x66,0},{ 0xF0,0x66,0} }, { { 0x0D,0},{ 0xF0,0x0D,0} }, /*00c*/ - { { 0x15,0},{ 0xF0,0x15,0} }, { { 0x1D,0},{ 0xF0,0x1D,0} }, { { 0x24,0},{ 0xF0,0x24,0} }, { { 0x2D,0},{ 0xF0,0x2D,0} }, /*010*/ - { { 0x2C,0},{ 0xF0,0x2C,0} }, { { 0x35,0},{ 0xF0,0x35,0} }, { { 0x3C,0},{ 0xF0,0x3C,0} }, { { 0x43,0},{ 0xF0,0x43,0} }, /*014*/ - { { 0x44,0},{ 0xF0,0x44,0} }, { { 0x4D,0},{ 0xF0,0x4D,0} }, { { 0x54,0},{ 0xF0,0x54,0} }, { { 0x5B,0},{ 0xF0,0x5B,0} }, /*018*/ - { { 0x5A,0},{ 0xF0,0x5A,0} }, { { 0x14,0},{ 0xF0,0x14,0} }, { { 0x1C,0},{ 0xF0,0x1C,0} }, { { 0x1B,0},{ 0xF0,0x1B,0} }, /*01c*/ - { { 0x23,0},{ 0xF0,0x23,0} }, { { 0x2B,0},{ 0xF0,0x2B,0} }, { { 0x34,0},{ 0xF0,0x34,0} }, { { 0x33,0},{ 0xF0,0x33,0} }, /*020*/ - { { 0x3B,0},{ 0xF0,0x3B,0} }, { { 0x42,0},{ 0xF0,0x42,0} }, { { 0x4B,0},{ 0xF0,0x4B,0} }, { { 0x4C,0},{ 0xF0,0x4C,0} }, /*024*/ - { { 0x52,0},{ 0xF0,0x52,0} }, { { 0x0E,0},{ 0xF0,0x0E,0} }, { { 0x12,0},{ 0xF0,0x12,0} }, { { 0x5D,0},{ 0xF0,0x5D,0} }, /*028*/ - { { 0x1A,0},{ 0xF0,0x1A,0} }, { { 0x22,0},{ 0xF0,0x22,0} }, { { 0x21,0},{ 0xF0,0x21,0} }, { { 0x2A,0},{ 0xF0,0x2A,0} }, /*02c*/ - { { 0x32,0},{ 0xF0,0x32,0} }, { { 0x31,0},{ 0xF0,0x31,0} }, { { 0x3A,0},{ 0xF0,0x3A,0} }, { { 0x41,0},{ 0xF0,0x41,0} }, /*030*/ - { { 0x49,0},{ 0xF0,0x49,0} }, { { 0x4A,0},{ 0xF0,0x4A,0} }, { { 0x59,0},{ 0xF0,0x59,0} }, { { 0x7C,0},{ 0xF0,0x7C,0} }, /*034*/ - { { 0x11,0},{ 0xF0,0x11,0} }, { { 0x29,0},{ 0xF0,0x29,0} }, { { 0x58,0},{ 0xF0,0x58,0} }, { { 0x05,0},{ 0xF0,0x05,0} }, /*038*/ - { { 0x06,0},{ 0xF0,0x06,0} }, { { 0x04,0},{ 0xF0,0x04,0} }, { { 0x0C,0},{ 0xF0,0x0C,0} }, { { 0x03,0},{ 0xF0,0x03,0} }, /*03c*/ - { { 0x0B,0},{ 0xF0,0x0B,0} }, { { 0x83,0},{ 0xF0,0x83,0} }, { { 0x0A,0},{ 0xF0,0x0A,0} }, { { 0x01,0},{ 0xF0,0x01,0} }, /*040*/ - { { 0x09,0},{ 0xF0,0x09,0} }, { { 0x77,0},{ 0xF0,0x77,0} }, { { 0x7E,0},{ 0xF0,0x7E,0} }, { { 0x6C,0},{ 0xF0,0x6C,0} }, /*044*/ - { { 0x75,0},{ 0xF0,0x75,0} }, { { 0x7D,0},{ 0xF0,0x7D,0} }, { { 0x7B,0},{ 0xF0,0x7B,0} }, { { 0x6B,0},{ 0xF0,0x6B,0} }, /*048*/ - { { 0x73,0},{ 0xF0,0x73,0} }, { { 0x74,0},{ 0xF0,0x74,0} }, { { 0x79,0},{ 0xF0,0x79,0} }, { { 0x69,0},{ 0xF0,0x69,0} }, /*04c*/ - { { 0x72,0},{ 0xF0,0x72,0} }, { { 0x7A,0},{ 0xF0,0x7A,0} }, { { 0x70,0},{ 0xF0,0x70,0} }, { { 0x71,0},{ 0xF0,0x71,0} }, /*050*/ - { { 0x84,0},{ 0xF0,0x84,0} }, { { 0x60,0},{ 0xF0,0x60,0} }, { { 0x61,0},{ 0xF0,0x61,0} }, { { 0x78,0},{ 0xF0,0x78,0} }, /*054*/ - { { 0x07,0},{ 0xF0,0x07,0} }, { { 0x0F,0},{ 0xF0,0x0F,0} }, { { 0x17,0},{ 0xF0,0x17,0} }, { { 0x1F,0},{ 0xF0,0x1F,0} }, /*058*/ - { { 0x27,0},{ 0xF0,0x27,0} }, { { 0x2F,0},{ 0xF0,0x2F,0} }, { { 0x37,0},{ 0xF0,0x37,0} }, { { 0x3F,0},{ 0xF0,0x3F,0} }, /*05c*/ - { { 0x47,0},{ 0xF0,0x47,0} }, { { 0x4F,0},{ 0xF0,0x4F,0} }, { { 0x56,0},{ 0xF0,0x56,0} }, { { 0x5E,0},{ 0xF0,0x5E,0} }, /*060*/ - { { 0x08,0},{ 0xF0,0x08,0} }, { { 0x10,0},{ 0xF0,0x10,0} }, { { 0x18,0},{ 0xF0,0x18,0} }, { { 0x20,0},{ 0xF0,0x20,0} }, /*064*/ - { { 0x28,0},{ 0xF0,0x28,0} }, { { 0x30,0},{ 0xF0,0x30,0} }, { { 0x38,0},{ 0xF0,0x38,0} }, { { 0x40,0},{ 0xF0,0x40,0} }, /*068*/ - { { 0x48,0},{ 0xF0,0x48,0} }, { { 0x50,0},{ 0xF0,0x50,0} }, { { 0x57,0},{ 0xF0,0x57,0} }, { { 0x6F,0},{ 0xF0,0x6F,0} }, /*06c*/ - { { 0x13,0},{ 0xF0,0x13,0} }, { { 0x19,0},{ 0xF0,0x19,0} }, { { 0x39,0},{ 0xF0,0x39,0} }, { { 0x51,0},{ 0xF0,0x51,0} }, /*070*/ - { { 0x53,0},{ 0xF0,0x53,0} }, { { 0x5C,0},{ 0xF0,0x5C,0} }, { { 0x5F,0},{ 0xF0,0x5F,0} }, { { 0x62,0},{ 0xF0,0x62,0} }, /*074*/ - { { 0x63,0},{ 0xF0,0x63,0} }, { { 0x64,0},{ 0xF0,0x64,0} }, { { 0x65,0},{ 0xF0,0x65,0} }, { { 0x67,0},{ 0xF0,0x67,0} }, /*078*/ - { { 0x68,0},{ 0xF0,0x68,0} }, { { 0x6A,0},{ 0xF0,0x6A,0} }, { { 0x6D,0},{ 0xF0,0x6D,0} }, { { 0x6E,0},{ 0xF0,0x6E,0} }, /*07c*/ - - { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ - { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ - { { 0x8c,0},{ 0xf0,0x8c,0} }, { { 0x8d,0},{ 0xf0,0x8d,0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ - { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ - { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ - { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ - { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ - { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ - { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ - { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ - { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ - { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ - { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ - { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ - { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ - { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ - { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ - { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ - { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ - { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ - { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ - { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ - { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ - { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ - { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ - { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ - { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ - { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ - { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ - { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ - - { {0xe1,0x14,0},{0xe1,0xf0,0x14,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ - { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ - { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ - { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ - { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ - { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ - { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ - { {0xe0,0x5A,0},{0xe0,0xF0,0x5A,0} }, { {0xe0,0x14,0},{0xe0,0xF0,0x14,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ - { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ - { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ - { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { {0xe0,0x4A,0},{0xe0,0xF0,0x4A,0} }, { { 0},{ 0} }, { {0xe0,0x7C,0},{0xe0,0xF0,0x7C,0} }, /*134*/ - { {0xe0,0x11,0},{0xe0,0xF0,0x11,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ - { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ - { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ - { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { {0xe0,0x6C,0},{0xe0,0xF0,0x6C,0} }, /*144*/ - { {0xe0,0x75,0},{0xe0,0xF0,0x75,0} }, { {0xe0,0x7D,0},{0xe0,0xF0,0x7D,0} }, { { 0},{ 0} }, { {0xe0,0x6B,0},{0xe0,0xF0,0x6B,0} }, /*148*/ - { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { {0xe0,0x74,0},{0xe0,0xF0,0x74,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { {0xe0,0x69,0},{0xe0,0xF0,0x69,0} }, /*14c*/ - { {0xe0,0x72,0},{0xe0,0xF0,0x72,0} }, { {0xe0,0x7A,0},{0xe0,0xF0,0x7A,0} }, { {0xe0,0x70,0},{0xe0,0xF0,0x70,0} }, { {0xe0,0x71,0},{0xe0,0xF0,0x71,0} }, /*150*/ - { { 0},{ 0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ - { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { {0xe0,0x1F,0},{0xe0,0xF0,0x1F,0} }, /*158*/ - { {0xe0,0x27,0},{0xe0,0xF0,0x27,0} }, { {0xe0,0x2F,0},{0xe0,0xF0,0x2F,0} }, { {0xe0,0x37,0},{0xe0,0xF0,0x37,0} }, { {0xe0,0x3F,0},{0xe0,0xF0,0x3F,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { {0xe0,0x5E,0},{0xe0,0xF0,0x5E,0} }, /*160*/ - { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ - { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ - { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ - { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ - { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ - { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ - // clang-format on -}; - -static const scancode scancode_set3[512] = { - // clang-format off - { { 0},{ 0} }, { { 0x08,0},{ 0xf0,0x08,0} }, { { 0x16,0},{ 0xf0,0x16,0} }, { { 0x1E,0},{ 0xf0,0x1E,0} }, /*000*/ - { { 0x26,0},{ 0xf0,0x26,0} }, { { 0x25,0},{ 0xf0,0x25,0} }, { { 0x2E,0},{ 0xf0,0x2E,0} }, { { 0x36,0},{ 0xf0,0x36,0} }, /*004*/ - { { 0x3D,0},{ 0xf0,0x3D,0} }, { { 0x3E,0},{ 0xf0,0x3E,0} }, { { 0x46,0},{ 0xf0,0x46,0} }, { { 0x45,0},{ 0xf0,0x45,0} }, /*008*/ - { { 0x4E,0},{ 0xf0,0x4E,0} }, { { 0x55,0},{ 0xf0,0x55,0} }, { { 0x66,0},{ 0xf0,0x66,0} }, { { 0x0D,0},{ 0xf0,0x0D,0} }, /*00c*/ - { { 0x15,0},{ 0xf0,0x15,0} }, { { 0x1D,0},{ 0xf0,0x1D,0} }, { { 0x24,0},{ 0xf0,0x24,0} }, { { 0x2D,0},{ 0xf0,0x2D,0} }, /*010*/ - { { 0x2C,0},{ 0xf0,0x2C,0} }, { { 0x35,0},{ 0xf0,0x35,0} }, { { 0x3C,0},{ 0xf0,0x3C,0} }, { { 0x43,0},{ 0xf0,0x43,0} }, /*014*/ - { { 0x44,0},{ 0xf0,0x44,0} }, { { 0x4D,0},{ 0xf0,0x4D,0} }, { { 0x54,0},{ 0xf0,0x54,0} }, { { 0x5B,0},{ 0xf0,0x5B,0} }, /*018*/ - { { 0x5A,0},{ 0xf0,0x5A,0} }, { { 0x11,0},{ 0xf0,0x11,0} }, { { 0x1C,0},{ 0xf0,0x1C,0} }, { { 0x1B,0},{ 0xf0,0x1B,0} }, /*01c*/ - { { 0x23,0},{ 0xf0,0x23,0} }, { { 0x2B,0},{ 0xf0,0x2B,0} }, { { 0x34,0},{ 0xf0,0x34,0} }, { { 0x33,0},{ 0xf0,0x33,0} }, /*020*/ - { { 0x3B,0},{ 0xf0,0x3B,0} }, { { 0x42,0},{ 0xf0,0x42,0} }, { { 0x4B,0},{ 0xf0,0x4B,0} }, { { 0x4C,0},{ 0xf0,0x4C,0} }, /*024*/ - { { 0x52,0},{ 0xf0,0x52,0} }, { { 0x0E,0},{ 0xf0,0x0E,0} }, { { 0x12,0},{ 0xf0,0x12,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, /*028*/ - { { 0x1A,0},{ 0xf0,0x1A,0} }, { { 0x22,0},{ 0xf0,0x22,0} }, { { 0x21,0},{ 0xf0,0x21,0} }, { { 0x2A,0},{ 0xf0,0x2A,0} }, /*02c*/ - { { 0x32,0},{ 0xf0,0x32,0} }, { { 0x31,0},{ 0xf0,0x31,0} }, { { 0x3A,0},{ 0xf0,0x3A,0} }, { { 0x41,0},{ 0xf0,0x41,0} }, /*030*/ - { { 0x49,0},{ 0xf0,0x49,0} }, { { 0x4A,0},{ 0xf0,0x4A,0} }, { { 0x59,0},{ 0xf0,0x59,0} }, { { 0x7E,0},{ 0xf0,0x7E,0} }, /*034*/ - { { 0x19,0},{ 0xf0,0x19,0} }, { { 0x29,0},{ 0xf0,0x29,0} }, { { 0x14,0},{ 0xf0,0x14,0} }, { { 0x07,0},{ 0xf0,0x07,0} }, /*038*/ - { { 0x0F,0},{ 0xf0,0x0F,0} }, { { 0x17,0},{ 0xf0,0x17,0} }, { { 0x1F,0},{ 0xf0,0x1F,0} }, { { 0x27,0},{ 0xf0,0x27,0} }, /*03c*/ - { { 0x2F,0},{ 0xf0,0x2F,0} }, { { 0x37,0},{ 0xf0,0x37,0} }, { { 0x3F,0},{ 0xf0,0x3F,0} }, { { 0x47,0},{ 0xf0,0x47,0} }, /*040*/ - { { 0x4F,0},{ 0xf0,0x4F,0} }, { { 0x76,0},{ 0xf0,0x76,0} }, { { 0x5F,0},{ 0xf0,0x5F,0} }, { { 0x6C,0},{ 0xf0,0x6C,0} }, /*044*/ - { { 0x75,0},{ 0xf0,0x75,0} }, { { 0x7D,0},{ 0xf0,0x7D,0} }, { { 0x84,0},{ 0xf0,0x84,0} }, { { 0x6B,0},{ 0xf0,0x6B,0} }, /*048*/ - { { 0x73,0},{ 0xf0,0x73,0} }, { { 0x74,0},{ 0xf0,0x74,0} }, { { 0x7C,0},{ 0xf0,0x7C,0} }, { { 0x69,0},{ 0xf0,0x69,0} }, /*04c*/ - { { 0x72,0},{ 0xf0,0x72,0} }, { { 0x7A,0},{ 0xf0,0x7A,0} }, { { 0x70,0},{ 0xf0,0x70,0} }, { { 0x71,0},{ 0xf0,0x71,0} }, /*050*/ - { { 0x57,0},{ 0xf0,0x57,0} }, { { 0x60,0},{ 0xf0,0x60,0} }, { { 0},{ 0} }, { { 0x56,0},{ 0xf0,0x56,0} }, /*054*/ - { { 0x5E,0},{ 0xf0,0x5E,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*058*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*05c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*060*/ - { { 0},{ 0} }, { { 0x10,0},{ 0xf0,0x10,0} }, { { 0x18,0},{ 0xf0,0x18,0} }, { { 0x20,0},{ 0xf0,0x20,0} }, /*064*/ - { { 0x28,0},{ 0xf0,0x28,0} }, { { 0x30,0},{ 0xf0,0x30,0} }, { { 0x38,0},{ 0xf0,0x38,0} }, { { 0x40,0},{ 0xf0,0x40,0} }, /*068*/ - { { 0x48,0},{ 0xf0,0x48,0} }, { { 0x50,0},{ 0xf0,0x50,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*06c*/ - { { 0x87,0},{ 0xf0,0x87,0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0x51,0},{ 0xf0,0x51,0} }, /*070*/ - { { 0x53,0},{ 0xf0,0x53,0} }, { { 0x5C,0},{ 0xf0,0x5C,0} }, { { 0},{ 0} }, { { 0x62,0},{ 0xf0,0x62,0} }, /*074*/ - { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x85,0} }, /*078*/ - { { 0x68,0},{ 0xf0,0x68,0} }, { { 0x13,0},{ 0xf0,0x13,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*07c*/ - - { { 0x80,0},{ 0xf0,0x80,0} }, { { 0x81,0},{ 0xf0,0x81,0} }, { { 0x82,0},{ 0xf0,0x82,0} }, { { 0},{ 0} }, /*080*/ - { { 0},{ 0} }, { { 0x85,0},{ 0xf0,0x54,0} }, { { 0x86,0},{ 0xf0,0x86,0} }, { { 0x87,0},{ 0xf0,0x87,0} }, /*084*/ - { { 0x88,0},{ 0xf0,0x88,0} }, { { 0x89,0},{ 0xf0,0x89,0} }, { { 0x8a,0},{ 0xf0,0x8a,0} }, { { 0x8b,0},{ 0xf0,0x8b,0} }, /*088*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0x8e,0},{ 0xf0,0x8e,0} }, { { 0x8f,0},{ 0xf0,0x8f,0} }, /*08c*/ - { { 0x90,0},{ 0xf0,0x90,0} }, { { 0x91,0},{ 0xf0,0x91,0} }, { { 0x92,0},{ 0xf0,0x92,0} }, { { 0x93,0},{ 0xf0,0x93,0} }, /*090*/ - { { 0x94,0},{ 0xf0,0x94,0} }, { { 0x95,0},{ 0xf0,0x95,0} }, { { 0x96,0},{ 0xf0,0x96,0} }, { { 0x97,0},{ 0xf0,0x97,0} }, /*094*/ - { { 0x98,0},{ 0xf0,0x98,0} }, { { 0x99,0},{ 0xf0,0x99,0} }, { { 0x9a,0},{ 0xf0,0x9a,0} }, { { 0x9b,0},{ 0xf0,0x9b,0} }, /*098*/ - { { 0x9c,0},{ 0xf0,0x9c,0} }, { { 0x9d,0},{ 0xf0,0x9d,0} }, { { 0x9e,0},{ 0xf0,0x9e,0} }, { { 0x9f,0},{ 0xf0,0x9f,0} }, /*09c*/ - { { 0xa0,0},{ 0xf0,0xa0,0} }, { { 0xa1,0},{ 0xf0,0xa1,0} }, { { 0xa2,0},{ 0xf0,0xa2,0} }, { { 0xa3,0},{ 0xf0,0xa3,0} }, /*0a0*/ - { { 0xa4,0},{ 0xf0,0xa4,0} }, { { 0xa5,0},{ 0xf0,0xa5,0} }, { { 0xa6,0},{ 0xf0,0xa6,0} }, { { 0xa7,0},{ 0xf0,0xa7,0} }, /*0a4*/ - { { 0xa8,0},{ 0xf0,0xa8,0} }, { { 0xa9,0},{ 0xf0,0xa9,0} }, { { 0xaa,0},{ 0xf0,0xaa,0} }, { { 0xab,0},{ 0xf0,0xab,0} }, /*0a8*/ - { { 0xac,0},{ 0xf0,0xac,0} }, { { 0xad,0},{ 0xf0,0xad,0} }, { { 0xae,0},{ 0xf0,0xae,0} }, { { 0xaf,0},{ 0xf0,0xaf,0} }, /*0ac*/ - { { 0xb0,0},{ 0xf0,0xb0,0} }, { { 0xb1,0},{ 0xf0,0xb1,0} }, { { 0xb2,0},{ 0xf0,0xb2,0} }, { { 0xb3,0},{ 0xf0,0xb3,0} }, /*0b0*/ - { { 0xb4,0},{ 0xf0,0xb4,0} }, { { 0xb5,0},{ 0xf0,0xb5,0} }, { { 0xb6,0},{ 0xf0,0xb6,0} }, { { 0xb7,0},{ 0xf0,0xb7,0} }, /*0b4*/ - { { 0xb8,0},{ 0xf0,0xb8,0} }, { { 0xb9,0},{ 0xf0,0xb9,0} }, { { 0xba,0},{ 0xf0,0xba,0} }, { { 0xbb,0},{ 0xf0,0xbb,0} }, /*0b8*/ - { { 0xbc,0},{ 0xf0,0xbc,0} }, { { 0xbd,0},{ 0xf0,0xbd,0} }, { { 0xbe,0},{ 0xf0,0xbe,0} }, { { 0xbf,0},{ 0xf0,0xbf,0} }, /*0bc*/ - { { 0xc0,0},{ 0xf0,0xc0,0} }, { { 0xc1,0},{ 0xf0,0xc1,0} }, { { 0xc2,0},{ 0xf0,0xc2,0} }, { { 0xc3,0},{ 0xf0,0xc3,0} }, /*0c0*/ - { { 0xc4,0},{ 0xf0,0xc4,0} }, { { 0xc5,0},{ 0xf0,0xc5,0} }, { { 0xc6,0},{ 0xf0,0xc6,0} }, { { 0xc7,0},{ 0xf0,0xc7,0} }, /*0c4*/ - { { 0xc8,0},{ 0xf0,0xc8,0} }, { { 0xc9,0},{ 0xf0,0xc9,0} }, { { 0xca,0},{ 0xf0,0xca,0} }, { { 0xcb,0},{ 0xf0,0xcb,0} }, /*0c8*/ - { { 0xcc,0},{ 0xf0,0xcc,0} }, { { 0xcd,0},{ 0xf0,0xcd,0} }, { { 0xce,0},{ 0xf0,0xce,0} }, { { 0xcf,0},{ 0xf0,0xcf,0} }, /*0cc*/ - { { 0xd0,0},{ 0xf0,0xd0,0} }, { { 0xd1,0},{ 0xf0,0xd0,0} }, { { 0xd2,0},{ 0xf0,0xd2,0} }, { { 0xd3,0},{ 0xf0,0xd3,0} }, /*0d0*/ - { { 0xd4,0},{ 0xf0,0xd4,0} }, { { 0xd5,0},{ 0xf0,0xd5,0} }, { { 0xd6,0},{ 0xf0,0xd6,0} }, { { 0xd7,0},{ 0xf0,0xd7,0} }, /*0d4*/ - { { 0xd8,0},{ 0xf0,0xd8,0} }, { { 0xd9,0},{ 0xf0,0xd9,0} }, { { 0xda,0},{ 0xf0,0xda,0} }, { { 0xdb,0},{ 0xf0,0xdb,0} }, /*0d8*/ - { { 0xdc,0},{ 0xf0,0xdc,0} }, { { 0xdd,0},{ 0xf0,0xdd,0} }, { { 0xde,0},{ 0xf0,0xde,0} }, { { 0xdf,0},{ 0xf0,0xdf,0} }, /*0dc*/ - { { 0xe0,0},{ 0xf0,0xe0,0} }, { { 0xe1,0},{ 0xf0,0xe1,0} }, { { 0xe2,0},{ 0xf0,0xe2,0} }, { { 0xe3,0},{ 0xf0,0xe3,0} }, /*0e0*/ - { { 0xe4,0},{ 0xf0,0xe4,0} }, { { 0xe5,0},{ 0xf0,0xe5,0} }, { { 0xe6,0},{ 0xf0,0xe6,0} }, { { 0xe7,0},{ 0xf0,0xe7,0} }, /*0e4*/ - { { 0xe8,0},{ 0xf0,0xe8,0} }, { { 0xe9,0},{ 0xf0,0xe9,0} }, { { 0xea,0},{ 0xf0,0xea,0} }, { { 0xeb,0},{ 0xf0,0xeb,0} }, /*0e8*/ - { { 0xec,0},{ 0xf0,0xec,0} }, { { 0xed,0},{ 0xf0,0xed,0} }, { { 0xee,0},{ 0xf0,0xee,0} }, { { 0xef,0},{ 0xf0,0xef,0} }, /*0ec*/ - { { 0},{ 0} }, { { 0xf1,0},{ 0xf0,0xf1,0} }, { { 0xf2,0},{ 0xf0,0xf2,0} }, { { 0xf3,0},{ 0xf0,0xf3,0} }, /*0f0*/ - { { 0xf4,0},{ 0xf0,0xf4,0} }, { { 0xf5,0},{ 0xf0,0xf5,0} }, { { 0xf6,0},{ 0xf0,0xf6,0} }, { { 0xf7,0},{ 0xf0,0xf7,0} }, /*0f4*/ - { { 0xf8,0},{ 0xf0,0xf8,0} }, { { 0xf9,0},{ 0xf0,0xf9,0} }, { { 0xfa,0},{ 0xf0,0xfa,0} }, { { 0xfb,0},{ 0xf0,0xfb,0} }, /*0f8*/ - { { 0xfc,0},{ 0xf0,0xfc,0} }, { { 0xfd,0},{ 0xf0,0xfd,0} }, { { 0xfe,0},{ 0xf0,0xfe,0} }, { { 0xff,0},{ 0xf0,0xff,0} }, /*0fc*/ - - { { 0x62,0},{ 0xF0,0x62,0} }, { {0xe0,0x76,0},{0xe0,0xF0,0x76,0} }, { {0xe0,0x16,0},{0xe0,0xF0,0x16,0} }, { {0xe0,0x1E,0},{0xe0,0xF0,0x1E,0} }, /*100*/ - { {0xe0,0x26,0},{0xe0,0xF0,0x26,0} }, { {0xe0,0x25,0},{0xe0,0xF0,0x25,0} }, { {0xe0,0x2E,0},{0xe0,0xF0,0x2E,0} }, { {0xe0,0x36,0},{0xe0,0xF0,0x36,0} }, /*104*/ - { {0xe0,0x3D,0},{0xe0,0xF0,0x3D,0} }, { {0xe0,0x3E,0},{0xe0,0xF0,0x3E,0} }, { {0xe0,0x46,0},{0xe0,0xF0,0x46,0} }, { {0xe0,0x45,0},{0xe0,0xF0,0x45,0} }, /*108*/ - { {0xe0,0x4E,0},{0xe0,0xF0,0x4E,0} }, { { 0},{ 0} }, { {0xe0,0x66,0},{0xe0,0xF0,0x66,0} }, { {0xe0,0x0D,0},{0xe0,0xF0,0x0D,0} }, /*10c*/ - { {0xe0,0x15,0},{0xe0,0xF0,0x15,0} }, { {0xe0,0x1D,0},{0xe0,0xF0,0x1D,0} }, { {0xe0,0x24,0},{0xe0,0xF0,0x24,0} }, { {0xe0,0x2D,0},{0xe0,0xF0,0x2D,0} }, /*110*/ - { {0xe0,0x2C,0},{0xe0,0xF0,0x2C,0} }, { {0xe0,0x35,0},{0xe0,0xF0,0x35,0} }, { {0xe0,0x3C,0},{0xe0,0xF0,0x3C,0} }, { {0xe0,0x43,0},{0xe0,0xF0,0x43,0} }, /*114*/ - { {0xe0,0x44,0},{0xe0,0xF0,0x44,0} }, { {0xe0,0x4D,0},{0xe0,0xF0,0x4D,0} }, { {0xe0,0x54,0},{0xe0,0xF0,0x54,0} }, { {0xe0,0x5B,0},{0xe0,0xF0,0x5B,0} }, /*118*/ - { { 0x79,0},{ 0xf0,0x79,0} }, { { 0x58,0},{ 0xf0,0x58,0} }, { {0xe0,0x1C,0},{0xe0,0xF0,0x1C,0} }, { {0xe0,0x1B,0},{0xe0,0xF0,0x1B,0} }, /*11c*/ - { {0xe0,0x23,0},{0xe0,0xF0,0x23,0} }, { {0xe0,0x2B,0},{0xe0,0xF0,0x2B,0} }, { {0xe0,0x34,0},{0xe0,0xF0,0x34,0} }, { {0xe0,0x33,0},{0xe0,0xF0,0x33,0} }, /*120*/ - { {0xe0,0x3B,0},{0xe0,0xF0,0x3B,0} }, { {0xe0,0x42,0},{0xe0,0xF0,0x42,0} }, { {0xe0,0x4B,0},{0xe0,0xF0,0x4B,0} }, { { 0},{ 0} }, /*124*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*128*/ - { {0xe0,0x1A,0},{0xe0,0xF0,0x1A,0} }, { {0xe0,0x22,0},{0xe0,0xF0,0x22,0} }, { {0xe0,0x21,0},{0xe0,0xF0,0x21,0} }, { {0xe0,0x2A,0},{0xe0,0xF0,0x2A,0} }, /*12c*/ - { {0xe0,0x32,0},{0xe0,0xF0,0x32,0} }, { {0xe0,0x31,0},{0xe0,0xF0,0x31,0} }, { {0xe0,0x3A,0},{0xe0,0xF0,0x3A,0} }, { { 0},{ 0} }, /*130*/ - { {0xe0,0x49,0},{0xe0,0xF0,0x49,0} }, { { 0x77,0},{ 0xf0,0x77,0} }, { { 0},{ 0} }, { { 0x57,0},{ 0xf0,0x57,0} }, /*134*/ - { { 0x39,0},{ 0xf0,0x39,0} }, { { 0},{ 0} }, { {0xe0,0x58,0},{0xe0,0xF0,0x58,0} }, { {0xe0,0x05,0},{0xe0,0xF0,0x05,0} }, /*138*/ - { {0xe0,0x06,0},{0xe0,0xF0,0x06,0} }, { {0xe0,0x04,0},{0xe0,0xF0,0x04,0} }, { {0xe0,0x0C,0},{0xe0,0xF0,0x0C,0} }, { {0xe0,0x03,0},{0xe0,0xF0,0x03,0} }, /*13c*/ - { {0xe0,0x0B,0},{0xe0,0xF0,0x0B,0} }, { {0xe0,0x02,0},{0xe0,0xF0,0x02,0} }, { {0xe0,0x0A,0},{0xe0,0xF0,0x0A,0} }, { {0xe0,0x01,0},{0xe0,0xF0,0x01,0} }, /*140*/ - { {0xe0,0x09,0},{0xe0,0xF0,0x09,0} }, { { 0},{ 0} }, { {0xe0,0x7E,0},{0xe0,0xF0,0x7E,0} }, { { 0x6E,0},{ 0xf0,0x6E,0} }, /*144*/ - { { 0x63,0},{ 0xf0,0x63,0} }, { { 0x6F,0},{ 0xf0,0x6F,0} }, { { 0},{ 0} }, { { 0x61,0},{ 0xf0,0x61,0} }, /*148*/ - { {0xe0,0x73,0},{0xe0,0xF0,0x73,0} }, { { 0x6A,0},{ 0xf0,0x6A,0} }, { {0xe0,0x79,0},{0xe0,0xF0,0x79,0} }, { { 0x65,0},{ 0xf0,0x65,0} }, /*14c*/ - { { 0x60,0},{ 0xf0,0x60,0} }, { { 0x6D,0},{ 0xf0,0x6D,0} }, { { 0x67,0},{ 0xf0,0x67,0} }, { { 0x64,0},{ 0xf0,0x64,0} }, /*150*/ - { { 0xd4,0},{ 0xf0,0xD4,0} }, { {0xe0,0x60,0},{0xe0,0xF0,0x60,0} }, { { 0},{ 0} }, { {0xe0,0x78,0},{0xe0,0xF0,0x78,0} }, /*154*/ - { {0xe0,0x07,0},{0xe0,0xF0,0x07,0} }, { {0xe0,0x0F,0},{0xe0,0xF0,0x0F,0} }, { {0xe0,0x17,0},{0xe0,0xF0,0x17,0} }, { { 0x8B,0},{ 0xf0,0x8B,0} }, /*158*/ - { { 0x8C,0},{ 0xf0,0x8C,0} }, { { 0x8D,0},{ 0xf0,0x8D,0} }, { { 0},{ 0} }, { { 0x7F,0},{ 0xf0,0x7F,0} }, /*15c*/ - { { 0},{ 0} }, { {0xe0,0x4F,0},{0xe0,0xF0,0x4F,0} }, { {0xe0,0x56,0},{0xe0,0xF0,0x56,0} }, { { 0},{ 0} }, /*160*/ - { {0xe0,0x08,0},{0xe0,0xF0,0x08,0} }, { {0xe0,0x10,0},{0xe0,0xF0,0x10,0} }, { {0xe0,0x18,0},{0xe0,0xF0,0x18,0} }, { {0xe0,0x20,0},{0xe0,0xF0,0x20,0} }, /*164*/ - { {0xe0,0x28,0},{0xe0,0xF0,0x28,0} }, { {0xe0,0x30,0},{0xe0,0xF0,0x30,0} }, { {0xe0,0x38,0},{0xe0,0xF0,0x38,0} }, { {0xe0,0x40,0},{0xe0,0xF0,0x40,0} }, /*168*/ - { {0xe0,0x48,0},{0xe0,0xF0,0x48,0} }, { {0xe0,0x50,0},{0xe0,0xF0,0x50,0} }, { {0xe0,0x57,0},{0xe0,0xF0,0x57,0} }, { { 0},{ 0} }, /*16c*/ - { {0xe0,0x13,0},{0xe0,0xF0,0x13,0} }, { {0xe0,0x19,0},{0xe0,0xF0,0x19,0} }, { {0xe0,0x39,0},{0xe0,0xF0,0x39,0} }, { {0xe0,0x51,0},{0xe0,0xF0,0x51,0} }, /*170*/ - { {0xe0,0x53,0},{0xe0,0xF0,0x53,0} }, { {0xe0,0x5C,0},{0xe0,0xF0,0x5C,0} }, { { 0},{ 0} }, { {0xe0,0x62,0},{0xe0,0xF0,0x62,0} }, /*174*/ - { {0xe0,0x63,0},{0xe0,0xF0,0x63,0} }, { {0xe0,0x64,0},{0xe0,0xF0,0x64,0} }, { {0xe0,0x65,0},{0xe0,0xF0,0x65,0} }, { {0xe0,0x67,0},{0xe0,0xF0,0x67,0} }, /*178*/ - { {0xe0,0x68,0},{0xe0,0xF0,0x68,0} }, { {0xe0,0x6A,0},{0xe0,0xF0,0x6A,0} }, { {0xe0,0x6D,0},{0xe0,0xF0,0x6D,0} }, { {0xe0,0x6E,0},{0xe0,0xF0,0x6E,0} }, /*17c*/ - - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*180*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*184*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*188*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*18c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*190*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*194*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*198*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*19c*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1a8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1ac*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1c8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1cc*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1d8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1dc*/ - { { 0},{ 0} }, { {0xe0,0xe1,0},{0xe0,0xF0,0xE1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1e8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xee,0},{0xe0,0xF0,0xEE,0} }, { { 0},{ 0} }, /*1ec*/ - { { 0},{ 0} }, { {0xe0,0xf1,0},{0xe0,0xF0,0xF1,0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f0*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f4*/ - { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, { { 0},{ 0} }, /*1f8*/ - { { 0},{ 0} }, { { 0},{ 0} }, { {0xe0,0xfe,0},{0xe0,0xF0,0xFE,0} }, { {0xe0,0xff,0},{0xe0,0xF0,0xFF,0} } /*1fc*/ - // clang-format on -}; - -// #define ENABLE_KEYBOARD_AT_LOG 1 -#ifdef ENABLE_KEYBOARD_AT_LOG -int keyboard_at_do_log = ENABLE_KEYBOARD_AT_LOG; - -static void -kbd_log(const char *fmt, ...) -{ - va_list ap; - - if (keyboard_at_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define kbd_log(fmt, ...) -#endif - -static void -set_scancode_map(atkbd_t *dev) -{ - switch (keyboard_mode) { - case 1: - default: - keyboard_set_table(scancode_set1); - break; - case 2: - keyboard_set_table(scancode_set2); - break; - - case 3: - keyboard_set_table(scancode_set3); - break; - } -} - -static void -kbc_queue_reset(atkbd_t *dev, uint8_t channel) -{ - switch (channel) { - case 1: - dev->key_queue_start = dev->key_queue_end = 0; - memset(dev->key_queue, 0x00, sizeof(dev->key_queue)); - /* FALLTHROUGH */ - case 4: - dev->key_cmd_queue_start = dev->key_cmd_queue_end = 0; - memset(dev->key_cmd_queue, 0x00, sizeof(dev->key_cmd_queue)); - break; - - case 2: - dev->mouse_queue_start = dev->mouse_queue_end = 0; - memset(dev->mouse_queue, 0x00, sizeof(dev->mouse_queue)); - /* FALLTHROUGH */ - case 3: - dev->mouse_cmd_queue_start = dev->mouse_cmd_queue_end = 0; - memset(dev->mouse_cmd_queue, 0x00, sizeof(dev->mouse_cmd_queue)); - break; - - case 0: - default: - dev->key_ctrl_queue_start = dev->key_ctrl_queue_end = 0; - memset(dev->key_ctrl_queue, 0x00, sizeof(dev->key_ctrl_queue)); - } -} - -static void -kbc_queue_add(atkbd_t *dev, uint8_t val, uint8_t channel) -{ - switch (channel) { - case 4: - kbd_log("ATkbc: dev->key_cmd_queue[%02X] = %02X;\n", dev->key_cmd_queue_end, val); - dev->key_cmd_queue[dev->key_cmd_queue_end] = val; - dev->key_cmd_queue_end = (dev->key_cmd_queue_end + 1) & 0xf; - break; - case 3: - kbd_log("ATkbc: dev->mouse_cmd_queue[%02X] = %02X;\n", dev->mouse_cmd_queue_end, val); - dev->mouse_cmd_queue[dev->mouse_cmd_queue_end] = val; - dev->mouse_cmd_queue_end = (dev->mouse_cmd_queue_end + 1) & 0xf; - break; - case 2: - kbd_log("ATkbc: dev->mouse_queue[%02X] = %02X;\n", dev->mouse_queue_end, val); - dev->mouse_queue[dev->mouse_queue_end] = val; - dev->mouse_queue_end = (dev->mouse_queue_end + 1) & 0xf; - break; - case 1: - kbd_log("ATkbc: dev->key_queue[%02X] = %02X;\n", dev->key_queue_end, val); - dev->key_queue[dev->key_queue_end] = val; - dev->key_queue_end = (dev->key_queue_end + 1) & 0xf; - break; - case 0: - default: - kbd_log("ATkbc: dev->key_ctrl_queue[%02X] = %02X;\n", dev->key_ctrl_queue_end, val); - dev->key_ctrl_queue[dev->key_ctrl_queue_end] = val; - dev->key_ctrl_queue_end = (dev->key_ctrl_queue_end + 1) & 0x3f; - break; - } -} - -static int -kbc_translate(atkbd_t *dev, uint8_t val) -{ - int xt_mode = (dev->mem[0x20] & 0x20) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF); - int translate = (dev->mem[0x20] & 0x40) || xt_mode || ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2); - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - int ret = - 1; - - /* Allow for scan code translation. */ - if (translate && (val == 0xf0)) { - kbd_log("ATkbd: translate is on, F0 prefix detected\n"); - dev->sc_or = 0x80; - return ret; - } - - /* Skip break code if translated make code has bit 7 set. */ - if (translate && (dev->sc_or == 0x80) && (nont_to_t[val] & 0x80)) { - kbd_log("ATkbd: translate is on, skipping scan code: %02X (original: F0 %02X)\n", nont_to_t[val], val); - dev->sc_or = 0; - return ret; - } - - /* Test for T3100E 'Fn' key (Right Alt / Right Ctrl) */ - if ((dev != NULL) && (kbc_ven == KBC_VEN_TOSHIBA) && - (keyboard_recv(0x138) || keyboard_recv(0x11d))) switch (val) { - case 0x4f: - t3100e_notify_set(0x01); - break; /* End */ - case 0x50: - t3100e_notify_set(0x02); - break; /* Down */ - case 0x51: - t3100e_notify_set(0x03); - break; /* PgDn */ - case 0x52: - t3100e_notify_set(0x04); - break; /* Ins */ - case 0x53: - t3100e_notify_set(0x05); - break; /* Del */ - case 0x54: - t3100e_notify_set(0x06); - break; /* SysRQ */ - case 0x45: - t3100e_notify_set(0x07); - break; /* NumLock */ - case 0x46: - t3100e_notify_set(0x08); - break; /* ScrLock */ - case 0x47: - t3100e_notify_set(0x09); - break; /* Home */ - case 0x48: - t3100e_notify_set(0x0a); - break; /* Up */ - case 0x49: - t3100e_notify_set(0x0b); - break; /* PgUp */ - case 0x4a: - t3100e_notify_set(0x0c); - break; /* Keypad - */ - case 0x4b: - t3100e_notify_set(0x0d); - break; /* Left */ - case 0x4c: - t3100e_notify_set(0x0e); - break; /* KP 5 */ - case 0x4d: - t3100e_notify_set(0x0f); - break; /* Right */ - } - - kbd_log("ATkbd: translate is %s, ", translate ? "on" : "off"); -#ifdef ENABLE_KEYBOARD_AT_LOG - kbd_log("scan code: "); - if (translate) { - kbd_log("%02X (original: ", (nont_to_t[val] | dev->sc_or)); - if (dev->sc_or == 0x80) - kbd_log("F0 "); - kbd_log("%02X)\n", val); - } else - kbd_log("%02X\n", val); -#endif - - ret = translate ? (nont_to_t[val] | dev->sc_or) : val; - - if (dev->sc_or == 0x80) - dev->sc_or = 0; - - return ret; -} - -static void -add_to_kbc_queue_front(atkbd_t *dev, uint8_t val, uint8_t channel, uint8_t stat_hi) -{ - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - int temp = (channel == 1) ? kbc_translate(dev, val) : val; - - if (temp == -1) - return; - - if ((kbc_ven == KBC_VEN_AMI) || (kbc_ven == KBC_VEN_TG) || - (kbc_ven == KBC_VEN_TG_GREEN) || ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - stat_hi |= ((dev->input_port & 0x80) ? 0x10 : 0x00); - else - stat_hi |= 0x10; - - kbd_log("ATkbc: Adding %02X to front on channel %i...\n", temp, channel); - dev->status = (dev->status & ~0xf0) | STAT_OFULL | stat_hi; - - /* WARNING: On PS/2, all IRQ's are level-triggered, but the IBM PS/2 KBC firmware is explicitly - written to pulse its P2 IRQ bits, so they should be kept as as edge-triggered here. */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - if (channel >= 2) { - dev->status |= STAT_MFULL; - - if (dev->mem[0x20] & 0x02) - picint_common(1 << 12, 0, 1); - picint_common(1 << 1, 0, 0); - } else { - if (dev->mem[0x20] & 0x01) - picint_common(1 << 1, 0, 1); - picint_common(1 << 12, 0, 0); - } - } else if (dev->mem[0x20] & 0x01) - picintlevel(1 << 1); /* AT KBC: IRQ 1 is level-triggered because it is tied to OBF. */ - - dev->out = temp; -} - -static void -add_data_kbd_cmd_queue(atkbd_t *dev, uint8_t val) -{ - if (dev->key_cmd_queue_end >= 16) { - kbd_log("ATkbc: Unable to add to queue, dev->key_cmd_queue_end >= 16\n"); - return; - } - kbd_log("ATkbc: dev->key_cmd_queue[%02X] = %02X;\n", dev->key_cmd_queue_end, val); - kbc_queue_add(dev, val, 4); - dev->kbd_last_scan_code = val; -} - -static void -add_data_kbd_queue(atkbd_t *dev, uint8_t val) -{ - if (!keyboard_scan || (dev->key_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !keyboard_scan, (dev->key_queue_end >= 16)); - return; - } - kbd_log("ATkbc: key_queue[%02X] = %02X;\n", dev->key_queue_end, val); - kbc_queue_add(dev, val, 1); - dev->kbd_last_scan_code = val; -} - -static void -add_data_kbd_front(atkbd_t *dev, uint8_t val) -{ - add_data_kbd_cmd_queue(dev, val); -} - -static void kbd_process_cmd(void *priv); -static void kbc_process_cmd(void *priv); - -static void -set_enable_kbd(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xef; - dev->mem[0x20] |= (enable ? 0x00 : 0x10); -} - -static void -set_enable_mouse(atkbd_t *dev, uint8_t enable) -{ - dev->mem[0x20] &= 0xdf; - dev->mem[0x20] |= (enable ? 0x00 : 0x20); -} - -static void -kbc_ibf_process(atkbd_t *dev) -{ - /* IBF set, process both commands and data. */ - dev->status &= ~STAT_IFULL; - dev->kbc_state = KBC_STATE_MAIN_IBF; - if (dev->status & STAT_CD) - kbc_process_cmd(dev); - else { - set_enable_kbd(dev, 1); - dev->key_wantcmd = 1; - dev->key_dat = dev->ib; - dev->kbc_state = KBC_STATE_SEND_KBD; - } -} - -static void -kbc_scan_kbd_at(atkbd_t *dev) -{ - if (!(dev->mem[0x20] & 0x10)) { - /* Both OBF and IBF clear and keyboard is enabled. */ - /* XT mode. */ - if (dev->mem[0x20] & 0x20) { - if (dev->out_new != -1) { - add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); - dev->out_new = -1; - dev->kbc_state = KBC_STATE_MAIN_IBF; - } else if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - /* AT mode. */ - } else { - // dev->t = dev->mem[0x28]; - if (dev->mem[0x2e] != 0x00) { - // if (!(dev->t & 0x02)) - // return; - dev->mem[0x2e] = 0x00; - } - dev->output_port &= 0xbf; - if (dev->out_new != -1) { - /* In our case, we never have noise on the line, so we can simplify this. */ - /* Read data from the keyboard. */ - if (dev->mem[0x20] & 0x40) { - if ((dev->mem[0x20] & 0x08) || (dev->input_port & 0x80)) - add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); - dev->mem[0x2d] = (dev->out_new == 0xf0) ? 0x80 : 0x00; - } else - add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); - dev->out_new = -1; - dev->kbc_state = KBC_STATE_MAIN_IBF; - } - } - } -} - -static void write_output(atkbd_t *dev, uint8_t val); - -static void -kbc_poll_at(atkbd_t *dev) -{ - switch (dev->kbc_state) { - case KBC_STATE_RESET: - if (dev->status & STAT_IFULL) { - dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL; - if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) - kbc_process_cmd(dev); - } - break; - case KBC_STATE_MAIN_IBF: - default: - if (dev->status & STAT_OFULL) { - /* OBF set, wait until it is cleared but still process commands. */ - if ((dev->status & STAT_IFULL) && (dev->status & STAT_CD)) { - dev->status &= ~STAT_IFULL; - kbc_process_cmd(dev); - } - } else if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - else if (!(dev->mem[0x20] & 0x10)) - dev->kbc_state = KBC_STATE_MAIN_KBD; - break; - case KBC_STATE_MAIN_KBD: - case KBC_STATE_MAIN_BOTH: - if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - else { - (void) kbc_scan_kbd_at(dev); - dev->kbc_state = KBC_STATE_MAIN_IBF; - } - break; - case KBC_STATE_KBC_OUT: - /* Keyboard controller command want to output multiple bytes. */ - if (dev->status & STAT_IFULL) { - /* Data from host aborts dumping. */ - dev->kbc_state = KBC_STATE_MAIN_IBF; - kbc_ibf_process(dev); - } - /* Do not continue dumping until OBF is clear. */ - if (!(dev->status & STAT_OFULL)) { - kbd_log("ATkbc: %02X coming from channel 0\n", dev->key_ctrl_queue[dev->key_ctrl_queue_start]); - add_to_kbc_queue_front(dev, dev->key_ctrl_queue[dev->key_ctrl_queue_start], 0, 0x00); - dev->key_ctrl_queue_start = (dev->key_ctrl_queue_start + 1) & 0x3f; - if (dev->key_ctrl_queue_start == dev->key_ctrl_queue_end) - dev->kbc_state = KBC_STATE_MAIN_IBF; - } - break; - case KBC_STATE_KBC_PARAM: - /* Keyboard controller command wants data, wait for said data. */ - if (dev->status & STAT_IFULL) { - /* Command written, abort current command. */ - if (dev->status & STAT_CD) - dev->kbc_state = KBC_STATE_MAIN_IBF; - - dev->status &= ~STAT_IFULL; - kbc_process_cmd(dev); - } - break; - case KBC_STATE_SEND_KBD: - if (!dev->key_wantcmd) - dev->kbc_state = KBC_STATE_SCAN_KBD; - break; - case KBC_STATE_SCAN_KBD: - kbc_scan_kbd_at(dev); - break; - } -} - -/* - Correct Procedure: - 1. Controller asks the device (keyboard or mouse) for a byte. - 2. The device, unless it's in the reset or command states, sees if there's anything to give it, - and if yes, begins the transfer. - 3. The controller checks if there is a transfer, if yes, transfers the byte and sends it to the host, - otherwise, checks the next device, or if there is no device left to check, checks if IBF is full - and if yes, processes it. - */ -static int -kbc_scan_kbd_ps2(atkbd_t *dev) -{ - if (dev->out_new != -1) { - kbd_log("ATkbc: %02X coming from channel 1\n", dev->out_new & 0xff); - add_to_kbc_queue_front(dev, dev->out_new, 1, 0x00); - dev->out_new = -1; - dev->kbc_state = KBC_STATE_MAIN_IBF; - return 1; - } - - return 0; -} - -static int -kbc_scan_aux_ps2(atkbd_t *dev) -{ - if (dev->out_new_mouse != -1) { - kbd_log("ATkbc: %02X coming from channel 2\n", dev->out_new_mouse & 0xff); - add_to_kbc_queue_front(dev, dev->out_new_mouse, 2, 0x00); - dev->out_new_mouse = -1; - dev->kbc_state = KBC_STATE_MAIN_IBF; - return 1; - } - - return 0; -} - -static void -kbc_poll_ps2(atkbd_t *dev) -{ - switch (dev->kbc_state) { - case KBC_STATE_RESET: - if (dev->status & STAT_IFULL) { - dev->status = ((dev->status & 0x0f) | 0x10) & ~STAT_IFULL; - if ((dev->status & STAT_CD) && (dev->ib == 0xaa)) - kbc_process_cmd(dev); - } - break; - case KBC_STATE_MAIN_IBF: - default: - if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - else if (!(dev->status & STAT_OFULL)) { - if (dev->mem[0x20] & 0x20) { - if (!(dev->mem[0x20] & 0x10)) { - dev->output_port &= 0xbf; - dev->kbc_state = KBC_STATE_MAIN_KBD; - } - } else { - dev->output_port &= 0xf7; - if (dev->mem[0x20] & 0x10) - dev->kbc_state = KBC_STATE_MAIN_MOUSE; - else { - dev->output_port &= 0xbf; - dev->kbc_state = KBC_STATE_MAIN_BOTH; - } - } - } - break; - case KBC_STATE_MAIN_KBD: - if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - else { - (void) kbc_scan_kbd_ps2(dev); - dev->kbc_state = KBC_STATE_MAIN_IBF; - } - break; - case KBC_STATE_MAIN_MOUSE: - if (dev->status & STAT_IFULL) - kbc_ibf_process(dev); - else { - (void) kbc_scan_aux_ps2(dev); - dev->kbc_state = KBC_STATE_MAIN_IBF; - } - break; - case KBC_STATE_MAIN_BOTH: - if (kbc_scan_kbd_ps2(dev)) - dev->kbc_state = KBC_STATE_MAIN_IBF; - else - dev->kbc_state = KBC_STATE_MAIN_MOUSE; - break; - case KBC_STATE_KBC_OUT: - /* Keyboard controller command want to output multiple bytes. */ - if (dev->status & STAT_IFULL) { - /* Data from host aborts dumping. */ - dev->kbc_state = KBC_STATE_MAIN_IBF; - kbc_ibf_process(dev); - } - /* Do not continue dumping until OBF is clear. */ - if (!(dev->status & STAT_OFULL)) { - kbd_log("ATkbc: %02X coming from channel 0\n", dev->out_new & 0xff); - add_to_kbc_queue_front(dev, dev->key_ctrl_queue[dev->key_ctrl_queue_start], 0, 0x00); - dev->key_ctrl_queue_start = (dev->key_ctrl_queue_start + 1) & 0x3f; - if (dev->key_ctrl_queue_start == dev->key_ctrl_queue_end) - dev->kbc_state = KBC_STATE_MAIN_IBF; - } - break; - case KBC_STATE_KBC_PARAM: - /* Keyboard controller command wants data, wait for said data. */ - if (dev->status & STAT_IFULL) { - /* Command written, abort current command. */ - if (dev->status & STAT_CD) - dev->kbc_state = KBC_STATE_MAIN_IBF; - - dev->status &= ~STAT_IFULL; - kbc_process_cmd(dev); - } - break; - case KBC_STATE_SEND_KBD: - if (!dev->key_wantcmd) - dev->kbc_state = KBC_STATE_SCAN_KBD; - break; - case KBC_STATE_SCAN_KBD: - (void) kbc_scan_kbd_ps2(dev); - break; - case KBC_STATE_SEND_MOUSE: - if (!dev->mouse_wantcmd) - dev->kbc_state = KBC_STATE_SCAN_MOUSE; - break; - case KBC_STATE_SCAN_MOUSE: - (void) kbc_scan_aux_ps2(dev); - break; - } -} - -static void -kbc_poll_kbd(atkbd_t *dev) -{ - switch (dev->kbd_state) { - case DEV_STATE_MAIN_1: - /* Process the command if needed and then return to main loop #2. */ - if (dev->key_wantcmd) { - kbd_log("ATkbc: Processing keyboard command %02X...\n", dev->key_dat); - kbc_queue_reset(dev, 4); - // dev->out_new = -1; - kbd_process_cmd(dev); - dev->key_wantcmd = 0; - } else - dev->kbd_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 (keyboard_scan && (dev->out_new == -1) && (dev->key_queue_start != dev->key_queue_end)) { - kbd_log("ATkbc: %02X (DATA) on channel 1\n", dev->key_queue[dev->key_queue_start]); - dev->out_new = dev->key_queue[dev->key_queue_start]; - dev->key_queue_start = (dev->key_queue_start + 1) & 0xf; - } - if (!keyboard_scan || dev->key_wantcmd) - dev->kbd_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->key_wantcmd) { - kbd_log("ATkbc: Processing keyboard command %02X...\n", dev->key_dat); - kbc_queue_reset(dev, 4); - kbd_process_cmd(dev); - dev->key_wantcmd = 0; - break; - } - /* FALLTHROUGH */ - case DEV_STATE_MAIN_WANT_IN: - /* Output command response and then wait for host data. */ - if ((dev->out_new == -1) && (dev->key_cmd_queue_start != dev->key_cmd_queue_end)) { - kbd_log("ATkbc: %02X (CMD ) on channel 1\n", dev->key_cmd_queue[dev->key_cmd_queue_start]); - dev->out_new = dev->key_cmd_queue[dev->key_cmd_queue_start]; - dev->key_cmd_queue_start = (dev->key_cmd_queue_start + 1) & 0xf; - } - if (dev->key_cmd_queue_start == dev->key_cmd_queue_end) - dev->kbd_state = (dev->kbd_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->key_wantcmd) { - kbd_log("ATkbc: Processing keyboard command %02X parameter %02X...\n", dev->key_command, dev->key_dat); - kbc_queue_reset(dev, 4); - // dev->out_new = -1; - kbd_process_cmd(dev); - dev->key_wantcmd = 0; - } - break; - } -} - -static void -kbc_poll_aux(atkbd_t *dev) -{ - switch (dev->mouse_state) { - case DEV_STATE_MAIN_1: - /* Process the command if needed and then return to main loop #2. */ - if (dev->mouse_wantcmd) { - kbd_log("ATkbc: Processing mouse command %02X...\n", dev->mouse_dat); - kbc_queue_reset(dev, 3); - // dev->out_new_mouse = -1; - dev->mouse_state = DEV_STATE_MAIN_OUT; - mouse_write(dev->mouse_dat, mouse_p); - if ((dev->mouse_dat == 0xe8) || (dev->mouse_dat == 0xf3)) - dev->mouse_state = DEV_STATE_MAIN_WANT_IN; - dev->mouse_wantcmd = 0; - } else - dev->mouse_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 (mouse_scan && (dev->out_new_mouse == -1) && (dev->mouse_queue_start != dev->mouse_queue_end)) { - kbd_log("ATkbc: %02X (DATA) on channel 2\n", dev->mouse_queue[dev->mouse_queue_start]); - dev->out_new_mouse = dev->mouse_queue[dev->mouse_queue_start]; - dev->mouse_queue_start = (dev->mouse_queue_start + 1) & 0xf; - } - if (!mouse_scan || dev->mouse_wantcmd) - dev->mouse_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->mouse_wantcmd) { - kbd_log("ATkbc: Processing mouse command %02X...\n", dev->mouse_dat); - kbc_queue_reset(dev, 3); - dev->mouse_state = DEV_STATE_MAIN_OUT; - mouse_write(dev->mouse_dat, mouse_p); - if ((dev->mouse_dat == 0xe8) || (dev->mouse_dat == 0xf3)) - dev->mouse_state = DEV_STATE_MAIN_WANT_IN; - dev->mouse_wantcmd = 0; - break; - } - /* FALLTHROUGH */ - case DEV_STATE_MAIN_WANT_IN: - /* Output command response and then wait for host data. */ - if ((dev->out_new_mouse == -1) && (dev->mouse_cmd_queue_start != dev->mouse_cmd_queue_end)) { - kbd_log("ATkbc: %02X (CMD ) on channel 2\n", dev->mouse_cmd_queue[dev->mouse_cmd_queue_start]); - dev->out_new_mouse = dev->mouse_cmd_queue[dev->mouse_cmd_queue_start]; - dev->mouse_cmd_queue_start = (dev->mouse_cmd_queue_start + 1) & 0xf; - } - if (dev->mouse_cmd_queue_start == dev->mouse_cmd_queue_end) - dev->mouse_state = (dev->mouse_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->mouse_wantcmd) { - kbd_log("ATkbc: Processing mouse command parameter %02X...\n", dev->mouse_dat); - kbc_queue_reset(dev, 3); - // dev->out_new_mouse = -1; - dev->mouse_state = DEV_STATE_MAIN_OUT; - mouse_write(dev->mouse_dat, mouse_p); - dev->mouse_wantcmd = 0; - } - break; - } -} - -/* TODO: State machines for controller, keyboard, and mouse. */ -static void -kbd_poll(void *priv) -{ - atkbd_t *dev = (atkbd_t *) priv; - - timer_advance_u64(&dev->send_delay_timer, (100ULL * TIMER_USEC)); - - /* TODO: Use a fuction pointer for this (also needed to the AMI KBC mode switching) - and implement the password security state. */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - kbc_poll_ps2(dev); - else - kbc_poll_at(dev); - - kbc_poll_kbd(dev); - - if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && mouse_write) - kbc_poll_aux(dev); - - // if (kbc_ports[0] && kbc_ports[0]>-priv) - // kbc_ports[0]>poll(kbc_ports[0]>-priv); - - // if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && kbc_ports[1] && kbc_ports[1]>-priv) - // kbc_ports[1]>poll(kbc_ports[1]>-priv); -} - -static void -add_data_vals(atkbd_t *dev, uint8_t *val, uint8_t len) -{ - int i; - - for (i = 0; i < len; i++) - add_data_kbd_queue(dev, val[i]); -} - -static void -add_data_kbd(uint16_t val) -{ - atkbd_t *dev = SavedKbd; - uint8_t fake_shift[4]; - uint8_t num_lock = 0, shift_states = 0; - - keyboard_get_states(NULL, &num_lock, NULL); - shift_states = keyboard_get_shift() & STATE_SHIFT_MASK; - - switch (val) { - case FAKE_LSHIFT_ON: - kbd_log("fake left shift on, scan code: "); - if (num_lock) { - if (shift_states) { - kbd_log("N/A (one or both shifts on)\n"); - break; - } else { - /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ - switch (keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; - fake_shift[1] = 0x2a; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; - fake_shift[1] = 0x12; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - } else { - if (shift_states & STATE_LSHIFT) { - /* Num lock off and left shift pressed. */ - switch (keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; - fake_shift[1] = 0xaa; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; - fake_shift[1] = 0xf0; - fake_shift[2] = 0x12; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - if (shift_states & STATE_RSHIFT) { - /* Num lock off and right shift pressed. */ - switch (keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; - fake_shift[1] = 0xb6; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; - fake_shift[1] = 0xf0; - fake_shift[2] = 0x59; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - kbd_log(shift_states ? "" : "N/A (both shifts off)\n"); - } - break; - - case FAKE_LSHIFT_OFF: - kbd_log("fake left shift on, scan code: "); - if (num_lock) { - if (shift_states) { - kbd_log("N/A (one or both shifts on)\n"); - break; - } else { - /* Num lock on and no shifts are pressed, send non-inverted fake shift. */ - switch (keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; - fake_shift[1] = 0xaa; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; - fake_shift[1] = 0xf0; - fake_shift[2] = 0x12; - add_data_vals(dev, fake_shift, 3); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - } else { - if (shift_states & STATE_LSHIFT) { - /* Num lock off and left shift pressed. */ - switch (keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; - fake_shift[1] = 0x2a; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; - fake_shift[1] = 0x12; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - if (shift_states & STATE_RSHIFT) { - /* Num lock off and right shift pressed. */ - switch (keyboard_mode & 0x02) { - case 1: - fake_shift[0] = 0xe0; - fake_shift[1] = 0x36; - add_data_vals(dev, fake_shift, 2); - break; - - case 2: - fake_shift[0] = 0xe0; - fake_shift[1] = 0x59; - add_data_vals(dev, fake_shift, 2); - break; - - default: - kbd_log("N/A (scan code set %i)\n", keyboard_mode & 0x02); - break; - } - } - kbd_log(shift_states ? "" : "N/A (both shifts off)\n"); - } - break; - - default: - add_data_kbd_queue(dev, val); - break; - } -} - -static void -write_output(atkbd_t *dev, uint8_t val) -{ - uint8_t old = dev->output_port; - kbd_log("ATkbc: write output port: %02X (old: %02X)\n", val, dev->output_port); - - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - -#if 0 - /* PS/2: Handle IRQ's. */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - /* IRQ 12 */ - picint_common(1 << 12, 0, val & 0x20); - - /* IRQ 1 */ - picint_common(1 << 1, 0, val & 0x10); - } -#endif - - /* AT, PS/2: Handle A20. */ - if ((old ^ val) & 0x02) { /* A20 enable change */ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - - /* AT, PS/2: Handle reset. */ - /* 0 holds the CPU in the RESET state, 1 releases it. To simplify this, - we just do everything on release. */ - if ((old ^ val) & 0x01) { /*Reset*/ - if (!(val & 0x01)) { /* Pin 0 selected. */ - /* Pin 0 selected. */ - kbd_log("write_output(): Pulse reset!\n"); - if (machines[machine].flags & MACHINE_COREBOOT) { - /* The SeaBIOS hard reset code attempts a KBC reset if ACPI RESET_REG - is not available. However, the KBC reset is normally a soft reset, so - SeaBIOS gets caught in a soft reset loop as it tries to hard reset the - machine. Hack around this by making the KBC reset a hard reset only on - coreboot machines. */ - pc_reset_hard(); - } else { - softresetx86(); /*Pulse reset!*/ - cpu_set_edx(); - flushmmucache(); - if (kbc_ven == KBC_VEN_ALI) - smbase = 0x00030000; - } - } - } - - /* Do this here to avoid an infinite reset loop. */ - dev->output_port = val; -} - -static void -write_output_fast_a20(atkbd_t *dev, uint8_t val) -{ - uint8_t old = dev->output_port; - kbd_log("ATkbc: write output port in fast A20 mode: %02X (old: %02X)\n", val, dev->output_port); - - /* AT, PS/2: Handle A20. */ - if ((old ^ val) & 0x02) { /* A20 enable change */ - mem_a20_key = val & 0x02; - mem_a20_recalc(); - flushmmucache(); - } - - /* Do this here to avoid an infinite reset loop. */ - dev->output_port = val; -} - -static void -write_cmd(atkbd_t *dev, uint8_t val) -{ - kbd_log("ATkbc: write command byte: %02X (old: %02X)\n", val, dev->mem[0x20]); - - /* PS/2 type 2 keyboard controllers always force the XLAT bit to 0. */ - if ((dev->flags & KBC_TYPE_MASK) == KBC_TYPE_PS2_2) { - val &= ~CCB_TRANSLATE; - dev->mem[0x20] &= ~CCB_TRANSLATE; - } else if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - if (val & 0x10) - dev->mem[0x2e] = 0x01; - } - - kbd_log("ATkbc: keyboard interrupt is now %s\n", (val & 0x01) ? "enabled" : "disabled"); - - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - /* Update the output port to mirror the IBF and OBF bits, if active. */ - write_output(dev, (dev->output_port & 0x0f) | ((val & 0x03) << 4) | ((val & 0x20) ? 0xc0 : 0x00)); - } - - kbd_log("Command byte now: %02X (%02X)\n", dev->mem[0x20], val); - - dev->status = (dev->status & ~STAT_SYSFLAG) | (val & STAT_SYSFLAG); -} - -static void -pulse_output(atkbd_t *dev, uint8_t mask) -{ - if (mask != 0x0f) { - dev->old_output_port = dev->output_port & ~(0xf0 | mask); - kbd_log("pulse_output(): Output port now: %02X\n", dev->output_port & (0xf0 | mask)); - write_output(dev, dev->output_port & (0xf0 | mask)); - timer_set_delay_u64(&dev->pulse_cb, 6ULL * TIMER_USEC); - } -} - -static void -pulse_poll(void *priv) -{ - atkbd_t *dev = (atkbd_t *) priv; - - kbd_log("pulse_poll(): Output port now: %02X\n", dev->output_port | dev->old_output_port); - write_output(dev, dev->output_port | dev->old_output_port); -} - -static uint8_t -write64_generic(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - uint8_t current_drive, fixed_bits; - uint8_t kbc_ven = 0x0; - kbc_ven = dev->flags & KBC_VEN_MASK; - - switch (val) { - case 0xa4: /* check if password installed */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: check if password installed\n"); - add_to_kbc_queue_front(dev, 0xf1, 0, 0x00); - return 0; - } - break; - - case 0xa7: /* disable mouse port */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: disable mouse port\n"); - set_enable_mouse(dev, 0); - return 0; - } - break; - - case 0xa8: /*Enable mouse port*/ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: enable mouse port\n"); - set_enable_mouse(dev, 1); - return 0; - } - break; - - case 0xa9: /*Test mouse port*/ - kbd_log("ATkbc: test mouse port\n"); - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); /* no error, this is testing the channel 2 interface */ - return 0; - } - break; - - case 0xaf: /* read keyboard version */ - kbd_log("ATkbc: read keyboard version\n"); - add_to_kbc_queue_front(dev, 0x42, 0, 0x00); - return 0; - - case 0xc0: /* read input port */ - kbd_log("ATkbc: read input port\n"); - fixed_bits = 4; - /* The SMM handlers of Intel AMI Pentium BIOS'es expect bit 6 to be set. */ - if (kbc_ven == KBC_VEN_INTEL_AMI) - fixed_bits |= 0x40; - if (kbc_ven == KBC_VEN_IBM_PS1) { - current_drive = fdc_get_current_drive(); - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits | (fdd_is_525(current_drive) ? 0x40 : 0x00), - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc) | (fdd_is_525(current_drive) ? 0x40 : 0x00); - } else if (kbc_ven == KBC_VEN_NCR) { - /* switch settings - * bit 7: keyboard disable - * bit 6: display type (0 color, 1 mono) - * bit 5: power-on default speed (0 high, 1 low) - * bit 4: sense RAM size (0 unsupported, 1 512k on system board) - * bit 3: coprocessor detect - * bit 2: unused - * bit 1: high/auto speed - * bit 0: dma mode - */ - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits | (video_is_mda() ? 0x40 : 0x00) | (hasfpu ? 0x08 : 0x00)) & 0xdf, - 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc); - } else { - if ((kbc_ven == KBC_VEN_TG) || (kbc_ven == KBC_VEN_TG_GREEN)) { - /* Bit 3, 2: - 1, 1: TriGem logo; - 1, 0: Garbled logo; - 0, 1: Epson logo; - 0, 0: Generic AMI logo. */ - if (dev->pci) - fixed_bits |= 8; - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); - } else if (((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) && ((dev->flags & KBC_VEN_MASK) != KBC_VEN_INTEL_AMI)) -#if 0 - add_to_kbc_queue_front(dev, (dev->input_port | fixed_bits) & - (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0xeb : 0xef), 0, 0x00); -#else - add_to_kbc_queue_front(dev, ((dev->input_port | fixed_bits) & 0xf0) | (((dev->flags & KBC_VEN_MASK) == KBC_VEN_ACER) ? 0x08 : 0x0c), 0, 0x00); -#endif - else - add_to_kbc_queue_front(dev, dev->input_port | fixed_bits, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc); - } - return 0; - - case 0xd3: /* write mouse output buffer */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: write mouse output buffer\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - return 0; - } - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - return 0; - - case 0xf0 ... 0xff: - kbd_log("ATkbc: pulse %01X\n", val & 0x0f); - pulse_output(dev, val & 0x0f); - return 0; - } - - kbd_log("ATkbc: bad command %02X\n", val); - return 1; -} - -static uint8_t -write60_ami(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - - switch (dev->command) { - /* 0x40 - 0x5F are aliases for 0x60-0x7F */ - case 0x40 ... 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->mem[(dev->command & 0x1f) + 0x20] = val; - if (dev->command == 0x60) - write_cmd(dev, val); - return 0; - - case 0xa5: /* get extended controller RAM */ - kbd_log("ATkbc: AMI - get extended controller RAM\n"); - add_to_kbc_queue_front(dev, dev->mem[val], 0, 0x00); - return 0; - - case 0xaf: /* set extended controller RAM */ - kbd_log("ATkbc: AMI - set extended controller RAM\n"); - if (dev->secr_phase == 1) { - dev->mem_addr = val; - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - dev->secr_phase = 2; - } else if (dev->secr_phase == 2) { - dev->mem[dev->mem_addr] = val; - dev->secr_phase = 0; - } - return 0; - - case 0xc1: - kbd_log("ATkbc: AMI MegaKey - write %02X to input port\n", val); - dev->input_port = val; - return 0; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->ami_flags = val; - return 0; - } - - return 1; -} - -static uint8_t -write64_ami(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - switch (val) { - case 0x00 ... 0x1f: - kbd_log("ATkbc: AMI - alias read from %08X\n", val); - add_to_kbc_queue_front(dev, dev->mem[val + 0x20], 0, 0x00); - return 0; - - case 0x40 ... 0x5f: - kbd_log("ATkbc: AMI - alias write to %08X\n", dev->command); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - return 0; - - case 0xa0: /* copyright message */ - kbc_queue_add(dev, 0x28, 0); - kbc_queue_add(dev, 0x00, 0); - dev->kbc_state = KBC_STATE_KBC_OUT; - break; - - case 0xa1: /* get controller version */ - kbd_log("ATkbc: AMI - get controller version\n"); - if ((kbc_ven == KBC_VEN_TG) || (kbc_ven == KBC_VEN_TG_GREEN)) - add_to_kbc_queue_front(dev, 'Z', 0, 0x00); - else if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - if (kbc_ven == KBC_VEN_ALI) - add_to_kbc_queue_front(dev, 'F', 0, 0x00); - else if ((dev->flags & KBC_VEN_MASK) == KBC_VEN_INTEL_AMI) - add_to_kbc_queue_front(dev, '5', 0, 0x00); - else if (cpu_64bitbus) - add_to_kbc_queue_front(dev, 'R', 0, 0x00); - else if (is486) - add_to_kbc_queue_front(dev, 'P', 0, 0x00); - else - add_to_kbc_queue_front(dev, 'H', 0, 0x00); - } else if (is386 && !is486) { - if (cpu_16bitbus) - add_to_kbc_queue_front(dev, 'D', 0, 0x00); - else - add_to_kbc_queue_front(dev, 'B', 0, 0x00); - } else if (!is386) - add_to_kbc_queue_front(dev, '8', 0, 0x00); - else - add_to_kbc_queue_front(dev, 'F', 0, 0x00); - return 0; - - case 0xa2: /* clear keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - clear KBC lines P22 and P23\n"); - write_output(dev, dev->output_port & 0xf3); - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - } - break; - - case 0xa3: /* set keyboard controller lines P22/P23 */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - set KBC lines P22 and P23\n"); - write_output(dev, dev->output_port | 0x0c); - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - } - break; - - case 0xa4: /* write clock = low */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - write clock = low\n"); - dev->ami_stat &= 0xfe; - return 0; - } - break; - - case 0xa5: /* write clock = high */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - write clock = high\n"); - dev->ami_stat |= 0x01; - } else { - kbd_log("ATkbc: get extended controller RAM\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - } - return 0; - - case 0xa6: /* read clock */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - read clock\n"); - add_to_kbc_queue_front(dev, (dev->ami_stat & 1) ? 0xff : 0x00, 0, 0x00); - return 0; - } - break; - - case 0xa7: /* write cache bad */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - write cache bad\n"); - dev->ami_stat &= 0xfd; - return 0; - } - break; - - case 0xa8: /* write cache good */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - write cache good\n"); - dev->ami_stat |= 0x02; - return 0; - } - break; - - case 0xa9: /* read cache */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: AMI - read cache\n"); - add_to_kbc_queue_front(dev, (dev->ami_stat & 2) ? 0xff : 0x00, 0, 0x00); - return 0; - } - break; - - case 0xaf: /* set extended controller RAM */ - if (kbc_ven == KBC_VEN_ALI) { - kbd_log("ATkbc: Award/ALi/VIA keyboard controller revision\n"); - add_to_kbc_queue_front(dev, 0x43, 0, 0x00); - } else { - kbd_log("ATkbc: set extended controller RAM\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - dev->secr_phase = 1; - } - return 0; - - case 0xb0 ... 0xb3: - /* set KBC lines P10-P13 (input port bits 0-3) low */ - kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) low\n"); - if (!(dev->flags & DEVICE_PCI) || (val > 0xb1)) - dev->input_port &= ~(1 << (val & 0x03)); - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - - case 0xb4: case 0xb5: - /* set KBC lines P22-P23 (output port bits 2-3) low */ - kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) low\n"); - if (!(dev->flags & DEVICE_PCI)) - write_output(dev, dev->output_port & ~(4 << (val & 0x01))); - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - - case 0xb8 ... 0xbb: - /* set KBC lines P10-P13 (input port bits 0-3) high */ - kbd_log("ATkbc: set KBC lines P10-P13 (input port bits 0-3) high\n"); - if (!(dev->flags & DEVICE_PCI) || (val > 0xb9)) { - dev->input_port |= (1 << (val & 0x03)); - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - } - return 0; - - case 0xbc: case 0xbd: - /* set KBC lines P22-P23 (output port bits 2-3) high */ - kbd_log("ATkbc: set KBC lines P22-P23 (output port bits 2-3) high\n"); - if (!(dev->flags & DEVICE_PCI)) - write_output(dev, dev->output_port | (4 << (val & 0x01))); - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - - case 0xc1: /* write input port */ - kbd_log("ATkbc: AMI MegaKey - write input port\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - return 0; - - case 0xc4: - /* set KBC line P14 low */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) low\n"); - dev->input_port &= 0xef; - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - case 0xc5: - /* set KBC line P15 low */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) low\n"); - dev->input_port &= 0xdf; - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - - case 0xc8: - /* - * unblock KBC lines P22/P23 - * (allow command D1 to change bits 2/3 of the output port) - */ - kbd_log("ATkbc: AMI - unblock KBC lines P22 and P23\n"); - dev->ami_flags &= 0xfb; - return 0; - - case 0xc9: - /* - * block KBC lines P22/P23 - * (disallow command D1 from changing bits 2/3 of the port) - */ - kbd_log("ATkbc: AMI - block KBC lines P22 and P23\n"); - dev->ami_flags |= 0x04; - return 0; - - case 0xcc: - /* set KBC line P14 high */ - kbd_log("ATkbc: set KBC line P14 (input port bit 4) high\n"); - dev->input_port |= 0x10; - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - case 0xcd: - /* set KBC line P15 high */ - kbd_log("ATkbc: set KBC line P15 (input port bit 5) high\n"); - dev->input_port |= 0x20; - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - - case 0xef: /* ??? - sent by AMI486 */ - kbd_log("ATkbc: ??? - sent by AMI486\n"); - return 0; - } - - return write64_generic(dev, val); -} - -static uint8_t -write64_ibm_mca(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - - switch (val) { - case 0xc1: /*Copy bits 0 to 3 of input port to status bits 4 to 7*/ - kbd_log("ATkbc: copy bits 0 to 3 of input port to status bits 4 to 7\n"); - dev->status &= 0x0f; - dev->status |= ((((dev->input_port & 0xfc) | 0x84) & 0x0f) << 4); - return 0; - - case 0xc2: /*Copy bits 4 to 7 of input port to status bits 4 to 7*/ - kbd_log("ATkbc: copy bits 4 to 7 of input port to status bits 4 to 7\n"); - dev->status &= 0x0f; - dev->status |= (((dev->input_port & 0xfc) | 0x84) & 0xf0); - return 0; - - case 0xaf: - kbd_log("ATkbc: bad KBC command AF\n"); - return 1; - - case 0xf0 ... 0xff: - kbd_log("ATkbc: pulse: %01X\n", (val & 0x03) | 0x0c); - pulse_output(dev, (val & 0x03) | 0x0c); - return 0; - } - - return write64_generic(dev, val); -} - -static uint8_t -write60_quadtel(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - - switch (dev->command) { - case 0xcf: /*??? - sent by MegaPC BIOS*/ - kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - return 0; - } - - return 1; -} - -static uint8_t -write64_olivetti(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - - switch (val) { - case 0x80: /* Olivetti-specific command */ - /* - * bit 7: bus expansion board present (M300) / keyboard unlocked (M290) - * bits 4-6: ??? - * bit 3: fast ram check (if inactive keyboard works erratically) - * bit 2: keyboard fuse present - * bits 0-1: ??? - */ - add_to_kbc_queue_front(dev, (0x0c | ((is386) ? 0x00 : 0x80)) & 0xdf, 0, 0x00); - dev->input_port = ((dev->input_port + 1) & 3) | (dev->input_port & 0xfc); - return 0; - } - - return write64_generic(dev, val); -} - -static uint8_t -write64_quadtel(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - - switch (val) { - case 0xaf: - kbd_log("ATkbc: bad KBC command AF\n"); - return 1; - - case 0xcf: /*??? - sent by MegaPC BIOS*/ - kbd_log("ATkbc: ??? - sent by MegaPC BIOS\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - return 0; - } - - return write64_generic(dev, val); -} - -static uint8_t -write60_toshiba(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - - switch (dev->command) { - case 0xb6: /* T3100e - set color/mono switch */ - kbd_log("ATkbc: T3100e - set color/mono switch\n"); - t3100e_mono_set(val); - return 0; - } - - return 1; -} - -static uint8_t -write64_toshiba(void *priv, uint8_t val) -{ - atkbd_t *dev = (atkbd_t *) priv; - - switch (val) { - case 0xaf: - kbd_log("ATkbc: bad KBC command AF\n"); - return 1; - - case 0xb0: /* T3100e: Turbo on */ - kbd_log("ATkbc: T3100e: Turbo on\n"); - t3100e_turbo_set(1); - return 0; - - case 0xb1: /* T3100e: Turbo off */ - kbd_log("ATkbc: T3100e: Turbo off\n"); - t3100e_turbo_set(0); - return 0; - - case 0xb2: /* T3100e: Select external display */ - kbd_log("ATkbc: T3100e: Select external display\n"); - t3100e_display_set(0x00); - return 0; - - case 0xb3: /* T3100e: Select internal display */ - kbd_log("ATkbc: T3100e: Select internal display\n"); - t3100e_display_set(0x01); - return 0; - - case 0xb4: /* T3100e: Get configuration / status */ - kbd_log("ATkbc: T3100e: Get configuration / status\n"); - add_to_kbc_queue_front(dev, t3100e_config_get(), 0, 0x00); - return 0; - - case 0xb5: /* T3100e: Get colour / mono byte */ - kbd_log("ATkbc: T3100e: Get colour / mono byte\n"); - add_to_kbc_queue_front(dev, t3100e_mono_get(), 0, 0x00); - return 0; - - case 0xb6: /* T3100e: Set colour / mono byte */ - kbd_log("ATkbc: T3100e: Set colour / mono byte\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - return 0; - - case 0xb7: /* T3100e: Emulate PS/2 keyboard */ - case 0xb8: /* T3100e: Emulate AT keyboard */ - dev->flags &= ~KBC_TYPE_MASK; - if (val == 0xb7) { - kbd_log("ATkbc: T3100e: Emulate PS/2 keyboard\n"); - dev->flags |= KBC_TYPE_PS2_NOREF; - } else { - kbd_log("ATkbc: T3100e: Emulate AT keyboard\n"); - dev->flags |= KBC_TYPE_ISA; - } - return 0; - - case 0xbb: /* T3100e: Read 'Fn' key. - Return it for right Ctrl and right Alt; on the real - T3100e, these keystrokes could only be generated - using 'Fn'. */ - kbd_log("ATkbc: T3100e: Read 'Fn' key\n"); - if (keyboard_recv(0xb8) || /* Right Alt */ - keyboard_recv(0x9d)) /* Right Ctrl */ - add_to_kbc_queue_front(dev, 0x04, 0, 0x00); - else - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - return 0; - - case 0xbc: /* T3100e: Reset Fn+Key notification */ - kbd_log("ATkbc: T3100e: Reset Fn+Key notification\n"); - t3100e_notify_set(0x00); - return 0; - - case 0xc0: /*Read input port*/ - kbd_log("ATkbc: read input port\n"); - - /* The T3100e returns all bits set except bit 6 which - * is set by t3100e_mono_set() */ - dev->input_port = (t3100e_mono_get() & 1) ? 0xff : 0xbf; - add_to_kbc_queue_front(dev, dev->input_port, 0, 0x00); - return 0; - } - - return write64_generic(dev, val); -} - -static void -kbd_key_reset(atkbd_t *dev, int do_fa) -{ - dev->out_new = -1; - kbc_queue_reset(dev, 1); - - dev->kbd_last_scan_code = 0x00; - - /* Set scan code set to 2. */ - keyboard_mode = 0x02; - set_scancode_map(dev); - - /* The BAT enables scanning. */ - keyboard_scan = 1; - - dev->sc_or = 0; - - if (do_fa) - add_data_kbd_front(dev, 0xfa); - add_data_kbd_front(dev, 0xaa); - - if (!do_fa) - dev->kbd_state = DEV_STATE_MAIN_OUT; -} - -static void -kbd_aux_reset(atkbd_t *dev, int do_fa) -{ - dev->out_new_mouse = -1; - kbc_queue_reset(dev, 2); - - /* The BAT enables scanning. */ - mouse_scan = 1; - - if (!do_fa) { - add_data_kbd_front(dev, 0xaa); - add_data_kbd_front(dev, 0x00); - - dev->mouse_state = DEV_STATE_MAIN_OUT; - } -} - -void -keyboard_at_mouse_reset(void) -{ - atkbd_t *dev = SavedKbd; - - kbd_aux_reset(dev, 1); -} - -static void -kbd_process_cmd(void *priv) -{ - atkbd_t *dev = (atkbd_t *) priv; - - dev->kbd_state = DEV_STATE_MAIN_OUT; - - if (dev->key_wantdata) { - dev->key_wantdata = 0; - - /* - * Several system BIOSes and OS device drivers - * mess up with this, and repeat the command - * code many times. Fun! - */ - if (dev->key_dat == dev->key_command) { - /* Respond NAK and ignore it. */ - add_data_kbd_front(dev, 0xfe); - dev->key_command = 0x00; - return; - } - - switch (dev->key_command) { - case 0xed: /* set/reset LEDs */ - add_data_kbd_front(dev, 0xfa); - kbd_log("ATkbd: set LEDs [%02x]\n", dev->key_dat); - break; - - case 0xf0: /* get/set scancode set */ - add_data_kbd_front(dev, 0xfa); - if (dev->key_dat == 0) { - kbd_log("Get scan code set: %02X\n", keyboard_mode); - add_data_kbd_front(dev, keyboard_mode); - } else { - if (dev->key_dat <= 3) { - keyboard_mode = dev->key_dat; - kbd_log("Scan code set now: %02X\n", keyboard_mode); - } - set_scancode_map(dev); - } - break; - - case 0xf3: /* set typematic rate/delay */ - add_data_kbd_front(dev, 0xfa); - break; - - default: - kbd_log("ATkbd: bad keyboard 0060 write %02X command %02X\n", dev->key_dat, dev->key_command); - add_data_kbd_front(dev, 0xfe); - break; - } - - /* Keyboard command is now done. */ - dev->key_command = 0x00; - } else { - /* No keyboard command in progress. */ - dev->key_command = 0x00; - - switch (dev->key_dat) { - case 0x00 ... 0x7f: - kbd_log("ATkbd: invalid command %02X\n", dev->key_dat); - add_data_kbd_front(dev, 0xfe); - break; - - case 0xed: /* set/reset LEDs */ - kbd_log("ATkbd: set/reset leds\n"); - add_data_kbd_front(dev, 0xfa); - - dev->key_wantdata = 1; - dev->kbd_state = DEV_STATE_MAIN_WANT_IN; - break; - - case 0xee: /* diagnostic echo */ - kbd_log("ATkbd: ECHO\n"); - add_data_kbd_front(dev, 0xee); - break; - - case 0xef: /* NOP (reserved for future use) */ - kbd_log("ATkbd: NOP\n"); - break; - - case 0xf0: /* get/set scan code set */ - kbd_log("ATkbd: scan code set\n"); - add_data_kbd_front(dev, 0xfa); - dev->key_wantdata = 1; - dev->kbd_state = DEV_STATE_MAIN_WANT_IN; - break; - - case 0xf2: /* read ID */ - kbd_log("ATkbd: read keyboard id\n"); - /* TODO: After keyboard type selection is implemented, make this - return the correct keyboard ID for the selected type. */ - add_data_kbd_front(dev, 0xfa); - add_data_kbd_front(dev, 0xab); - add_data_kbd_front(dev, 0x83); - break; - - case 0xf3: /* set typematic rate/delay */ - kbd_log("ATkbd: set typematic rate/delay\n"); - add_data_kbd_front(dev, 0xfa); - dev->key_wantdata = 1; - dev->kbd_state = DEV_STATE_MAIN_WANT_IN; - break; - - case 0xf4: /* enable keyboard */ - kbd_log("ATkbd: enable keyboard\n"); - add_data_kbd_front(dev, 0xfa); - keyboard_scan = 1; - break; - - case 0xf5: /* set defaults and disable keyboard */ - case 0xf6: /* set defaults */ - kbd_log("ATkbd: set defaults%s\n", (dev->key_dat == 0xf6) ? "" : " and disable keyboard"); - keyboard_scan = (dev->key_dat == 0xf6); - kbd_log("dev->key_dat = %02X, keyboard_scan = %i, dev->mem[0x20] = %02X\n", - dev->key_dat, keyboard_scan, dev->mem[0]); - add_data_kbd_front(dev, 0xfa); - - keyboard_set3_all_break = 0; - keyboard_set3_all_repeat = 0; - memset(keyboard_set3_flags, 0, 512); - keyboard_mode = 0x02; - set_scancode_map(dev); - break; - - case 0xf7: /* set all keys to repeat */ - kbd_log("ATkbd: set all keys to repeat\n"); - add_data_kbd_front(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf8: /* set all keys to give make/break codes */ - kbd_log("ATkbd: set all keys to give make/break codes\n"); - add_data_kbd_front(dev, 0xfa); - keyboard_set3_all_break = 1; - break; - - case 0xf9: /* set all keys to give make codes only */ - kbd_log("ATkbd: set all keys to give make codes only\n"); - add_data_kbd_front(dev, 0xfa); - keyboard_set3_all_break = 0; - break; - - case 0xfa: /* set all keys to repeat and give make/break codes */ - kbd_log("ATkbd: set all keys to repeat and give make/break codes\n"); - add_data_kbd_front(dev, 0xfa); - keyboard_set3_all_repeat = 1; - keyboard_set3_all_break = 1; - break; - - case 0xfe: /* resend last scan code */ - kbd_log("ATkbd: resend last scan code\n"); - add_data_kbd_front(dev, dev->kbd_last_scan_code); - break; - - case 0xff: /* reset */ - kbd_log("ATkbd: kbd reset\n"); - kbd_key_reset(dev, 1); - break; - - default: - kbd_log("ATkbd: bad keyboard command %02X\n", dev->key_dat); - add_data_kbd_front(dev, 0xfe); - } - - /* If command needs data, remember command. */ - if (dev->key_wantdata == 1) - dev->key_command = dev->key_dat; - } -} - -static void -kbc_process_cmd(void *priv) -{ - atkbd_t *dev = (atkbd_t *) priv; - int i = 0, bad = 1; - uint8_t mask, kbc_ven = dev->flags & KBC_VEN_MASK; - uint8_t cmd_ac_conv[16] = { 0x0b, 2, 3, 4, 5, 6, 7, 8, 9, 0x0a, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21 }; - - if (dev->status & STAT_CD) { - /* Controller command. */ - dev->want60 = 0; - dev->kbc_state = KBC_STATE_MAIN_IBF; - - /* Clear the keyboard controller queue. */ - kbc_queue_reset(dev, 0); - - switch (dev->ib) { - /* Read data from KBC memory. */ - case 0x20 ... 0x3f: - add_to_kbc_queue_front(dev, dev->mem[dev->ib], 0, 0x00); - break; - - /* Write data to KBC memory. */ - case 0x60 ... 0x7f: - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - break; - - case 0xaa: /* self-test */ - kbd_log("ATkbc: self-test\n"); - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - if (dev->kbc_state != KBC_STATE_RESET) { - kbd_log("ATkbc: self-test reinitialization\n"); - /* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */ - /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ - dev->input_port = dev->input_port & 0xff; - write_output(dev, 0x4b); - } - - dev->status = (dev->status & 0x0f) | 0x60; - - dev->mem[0x20] = 0x30; - dev->mem[0x21] = 0x01; - dev->mem[0x22] = 0x0b; - dev->mem[0x25] = 0x02; - dev->mem[0x27] = 0xf8; - dev->mem[0x28] = 0xce; - dev->mem[0x29] = 0x0b; - dev->mem[0x2a] = 0x10; - dev->mem[0x2b] = 0x20; - dev->mem[0x2c] = 0x15; - dev->mem[0x30] = 0x0b; - } else { - if (dev->kbc_state != KBC_STATE_RESET) { - kbd_log("ATkbc: self-test reinitialization\n"); - /* Yes, the firmware has an OR, but we need to make sure to keep any forcibly lowered bytes lowered. */ - /* TODO: Proper P1 implementation, with OR and AND flags in the machine table. */ - dev->input_port = dev->input_port & 0xff; - write_output(dev, 0xcf); - } - - dev->status = (dev->status & 0x0f) | 0x60; - - dev->mem[0x20] = 0x10; - dev->mem[0x21] = 0x01; - dev->mem[0x22] = 0x06; - dev->mem[0x25] = 0x01; - dev->mem[0x27] = 0xfb; - dev->mem[0x28] = 0xe0; - dev->mem[0x29] = 0x06; - dev->mem[0x2a] = 0x10; - dev->mem[0x2b] = 0x20; - dev->mem[0x2c] = 0x15; - } - - dev->out_new = dev->out_new_mouse = -1; - kbc_queue_reset(dev, 0); - - // dev->kbc_state = KBC_STATE_MAIN_IBF; - dev->kbc_state = KBC_STATE_KBC_OUT; - - // add_to_kbc_queue_front(dev, 0x55, 0, 0x00); - kbc_queue_add(dev, 0x55, 0); - break; - - case 0xab: /* interface test */ - kbd_log("ATkbc: interface test\n"); - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); /*no error*/ - break; - - case 0xac: /* diagnostic dump */ - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - kbd_log("ATkbc: diagnostic dump\n"); - dev->mem[0x30] = (dev->input_port & 0xf0) | 0x80; - dev->mem[0x31] = dev->output_port; - dev->mem[0x32] = 0x00; /* T0 and T1. */ - dev->mem[0x33] = 0x00; /* PSW - Program Status Word - always return 0x00 because we do not emulate this byte. */ - /* 20 bytes in high nibble in set 1, low nibble in set 1, set 1 space format = 60 bytes. */ - for (i = 0; i < 20; i++) { - kbc_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] >> 4], 0); - kbc_queue_add(dev, cmd_ac_conv[dev->mem[i + 0x20] & 0x0f], 0); - kbc_queue_add(dev, 0x39, 0); - } - dev->kbc_state = KBC_STATE_KBC_OUT; - } - break; - - case 0xad: /* disable keyboard */ - kbd_log("ATkbc: disable keyboard\n"); - set_enable_kbd(dev, 0); - break; - - case 0xae: /* enable keyboard */ - kbd_log("ATkbc: enable keyboard\n"); - set_enable_kbd(dev, 1); - break; - - case 0xc7: /* set port1 bits */ - kbd_log("ATkbc: Phoenix - set port1 bits\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - break; - - case 0xca: /* read keyboard mode */ - kbd_log("ATkbc: AMI - read keyboard mode\n"); - add_to_kbc_queue_front(dev, dev->ami_flags, 0, 0x00); - break; - - case 0xcb: /* set keyboard mode */ - kbd_log("ATkbc: AMI - set keyboard mode\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - break; - - case 0xd0: /* read output port */ - kbd_log("ATkbc: read output port\n"); - mask = 0xff; - if ((kbc_ven != KBC_VEN_OLIVETTI) && ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) && (dev->mem[0x20] & 0x10)) - mask &= 0xbf; - add_to_kbc_queue_front(dev, dev->output_port & mask, 0, 0x00); - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - break; - - case 0xd2: /* write keyboard output buffer */ - kbd_log("ATkbc: write keyboard output buffer\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - break; - - case 0xdd: /* disable A20 address line */ - case 0xdf: /* enable A20 address line */ - kbd_log("ATkbc: %sable A20\n", (dev->ib == 0xdd) ? "dis" : "en"); - write_output_fast_a20(dev, (dev->output_port & 0xfd) | (dev->ib & 0x02)); - break; - - case 0xe0: /* read test inputs */ - kbd_log("ATkbc: read test inputs\n"); - add_to_kbc_queue_front(dev, 0x00, 0, 0x00); - break; - - default: - /* - * Unrecognized controller command. - * - * If we have a vendor-specific handler, run - * that. Otherwise, or if that handler fails, - * log a bad command. - */ - if (dev->write64_ven) - bad = dev->write64_ven(dev, dev->ib); - - kbd_log(bad ? "ATkbc: bad controller command %02X\n" : "", dev->ib); - } - - /* If the command needs data, remember the command. */ - if (dev->want60) - dev->command = dev->ib; - } else if (dev->want60) { - /* Write data to controller. */ - dev->want60 = 0; - dev->kbc_state = KBC_STATE_MAIN_IBF; - - switch (dev->command) { - case 0x60 ... 0x7f: - dev->mem[(dev->command & 0x1f) + 0x20] = dev->ib; - if (dev->command == 0x60) - write_cmd(dev, dev->ib); - break; - - case 0xc7: /* set port1 bits */ - kbd_log("ATkbc: Phoenix - set port1 bits\n"); - dev->input_port |= dev->ib; - break; - - case 0xd1: /* write output port */ - kbd_log("ATkbc: write output port\n"); - /* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no), - discovered by reverse-engineering the AOpen Vi15G BIOS. */ - if (dev->ami_flags & 0x04) { - /* If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged. */ - dev->ib &= ~0x0c; - dev->ib |= (dev->output_port & 0x0c); - } - write_output(dev, dev->ib | 0x01); - break; - - case 0xd2: /* write to keyboard output buffer */ - kbd_log("ATkbc: write to keyboard output buffer\n"); - add_to_kbc_queue_front(dev, dev->ib, 0, 0x00); - break; - - case 0xd3: /* write to mouse output buffer */ - kbd_log("ATkbc: write to mouse output buffer\n"); - if (mouse_write && ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF)) - keyboard_at_adddata_mouse(dev->ib); - break; - - case 0xd4: /* write to mouse */ - kbd_log("ATkbc: write to mouse (%02X)\n", dev->ib); - - if (dev->ib == 0xbb) - break; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - set_enable_mouse(dev, 1); - if (mouse_write) { - dev->mouse_wantcmd = 1; - dev->mouse_dat = dev->ib; - dev->kbc_state = KBC_STATE_SEND_MOUSE; - } else - add_to_kbc_queue_front(dev, 0xfe, 2, 0x40); - } - break; - - default: - /* - * Run the vendor-specific handler - * if we have one. Otherwise, or if - * it returns an error, log a bad - * controller command. - */ - if (dev->write60_ven) - bad = dev->write60_ven(dev, dev->ib); - - if (bad) { - kbd_log("ATkbc: bad controller command %02x data %02x\n", dev->command, dev->ib); - } - } - } -} - -static void -kbd_write(uint16_t port, uint8_t val, void *priv) -{ - atkbd_t *dev = (atkbd_t *) priv; - - kbd_log((port == 0x61) ? "" : "[%04X:%08X] ATkbc: write(%04X) = %02X\n", CS, cpu_state.pc, port, val); - - switch (port) { - case 0x60: - dev->status &= ~STAT_CD; - if (dev->want60 && (dev->command == 0xd1)) { - kbd_log("ATkbc: write output port\n"); - - /* Fast A20 - ignore all other bits. */ - val = (val & 0x02) | (dev->output_port & 0xfd); - - /* Bit 2 of AMI flags is P22-P23 blocked (1 = yes, 0 = no), - discovered by reverse-engineering the AOpeN Vi15G BIOS. */ - if (dev->ami_flags & 0x04) { - /* If keyboard controller lines P22-P23 are blocked, - we force them to remain unchanged. */ - val &= ~0x0c; - val |= (dev->output_port & 0x0c); - } - - write_output_fast_a20(dev, val | 0x01); - - dev->want60 = 0; - dev->kbc_state = KBC_STATE_MAIN_IBF; - return; - } - break; - - case 0x64: - dev->status |= STAT_CD; - if (val == 0xd1) { - kbd_log("ATkbc: write output port\n"); - dev->want60 = 1; - dev->kbc_state = KBC_STATE_KBC_PARAM; - dev->command = 0xd1; - return; - } - break; - } - - dev->ib = val; - dev->status |= STAT_IFULL; -} - -static uint8_t -kbd_read(uint16_t port, void *priv) -{ - atkbd_t *dev = (atkbd_t *) priv; - uint8_t ret = 0xff; - - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) - cycles -= ISA_CYCLES(8); - - switch (port) { - case 0x60: - ret = dev->out; - dev->status &= ~STAT_OFULL; - /* TODO: IRQ is only tied to OBF on the AT KBC, on the PS/2 KBC, it is controlled by a bit the - output port (P2). - This also means that in AT mode, the IRQ is level-triggered. */ - if ((dev->flags & KBC_TYPE_MASK) < KBC_TYPE_PS2_NOREF) - picintc(1 << 1); - break; - - case 0x64: - ret = dev->status; - break; - - default: - kbd_log("ATkbc: read(%04x) invalid!\n",port); - break; - } - - kbd_log((port == 0x61) ? "" : "[%04X:%08X] ATkbc: read (%04X) = %02X\n", CS, cpu_state.pc, port, ret); - - return (ret); -} - -static void -kbd_reset(void *priv) -{ - atkbd_t *dev = (atkbd_t *) priv; - int i; - uint8_t kbc_ven = dev->flags & KBC_VEN_MASK; - - dev->status = STAT_UNLOCKED; - dev->mem[0x20] = 0x01; - dev->mem[0x20] |= CCB_TRANSLATE; - dev->secr_phase = 0; - dev->key_wantdata = 0; - - /* Set up the correct Video Type bits. */ - if (!is286 || (kbc_ven == KBC_VEN_ACER)) - dev->input_port = video_is_mda() ? 0xb0 : 0xf0; - else - dev->input_port = video_is_mda() ? 0xf0 : 0xb0; - kbd_log("ATkbc: input port = %02x\n", dev->input_port); - - /* Enable keyboard, disable mouse. */ - set_enable_kbd(dev, 0); - keyboard_scan = 0; - set_enable_mouse(dev, 0); - mouse_scan = 0; - - dev->out_new = dev->out_new_mouse = -1; - for (i = 0; i < 3; i++) - kbc_queue_reset(dev, i); - dev->kbd_last_scan_code = 0; - - dev->sc_or = 0; - - keyboard_mode = 0x02; - - memset(keyboard_set3_flags, 0, 512); - - set_scancode_map(dev); - - dev->ami_flags = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 0x01 : 0x00; - dev->ami_stat |= 0x02; - - dev->output_port = 0xcd; - if ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - write_output(dev, 0x4b); - } else { - /* The real thing writes CF and then AND's it with BF. */ - write_output(dev, 0x8f); - } - - /* Stage 1. */ - dev->status = (dev->status & 0x0f) | (dev->input_port & 0xf0); - - /* Reset the keyboard. */ - kbd_key_reset(dev, 0); - - /* Reset the mouse. */ - kbd_aux_reset(dev, 0); -} - -/* Reset the AT keyboard - this is needed for the PCI TRC and is done - until a better solution is found. */ -void -keyboard_at_reset(void) -{ - kbd_reset(SavedKbd); -} - -void -kbc_at_a20_reset(void) -{ - if (SavedKbd) { - SavedKbd->output_port = 0xcd; - if ((SavedKbd->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) { - write_output(SavedKbd, 0x4b); - } else { - /* The real thing writes CF and then AND's it with BF. */ - write_output(SavedKbd, 0x8f); - } - } -} - -static void -kbd_close(void *priv) -{ - atkbd_t *dev = (atkbd_t *) priv; - int i, max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 2 : 1; - - kbd_reset(dev); - - /* Stop timers. */ - timer_disable(&dev->send_delay_timer); - - keyboard_scan = 0; - keyboard_send = NULL; - - /* Disable the scancode maps. */ - keyboard_set_table(NULL); - - SavedKbd = NULL; - - for (i = 0; i < max_ports; i++) { - if (kbc_ports[i] != NULL) { - free(kbc_ports[i]); - kbc_ports[i] = NULL; - } - } - - free(dev); -} - -static void * -kbd_init(const device_t *info) -{ - atkbd_t *dev; - int i, max_ports; - - dev = (atkbd_t *) malloc(sizeof(atkbd_t)); - memset(dev, 0x00, sizeof(atkbd_t)); - - dev->flags = info->local; - dev->pci = !!(info->flags & DEVICE_PCI); - - /* We need this, sadly. */ - SavedKbd = dev; - - video_reset(gfxcard[0]); - kbd_reset(dev); - - io_sethandler(0x0060, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - io_sethandler(0x0064, 1, kbd_read, NULL, NULL, kbd_write, NULL, NULL, dev); - keyboard_send = add_data_kbd; - - timer_add(&dev->send_delay_timer, kbd_poll, dev, 1); - timer_add(&dev->pulse_cb, pulse_poll, dev, 0); - - dev->write60_ven = NULL; - dev->write64_ven = NULL; - - switch (dev->flags & KBC_VEN_MASK) { - case KBC_VEN_ACER: - case KBC_VEN_GENERIC: - case KBC_VEN_NCR: - case KBC_VEN_IBM_PS1: - dev->write64_ven = write64_generic; - break; - - case KBC_VEN_OLIVETTI: - dev->write64_ven = write64_olivetti; - break; - - case KBC_VEN_AMI: - case KBC_VEN_INTEL_AMI: - case KBC_VEN_ALI: - case KBC_VEN_TG: - case KBC_VEN_TG_GREEN: - dev->write60_ven = write60_ami; - dev->write64_ven = write64_ami; - break; - - case KBC_VEN_IBM_MCA: - dev->write64_ven = write64_ibm_mca; - break; - - case KBC_VEN_QUADTEL: - dev->write60_ven = write60_quadtel; - dev->write64_ven = write64_quadtel; - break; - - case KBC_VEN_TOSHIBA: - dev->write60_ven = write60_toshiba; - dev->write64_ven = write64_toshiba; - break; - } - - max_ports = ((dev->flags & KBC_TYPE_MASK) >= KBC_TYPE_PS2_NOREF) ? 2 : 1; - - for (i = 0; i < max_ports; i++) { - kbc_ports[i] = (kbc_port_t *) malloc(sizeof(kbc_port_t)); - memset(kbc_ports[i], 0x00, sizeof(kbc_port_t)); - } - - return (dev); -} - -const device_t keyboard_at_device = { - .name = "PC/AT Keyboard", - .internal_name = "keyboard_at", - .flags = 0, - .local = KBC_TYPE_ISA | KBC_VEN_GENERIC, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_at_ami_device = { - .name = "PC/AT Keyboard (AMI)", - .internal_name = "keyboard_at_ami", - .flags = 0, - .local = KBC_TYPE_ISA | KBC_VEN_AMI, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_at_tg_ami_device = { - .name = "PC/AT Keyboard (TriGem AMI)", - .internal_name = "keyboard_at_tg_ami", - .flags = 0, - .local = KBC_TYPE_ISA | KBC_VEN_TG, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_at_toshiba_device = { - .name = "PC/AT Keyboard (Toshiba)", - .internal_name = "keyboard_at_toshiba", - .flags = 0, - .local = KBC_TYPE_ISA | KBC_VEN_TOSHIBA, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_at_olivetti_device = { - .name = "PC/AT Keyboard (Olivetti)", - .internal_name = "keyboard_at_olivetti", - .flags = 0, - .local = KBC_TYPE_ISA | KBC_VEN_OLIVETTI, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_at_ncr_device = { - .name = "PC/AT Keyboard (NCR)", - .internal_name = "keyboard_at_ncr", - .flags = 0, - .local = KBC_TYPE_ISA | KBC_VEN_NCR, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_device = { - .name = "PS/2 Keyboard", - .internal_name = "keyboard_ps2", - .flags = 0, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_ps1_device = { - .name = "PS/2 Keyboard (IBM PS/1)", - .internal_name = "keyboard_ps2_ps1", - .flags = 0, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_ps1_pci_device = { - .name = "PS/2 Keyboard (IBM PS/1)", - .internal_name = "keyboard_ps2_ps1_pci", - .flags = DEVICE_PCI, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_IBM_PS1, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_xi8088_device = { - .name = "PS/2 Keyboard (Xi8088)", - .internal_name = "keyboard_ps2_xi8088", - .flags = 0, - .local = KBC_TYPE_PS2_1 | KBC_VEN_GENERIC, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_ami_device = { - .name = "PS/2 Keyboard (AMI)", - .internal_name = "keyboard_ps2_ami", - .flags = 0, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_tg_ami_device = { - .name = "PS/2 Keyboard (TriGem AMI)", - .internal_name = "keyboard_ps2_tg_ami", - .flags = 0, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_TG, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_mca_device = { - .name = "PS/2 Keyboard", - .internal_name = "keyboard_ps2_mca", - .flags = 0, - .local = KBC_TYPE_PS2_1 | KBC_VEN_IBM_MCA, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_mca_2_device = { - .name = "PS/2 Keyboard", - .internal_name = "keyboard_ps2_mca_2", - .flags = 0, - .local = KBC_TYPE_PS2_2 | KBC_VEN_IBM_MCA, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_quadtel_device = { - .name = "PS/2 Keyboard (Quadtel/MegaPC)", - .internal_name = "keyboard_ps2_quadtel", - .flags = 0, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_QUADTEL, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_pci_device = { - .name = "PS/2 Keyboard", - .internal_name = "keyboard_ps2_pci", - .flags = DEVICE_PCI, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_GENERIC, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_ami_pci_device = { - .name = "PS/2 Keyboard (AMI)", - .internal_name = "keyboard_ps2_ami_pci", - .flags = DEVICE_PCI, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_AMI, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_ali_pci_device = { - .name = "PS/2 Keyboard (ALi M5123/M1543C)", - .internal_name = "keyboard_ps2_ali_pci", - .flags = DEVICE_PCI, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_ALI, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_intel_ami_pci_device = { - .name = "PS/2 Keyboard (AMI)", - .internal_name = "keyboard_ps2_intel_ami_pci", - .flags = DEVICE_PCI, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_INTEL_AMI, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_tg_ami_pci_device = { - .name = "PS/2 Keyboard (TriGem AMI)", - .internal_name = "keyboard_ps2_tg_ami_pci", - .flags = DEVICE_PCI, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_TG, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -const device_t keyboard_ps2_acer_pci_device = { - .name = "PS/2 Keyboard (Acer 90M002A)", - .internal_name = "keyboard_ps2_acer_pci", - .flags = DEVICE_PCI, - .local = KBC_TYPE_PS2_NOREF | KBC_VEN_ACER, - .init = kbd_init, - .close = kbd_close, - .reset = kbd_reset, - { .available = NULL }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = NULL -}; - -void -keyboard_at_set_mouse(void (*func)(uint8_t val, void *priv), void *priv) -{ - mouse_write = func; - mouse_p = priv; -} - -void -keyboard_at_adddata_mouse(uint8_t val) -{ - atkbd_t *dev = SavedKbd; - - if (!mouse_scan || (dev->mouse_queue_end >= 16)) { - kbd_log("ATkbc: Unable to add to queue, conditions: %i, %i\n", !mouse_scan, (dev->mouse_queue_end >= 16)); - return; - } - kbc_queue_add(dev, val, 2); -} - -void -keyboard_at_adddata_mouse_cmd(uint8_t val) -{ - atkbd_t *dev = SavedKbd; - - if (dev->mouse_cmd_queue_end >= 16) { - kbd_log("ATkbc: Unable to add to queue, dev->mouse_cmd_queue_end >= 16\n"); - return; - } - kbc_queue_add(dev, val, 3); -} - -uint8_t -keyboard_at_mouse_pos(void) -{ - atkbd_t *dev = SavedKbd; - - return ((dev->mouse_queue_end - dev->mouse_queue_start) & 0xf); -} - -void -keyboard_at_set_a20_key(int state) -{ - atkbd_t *dev = SavedKbd; - - write_output(dev, (dev->output_port & 0xfd) | ((!!state) << 1)); -} diff --git a/src/device/mouse_ps2 - Cópia.c b/src/device/mouse_ps2 - Cópia.c deleted file mode 100644 index 1c8e0334d..000000000 --- a/src/device/mouse_ps2 - Cópia.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * 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. - * - * Implementation of PS/2 series Mouse devices. - * - * - * - * Authors: Fred N. van Kempen, - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/device.h> -#include <86box/keyboard.h> -#include <86box/mouse.h> - -enum { - MODE_STREAM, - MODE_REMOTE, - MODE_ECHO -}; - -typedef struct { - const char *name; /* name of this device */ - int8_t type; /* type of this device */ - - int mode; - - uint16_t flags; - uint8_t resolution; - uint8_t sample_rate; - - uint8_t command; - - int x, y, z, b; - - uint8_t last_data[6]; -} mouse_t; -#define FLAG_5BTN 0x100 /* using Intellimouse Optical mode */ -#define FLAG_INTELLI 0x80 /* device is IntelliMouse */ -#define FLAG_INTMODE 0x40 /* using Intellimouse mode */ -#define FLAG_SCALED 0x20 /* enable delta scaling */ -#define FLAG_ENABLED 0x10 /* dev is enabled for use */ -#define FLAG_CTRLDAT 0x08 /* ctrl or data mode */ - -int mouse_scan = 0; - -#ifdef ENABLE_MOUSE_PS2_LOG -int mouse_ps2_do_log = ENABLE_MOUSE_PS2_LOG; - -static void -mouse_ps2_log(const char *fmt, ...) -{ - va_list ap; - - if (mouse_ps2_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define mouse_ps2_log(fmt, ...) -#endif - -void -mouse_clear_data(void *priv) -{ - mouse_t *dev = (mouse_t *) priv; - - dev->flags &= ~FLAG_CTRLDAT; -} - -static void -ps2_report_coordinates(mouse_t *dev, int cmd) -{ - uint8_t buff[3] = { 0x08, 0x00, 0x00 }; - int temp_z; - - if (dev->x > 255) { - dev->x = 255; - buff[0] |= 0x40; - } - if (dev->x < -256) { - dev->x = -256; - buff[0] |= 0x40; - } - if (dev->y > 255) { - dev->y = 255; - buff[0] |= 0x80; - } - if (dev->y < -256) { - dev->y = -256; - buff[0] |= 0x80; - } - if (dev->z < -8) - dev->z = -8; - if (dev->z > 7) - dev->z = 7; - - if (dev->x < 0) - buff[0] |= 0x10; - if (dev->y < 0) - buff[0] |= 0x20; - if (mouse_buttons & 0x01) - buff[0] |= 0x01; - if (mouse_buttons & 0x02) - buff[0] |= 0x02; - if (dev->flags & FLAG_INTELLI) { - if (mouse_buttons & 0x04) - buff[0] |= 0x04; - } - buff[1] = (dev->x & 0xff); - buff[2] = (dev->y & 0xff); - - if (cmd) { - keyboard_at_adddata_mouse_cmd(buff[0]); - keyboard_at_adddata_mouse_cmd(buff[1]); - keyboard_at_adddata_mouse_cmd(buff[2]); - } else { - keyboard_at_adddata_mouse(buff[0]); - keyboard_at_adddata_mouse(buff[1]); - keyboard_at_adddata_mouse(buff[2]); - } - if (dev->flags & FLAG_INTMODE) { - temp_z = dev->z & 0x0f; - if ((dev->flags & FLAG_5BTN)) { - if (mouse_buttons & 8) - temp_z |= 0x10; - if (mouse_buttons & 16) - temp_z |= 0x20; - } else { - /* The wheel coordinate is sign-extended. */ - if (temp_z & 0x08) - temp_z |= 0xf0; - } - if (cmd) - keyboard_at_adddata_mouse_cmd(temp_z); - else - keyboard_at_adddata_mouse(temp_z); - } - - dev->x = dev->y = dev->z = 0; -} - -static void -ps2_write(uint8_t val, void *priv) -{ - mouse_t *dev = (mouse_t *) priv; - uint8_t temp; - - if (dev->flags & FLAG_CTRLDAT) { - dev->flags &= ~FLAG_CTRLDAT; - - if (val == 0xff) - goto mouse_reset; - - switch (dev->command) { - case 0xe8: /* set mouse resolution */ - dev->resolution = val; - keyboard_at_adddata_mouse_cmd(0xfa); - break; - - case 0xf3: /* set sample rate */ - dev->sample_rate = val; - keyboard_at_adddata_mouse_cmd(0xfa); /* Command response */ - break; - - default: - keyboard_at_adddata_mouse_cmd(0xfc); - } - } else { - dev->command = val; - - switch (dev->command) { - case 0xe6: /* set scaling to 1:1 */ - dev->flags &= ~FLAG_SCALED; - keyboard_at_adddata_mouse_cmd(0xfa); - break; - - case 0xe7: /* set scaling to 2:1 */ - dev->flags |= FLAG_SCALED; - keyboard_at_adddata_mouse_cmd(0xfa); - break; - - case 0xe8: /* set mouse resolution */ - dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse_cmd(0xfa); - break; - - case 0xe9: /* status request */ - keyboard_at_adddata_mouse_cmd(0xfa); - temp = (dev->flags & 0x30); - if (mouse_buttons & 1) - temp |= 4; - if (mouse_buttons & 2) - temp |= 1; - if ((mouse_buttons & 4) && (dev->flags & FLAG_INTELLI)) - temp |= 2; - keyboard_at_adddata_mouse_cmd(temp); - keyboard_at_adddata_mouse_cmd(dev->resolution); - keyboard_at_adddata_mouse_cmd(dev->sample_rate); - break; - - case 0xea: /* set stream */ - dev->flags &= ~FLAG_CTRLDAT; - mouse_scan = 1; - keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */ - break; - - case 0xeb: /* Get mouse data */ - keyboard_at_adddata_mouse_cmd(0xfa); - - ps2_report_coordinates(dev, 1); - break; - - case 0xf2: /* read ID */ - keyboard_at_adddata_mouse_cmd(0xfa); - if (dev->flags & FLAG_INTMODE) - keyboard_at_adddata_mouse_cmd((dev->flags & FLAG_5BTN) ? 0x04 : 0x03); - else - keyboard_at_adddata_mouse_cmd(0x00); - break; - - case 0xf3: /* set command mode */ - dev->flags |= FLAG_CTRLDAT; - keyboard_at_adddata_mouse_cmd(0xfa); /* ACK for command byte */ - break; - - case 0xf4: /* enable */ - dev->flags |= FLAG_ENABLED; - mouse_scan = 1; - keyboard_at_adddata_mouse_cmd(0xfa); - break; - - case 0xf5: /* disable */ - dev->flags &= ~FLAG_ENABLED; - mouse_scan = 0; - keyboard_at_adddata_mouse_cmd(0xfa); - break; - - case 0xf6: /* set defaults */ - case 0xff: /* reset */ -mouse_reset: - dev->mode = MODE_STREAM; - dev->flags &= 0x88; - mouse_scan = 1; - keyboard_at_mouse_reset(); - keyboard_at_adddata_mouse_cmd(0xfa); - if (dev->command == 0xff) { - keyboard_at_adddata_mouse_cmd(0xaa); - keyboard_at_adddata_mouse_cmd(0x00); - } - break; - - default: - keyboard_at_adddata_mouse_cmd(0xfe); - } - } - - if (dev->flags & FLAG_INTELLI) { - for (temp = 0; temp < 5; temp++) - dev->last_data[temp] = dev->last_data[temp + 1]; - - dev->last_data[5] = val; - - if ((dev->last_data[0] == 0xf3) && (dev->last_data[1] == 0xc8) && - (dev->last_data[2] == 0xf3) && (dev->last_data[3] == 0x64) && - (dev->last_data[4] == 0xf3) && (dev->last_data[5] == 0x50)) - dev->flags |= FLAG_INTMODE; - - if ((dev->flags & FLAG_INTMODE) && (dev->last_data[0] == 0xf3) && (dev->last_data[1] == 0xc8) && - (dev->last_data[2] == 0xf3) && (dev->last_data[3] == 0xc8) && - (dev->last_data[4] == 0xf3) && (dev->last_data[5] == 0x50)) - dev->flags |= FLAG_5BTN; - } -} - -static int -ps2_poll(int x, int y, int z, int b, double abs_x, double abs_y, void *priv) -{ - mouse_t *dev = (mouse_t *) priv; - - if (!x && !y && !z && (b == dev->b)) - return (0xff); - -#if 0 - if (!(dev->flags & FLAG_ENABLED)) - return(0xff); -#endif - - if (!mouse_scan) - return (0xff); - - dev->x += x; - dev->y -= y; - dev->z -= z; -#if 0 - if ((dev->mode == MODE_STREAM) && (dev->flags & FLAG_ENABLED) && (keyboard_at_mouse_pos() < 13)) { -#else - if ((dev->mode == MODE_STREAM) && (keyboard_at_mouse_pos() < 13)) { -#endif - dev->b = b; - - ps2_report_coordinates(dev, 0); - } - - return (0); -} - -/* - * Initialize the device for use by the user. - * - * We also get called from the various machines. - */ -void * -mouse_ps2_init(const device_t *info) -{ - mouse_t *dev; - int i; - - dev = (mouse_t *) malloc(sizeof(mouse_t)); - memset(dev, 0x00, sizeof(mouse_t)); - dev->name = info->name; - dev->type = info->local; - - dev->mode = MODE_STREAM; - i = device_get_config_int("buttons"); - if (i > 2) - dev->flags |= FLAG_INTELLI; - - if (i == 4) - i = 3; - - /* Hook into the general AT Keyboard driver. */ - keyboard_at_set_mouse(ps2_write, dev); - - mouse_ps2_log("%s: buttons=%d\n", dev->name, i); - - /* Tell them how many buttons we have. */ - mouse_set_buttons(i); - - /* Return our private data to the I/O layer. */ - return (dev); -} - -static void -ps2_close(void *priv) -{ - mouse_t *dev = (mouse_t *) priv; - - /* Unhook from the general AT Keyboard driver. */ - keyboard_at_set_mouse(NULL, NULL); - - free(dev); -} - -static const device_config_t ps2_config[] = { - // clang-format off - { - .name = "buttons", - .description = "Buttons", - .type = CONFIG_SELECTION, - .default_string = "", - .default_int = 2, - .file_filter = "", - .spinner = { 0 }, - .selection = { - { .description = "Two", .value = 2 }, - { .description = "Three", .value = 3 }, - { .description = "Wheel", .value = 4 }, - { .description = "Five + Wheel", .value = 5 }, - { .description = "" } - } - }, - { - .name = "", .description = "", .type = CONFIG_END - } - // clang-format on -}; - -const device_t mouse_ps2_device = { - .name = "Standard PS/2 Mouse", - .internal_name = "ps2", - .flags = DEVICE_PS2, - .local = MOUSE_TYPE_PS2, - .init = mouse_ps2_init, - .close = ps2_close, - .reset = NULL, - { .poll = ps2_poll }, - .speed_changed = NULL, - .force_redraw = NULL, - .config = ps2_config -}; diff --git a/src/mem/mem - Cópia.c b/src/mem/mem - Cópia.c deleted file mode 100644 index a8d9e994d..000000000 --- a/src/mem/mem - Cópia.c +++ /dev/null @@ -1,3092 +0,0 @@ -/* - * 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. - * - * Memory handling and MMU. - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2020 Sarah Walker. - * Copyright 2016-2020 Miran Grca. - * Copyright 2017-2020 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include <86box/86box.h> -#include <86box/version.h> -#include "cpu.h" -#include "x86_ops.h" -#include "x86.h" -#include <86box/machine.h> -#include <86box/m_xt_xi8088.h> -#include <86box/config.h> -#include <86box/io.h> -#include <86box/mem.h> -#include <86box/plat.h> -#include <86box/rom.h> -#include <86box/gdbstub.h> -#ifdef USE_DYNAREC -# include "codegen_public.h" -#else -# ifdef USE_NEW_DYNAREC -# define PAGE_MASK_SHIFT 6 -# else -# define PAGE_MASK_INDEX_MASK 3 -# define PAGE_MASK_INDEX_SHIFT 10 -# define PAGE_MASK_SHIFT 4 -# endif -# define PAGE_MASK_MASK 63 -#endif -#if (!defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC)) -# define BLOCK_PC_INVALID 0xffffffff -# define BLOCK_INVALID 0 -#endif - -mem_mapping_t ram_low_mapping, /* 0..640K mapping */ - ram_mid_mapping, /* 640..1024K mapping */ - ram_mid_mapping2, /* 640..1024K mapping, second part, for SiS 471 in relocate mode */ - ram_remapped_mapping, /* 640..1024K mapping */ - ram_remapped_mapping2, /* 640..1024K second mapping, for SiS 471 mode */ - ram_high_mapping, /* 1024K+ mapping */ - ram_2gb_mapping, /* 1024M+ mapping */ - ram_split_mapping, - bios_mapping, - bios_high_mapping; - -page_t *pages, /* RAM page table */ - **page_lookup; /* pagetable lookup */ -uint32_t pages_sz; /* #pages in table */ - -uint8_t *ram, *ram2; /* the virtual RAM */ -uint8_t page_ff[4096]; -uint32_t rammask; -uint32_t addr_space_size; - -uint8_t *rom; /* the virtual ROM */ -uint32_t biosmask, biosaddr; - -uint32_t pccache; -uint8_t *pccache2; - -int readlnext; -int readlookup[256]; -uintptr_t *readlookup2; -uintptr_t old_rl2; -uint8_t uncached = 0; -int writelnext; -int writelookup[256]; -uintptr_t *writelookup2; - -uint32_t mem_logical_addr; - -int shadowbios = 0, - shadowbios_write; -int readlnum = 0, - writelnum = 0; -int cachesize = 256; - -uint32_t get_phys_virt, - get_phys_phys; - -int mem_a20_key = 0, - mem_a20_alt = 0, - mem_a20_state = 0; - -int mmuflush = 0; -int mmu_perm = 4; - -#ifdef USE_NEW_DYNAREC -uint64_t *byte_dirty_mask; -uint64_t *byte_code_present_mask; - -uint32_t purgable_page_list_head = 0; -int purgeable_page_count = 0; -#endif - -uint8_t high_page = 0; /* if a high (> 4 gb) page was detected */ - -/* FIXME: re-do this with a 'mem_ops' struct. */ -static uint8_t *page_lookupp; /* pagetable mmu_perm lookup */ -static uint8_t *readlookupp; -static uint8_t *writelookupp; -static mem_mapping_t *base_mapping, *last_mapping; -static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO]; -static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO]; -static mem_mapping_t *read_mapping_bus[MEM_MAPPINGS_NO]; -static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO]; -static uint8_t *_mem_exec[MEM_MAPPINGS_NO]; -static uint8_t ff_pccache[4] = { 0xff, 0xff, 0xff, 0xff }; -static mem_state_t _mem_state[MEM_MAPPINGS_NO]; -static uint32_t remap_start_addr, remap_start_addr2; -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) -static size_t ram_size = 0, ram2_size = 0; -#else -static size_t ram_size = 0; -#endif - -#ifdef ENABLE_MEM_LOG -int mem_do_log = ENABLE_MEM_LOG; - -static void -mem_log(const char *fmt, ...) -{ - va_list ap; - - if (mem_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define mem_log(fmt, ...) -#endif - -int -mem_addr_is_ram(uint32_t addr) -{ - mem_mapping_t *mapping = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || - (mapping == &ram_mid_mapping2) || (mapping == &ram_remapped_mapping); -} - -void -resetreadlookup(void) -{ - int c; - - /* Initialize the page lookup table. */ - memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); - - /* Initialize the tables for lower (<= 1024K) RAM. */ - for (c = 0; c < 256; c++) { - readlookup[c] = 0xffffffff; - writelookup[c] = 0xffffffff; - } - - /* Initialize the tables for high (> 1024K) RAM. */ - memset(readlookup2, 0xff, (1 << 20) * sizeof(uintptr_t)); - memset(readlookupp, 0x04, (1 << 20) * sizeof(uint8_t)); - - memset(writelookup2, 0xff, (1 << 20) * sizeof(uintptr_t)); - memset(writelookupp, 0x04, (1 << 20) * sizeof(uint8_t)); - - readlnext = 0; - writelnext = 0; - pccache = 0xffffffff; - high_page = 0; -} - -void -flushmmucache(void) -{ - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = LOOKUP_INV; - readlookupp[readlookup[c]] = 4; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - page_lookupp[writelookup[c]] = 4; - writelookup2[writelookup[c]] = LOOKUP_INV; - writelookupp[writelookup[c]] = 4; - writelookup[c] = 0xffffffff; - } - } - mmuflush++; - - pccache = (uint32_t) 0xffffffff; - pccache2 = (uint8_t *) 0xffffffff; - -#ifdef USE_DYNAREC - codegen_flush(); -#endif -} - -void -flushmmucache_nopc(void) -{ - int c; - - for (c = 0; c < 256; c++) { - if (readlookup[c] != (int) 0xffffffff) { - readlookup2[readlookup[c]] = LOOKUP_INV; - readlookupp[readlookup[c]] = 4; - readlookup[c] = 0xffffffff; - } - if (writelookup[c] != (int) 0xffffffff) { - page_lookup[writelookup[c]] = NULL; - page_lookupp[writelookup[c]] = 4; - writelookup2[writelookup[c]] = LOOKUP_INV; - writelookupp[writelookup[c]] = 4; - writelookup[c] = 0xffffffff; - } - } -} - -void -mem_flush_write_page(uint32_t addr, uint32_t virt) -{ - page_t *page_target = &pages[addr >> 12]; - int c; -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - uint32_t a; -#endif - - for (c = 0; c < 256; c++) { - if (writelookup[c] != (int) 0xffffffff) { -#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) - uintptr_t target = (uintptr_t) &ram[(uintptr_t) (addr & ~0xfff) - (virt & ~0xfff)]; -#else - a = (uintptr_t) (addr & ~0xfff) - (virt & ~0xfff); - uintptr_t target; - - if ((addr & ~0xfff) >= (1 << 30)) - target = (uintptr_t) &ram2[a - (1 << 30)]; - else - target = (uintptr_t) &ram[a]; -#endif - - if (writelookup2[writelookup[c]] == target || page_lookup[writelookup[c]] == page_target) { - writelookup2[writelookup[c]] = LOOKUP_INV; - page_lookup[writelookup[c]] = NULL; - writelookup[c] = 0xffffffff; - } - } - } -} - -#define mmutranslate_read(addr) mmutranslatereal(addr, 0) -#define mmutranslate_write(addr) mmutranslatereal(addr, 1) -#define rammap(x) ((uint32_t *) (_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 2) & MEM_GRANULARITY_QMASK] -#define rammap64(x) ((uint64_t *) (_mem_exec[(x) >> MEM_GRANULARITY_BITS]))[((x) >> 3) & MEM_GRANULARITY_PMASK] - -static __inline uint64_t -mmutranslatereal_normal(uint32_t addr, int rw) -{ - uint32_t temp, temp2, temp3; - uint32_t addr2; - - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); - temp = temp2 = rammap(addr2); - if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - - return 0xffffffffffffffffULL; - } - - mmu_perm = temp & 4; - rammap(addr2) |= (rw ? 0x60 : 0x20); - - return (temp & ~0x3fffff) + (addr & 0x3fffff); - } - - temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); - temp3 = temp & temp2; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || ((is486 || isibm486) && (cr0 & WP_FLAG))))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - mmu_perm = temp & 4; - rammap(addr2) |= 0x20; - rammap((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) |= (rw ? 0x60 : 0x20); - - return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); -} - -static __inline uint64_t -mmutranslatereal_pae(uint32_t addr, int rw) -{ - uint64_t temp, temp2, temp3, temp4; - uint64_t addr2, addr3, addr4; - - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); - temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; - if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); - temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; - temp3 = temp & temp2; - if (!(temp & 1)) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - if (temp & 0x80) { - /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - - return 0xffffffffffffffffULL; - } - mmu_perm = temp & 4; - rammap64(addr3) |= (rw ? 0x60 : 0x20); - - return ((temp & ~0x1fffffULL) + (addr & 0x1fffffULL)) & 0x000000ffffffffffULL; - } - - addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); - temp = rammap64(addr4) & 0x000000ffffffffffULL; - temp3 = temp & temp4; - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (cr0 & WP_FLAG)))) { - cr2 = addr; - temp &= 1; - if (CPL == 3) - temp |= 4; - if (rw) - temp |= 2; - cpu_state.abrt = ABRT_PF; - abrt_error = temp; - return 0xffffffffffffffffULL; - } - - mmu_perm = temp & 4; - rammap64(addr3) |= 0x20; - rammap64(addr4) |= (rw ? 0x60 : 0x20); - - return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; -} - -uint64_t -mmutranslatereal(uint32_t addr, int rw) -{ - /* Fast path to return invalid without any call if an exception has occurred beforehand. */ - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - if (cr4 & CR4_PAE) - return mmutranslatereal_pae(addr, rw); - else - return mmutranslatereal_normal(addr, rw); -} - -/* This is needed because the old recompiler calls this to check for page fault. */ -uint32_t -mmutranslatereal32(uint32_t addr, int rw) -{ - /* Fast path to return invalid without any call if an exception has occurred beforehand. */ - if (cpu_state.abrt) - return (uint32_t) 0xffffffffffffffffULL; - - return (uint32_t) mmutranslatereal(addr, rw); -} - -static __inline uint64_t -mmutranslate_noabrt_normal(uint32_t addr, int rw) -{ - uint32_t temp, temp2, temp3; - uint32_t addr2; - - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc)); - temp = temp2 = rammap(addr2); - - if (!(temp & 1)) - return 0xffffffffffffffffULL; - - if ((temp & 0x80) && (cr4 & CR4_PSE)) { - /*4MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; - - return (temp & ~0x3fffff) + (addr & 0x3fffff); - } - - temp = rammap((temp & ~0xfff) + ((addr >> 10) & 0xffc)); - temp3 = temp & temp2; - - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; - - return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff)); -} - -static __inline uint64_t -mmutranslate_noabrt_pae(uint32_t addr, int rw) -{ - uint64_t temp, temp2, temp3, temp4; - uint64_t addr2, addr3, addr4; - - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - addr2 = (cr3 & ~0x1f) + ((addr >> 27) & 0x18); - temp = temp2 = rammap64(addr2) & 0x000000ffffffffffULL; - - if (!(temp & 1)) - return 0xffffffffffffffffULL; - - addr3 = (temp & ~0xfffULL) + ((addr >> 18) & 0xff8); - temp = temp4 = rammap64(addr3) & 0x000000ffffffffffULL; - temp3 = temp & temp2; - - if (!(temp & 1)) - return 0xffffffffffffffffULL; - - if (temp & 0x80) { - /*2MB page*/ - if (((CPL == 3) && !(temp & 4) && !cpl_override) || (rw && !(temp & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; - - return ((temp & ~0x1fffffULL) + (addr & 0x1fffff)) & 0x000000ffffffffffULL; - } - - addr4 = (temp & ~0xfffULL) + ((addr >> 9) & 0xff8); - temp = rammap64(addr4) & 0x000000ffffffffffULL; - ; - temp3 = temp & temp4; - - if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG)))) - return 0xffffffffffffffffULL; - - return ((temp & ~0xfffULL) + ((uint64_t) (addr & 0xfff))) & 0x000000ffffffffffULL; -} - -uint64_t -mmutranslate_noabrt(uint32_t addr, int rw) -{ - /* Fast path to return invalid without any call if an exception has occurred beforehand. */ - if (cpu_state.abrt) - return 0xffffffffffffffffULL; - - if (cr4 & CR4_PAE) - return mmutranslate_noabrt_pae(addr, rw); - else - return mmutranslate_noabrt_normal(addr, rw); -} - -void -mmu_invalidate(uint32_t addr) -{ - flushmmucache_cr3(); -} - -uint8_t -mem_addr_range_match(uint32_t addr, uint32_t start, uint32_t len) -{ - if (addr < start) - return 0; - else if (addr >= (start + len)) - return 0; - else - return 1; -} - -uint32_t -mem_addr_translate(uint32_t addr, uint32_t chunk_start, uint32_t len) -{ - uint32_t mask = len - 1; - - return chunk_start + (addr & mask); -} - -void -addreadlookup(uint32_t virt, uint32_t phys) -{ -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - uint32_t a; -#endif - - if (virt == 0xffffffff) - return; - - if (readlookup2[virt >> 12] != (uintptr_t) LOOKUP_INV) - return; - - if (readlookup[readlnext] != (int) 0xffffffff) { - if ((readlookup[readlnext] == ((es + DI) >> 12)) || (readlookup[readlnext] == ((es + EDI) >> 12))) - uncached = 1; - readlookup2[readlookup[readlnext]] = LOOKUP_INV; - } - -#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) - readlookup2[virt >> 12] = (uintptr_t) &ram[(uintptr_t) (phys & ~0xFFF) - (uintptr_t) (virt & ~0xfff)]; -#else - a = ((uint32_t) (phys & ~0xfff) - (uint32_t) (virt & ~0xfff)); - - if ((phys & ~0xfff) >= (1 << 30)) - readlookup2[virt >> 12] = (uintptr_t) &ram2[a - (1 << 30)]; - else - readlookup2[virt >> 12] = (uintptr_t) &ram[a]; -#endif - readlookupp[virt >> 12] = mmu_perm; - - readlookup[readlnext++] = virt >> 12; - readlnext &= (cachesize - 1); - - cycles -= 9; -} - -void -addwritelookup(uint32_t virt, uint32_t phys) -{ -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - uint32_t a; -#endif - - if (virt == 0xffffffff) - return; - - if (page_lookup[virt >> 12]) - return; - - if (writelookup[writelnext] != -1) { - page_lookup[writelookup[writelnext]] = NULL; - writelookup2[writelookup[writelnext]] = LOOKUP_INV; - } - -#ifdef USE_NEW_DYNAREC -# ifdef USE_DYNAREC - if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page) { -# else - if (pages[phys >> 12].block) { -# endif -#else -# ifdef USE_DYNAREC - if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page) { -# else - if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3]) { -# endif -#endif - page_lookup[virt >> 12] = &pages[phys >> 12]; - page_lookupp[virt >> 12] = mmu_perm; - } else { -#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64) - writelookup2[virt >> 12] = (uintptr_t) &ram[(uintptr_t) (phys & ~0xFFF) - (uintptr_t) (virt & ~0xfff)]; -#else - a = ((uint32_t) (phys & ~0xfff) - (uint32_t) (virt & ~0xfff)); - - if ((phys & ~0xfff) >= (1 << 30)) - writelookup2[virt >> 12] = (uintptr_t) &ram2[a - (1 << 30)]; - else - writelookup2[virt >> 12] = (uintptr_t) &ram[a]; -#endif - } - writelookupp[virt >> 12] = mmu_perm; - - writelookup[writelnext++] = virt >> 12; - writelnext &= (cachesize - 1); - - cycles -= 9; -} - -uint8_t * -getpccache(uint32_t a) -{ - uint64_t a64 = (uint64_t) a; - uint32_t a2; - - a2 = a; - - if (cr0 >> 31) { - a64 = mmutranslate_read(a64); - - if (a64 == 0xffffffffffffffffULL) - return ram; - } - a64 &= rammask; - - if (_mem_exec[a64 >> MEM_GRANULARITY_BITS]) { - if (is286) { - if (read_mapping[a64 >> MEM_GRANULARITY_BITS] && (read_mapping[a64 >> MEM_GRANULARITY_BITS]->flags & MEM_MAPPING_ROM_WS)) - cpu_prefetch_cycles = cpu_rom_prefetch_cycles; - else - cpu_prefetch_cycles = cpu_mem_prefetch_cycles; - } - - return &_mem_exec[a64 >> MEM_GRANULARITY_BITS][(uintptr_t) (a64 & MEM_GRANULARITY_PAGE) - (uintptr_t) (a2 & ~0xfff)]; - } - - mem_log("Bad getpccache %08X%08X\n", (uint32_t) (a64 >> 32), (uint32_t) (a64 & 0xffffffffULL)); - - return (uint8_t *) &ff_pccache; -} - -uint8_t -read_mem_b(uint32_t addr) -{ - mem_mapping_t *map; - uint8_t ret = 0xff; - int old_cycles = cycles; - - mem_logical_addr = addr; - addr &= rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_b) - ret = map->read_b(addr, map->p); - - resub_cycles(old_cycles); - - return ret; -} - -uint16_t -read_mem_w(uint32_t addr) -{ - mem_mapping_t *map; - uint16_t ret = 0xffff; - int old_cycles = cycles; - - mem_logical_addr = addr; - addr &= rammask; - - if (addr & 1) - ret = read_mem_b(addr) | (read_mem_b(addr + 1) << 8); - else { - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->read_w) - ret = map->read_w(addr, map->p); - else if (map && map->read_b) - ret = map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8); - } - - resub_cycles(old_cycles); - - return ret; -} - -void -write_mem_b(uint32_t addr, uint8_t val) -{ - mem_mapping_t *map; - int old_cycles = cycles; - - mem_logical_addr = addr; - addr &= rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->write_b) - map->write_b(addr, val, map->p); - - resub_cycles(old_cycles); -} - -void -write_mem_w(uint32_t addr, uint16_t val) -{ - mem_mapping_t *map; - int old_cycles = cycles; - - mem_logical_addr = addr; - addr &= rammask; - - if (addr & 1) { - write_mem_b(addr, val); - write_mem_b(addr + 1, val >> 8); - } else { - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map) { - if (map->write_w) - map->write_w(addr, val, map->p); - else if (map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - } - } - } - - resub_cycles(old_cycles); -} - -uint8_t -readmembl(uint32_t addr) -{ - mem_mapping_t *map; - uint64_t a; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[RB ] %08X\n", addr); - - GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); - - addr64 = (uint64_t) addr; - mem_logical_addr = addr; - - high_page = 0; - - if (cr0 >> 31) { - a = mmutranslate_read(addr); - addr64 = (uint32_t) a; - - if (a > 0xffffffffULL) - return 0xff; - } - addr = (uint32_t) (addr64 & rammask); - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_b) - return map->read_b(addr, map->p); - - return 0xff; -} - -void -writemembl(uint32_t addr, uint8_t val) -{ - mem_mapping_t *map; - uint64_t a; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[WB ] %08X = %02X\n", addr, val); - - GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); - - addr64 = (uint64_t) addr; - mem_logical_addr = addr; - - high_page = 0; - - if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { - page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); - return; - } - - if (cr0 >> 31) { - a = mmutranslate_write(addr); - addr64 = (uint32_t) a; - - if (a > 0xffffffffULL) - return; - } - addr = (uint32_t) (addr64 & rammask); - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->write_b) - map->write_b(addr, val, map->p); -} - -/* Read a byte from memory without MMU translation - result of previous MMU translation passed as value. */ -uint8_t -readmembl_no_mmut(uint32_t addr, uint32_t a64) -{ - mem_mapping_t *map; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[RBN] %08X\n", addr); - - GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1); - - mem_logical_addr = addr; - - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xff; - - addr = a64 & rammask; - } else - addr &= rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_b) - return map->read_b(addr, map->p); - - return 0xff; -} - -/* Write a byte to memory without MMU translation - result of previous MMU translation passed as value. */ -void -writemembl_no_mmut(uint32_t addr, uint32_t a64, uint8_t val) -{ - mem_mapping_t *map; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[WBN] %08X = %02X\n", addr, val); - - GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1); - - mem_logical_addr = addr; - - if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_b) { - page_lookup[addr >> 12]->write_b(addr, val, page_lookup[addr >> 12]); - return; - } - - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; - - addr = a64 & rammask; - } else - addr &= rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->write_b) - map->write_b(addr, val, map->p); -} - -uint16_t -readmemwl(uint32_t addr) -{ - mem_mapping_t *map; - int i; - uint64_t a; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[RW ] %08X\n", addr); - - addr64a[0] = addr; - addr64a[1] = addr + 1; - GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2); - - mem_logical_addr = addr; - - high_page = 0; - - if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { - for (i = 0; i < 2; i++) { - a = mmutranslate_read(addr + i); - addr64a[i] = (uint32_t) a; - - if (a > 0xffffffffULL) - return 0xffff; - } - } - - return readmembl_no_mmut(addr, addr64a[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint16_t *) (readlookup2[addr >> 12] + addr); - } - } - - if (cr0 >> 31) { - a = mmutranslate_read(addr); - addr64a[0] = (uint32_t) a; - - if (a > 0xffffffffULL) - return 0xffff; - } else - addr64a[0] = (uint64_t) addr; - - addr = addr64a[0] & rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->read_w) - return map->read_w(addr, map->p); - - if (map && map->read_b) { - return map->read_b(addr, map->p) | ((uint16_t) (map->read_b(addr + 1, map->p)) << 8); - } - - return 0xffff; -} - -void -writememwl(uint32_t addr, uint16_t val) -{ - mem_mapping_t *map; - int i; - uint64_t a; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[WW ] %08X = %04X\n", addr, val); - - addr64a[0] = addr; - addr64a[1] = addr + 1; - GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2); - - mem_logical_addr = addr; - - high_page = 0; - - if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { - for (i = 0; i < 2; i++) { - /* Do not translate a page that has a valid lookup, as that is by definition valid - and the whole purpose of the lookup is to avoid repeat identical translations. */ - if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { - a = mmutranslate_write(addr + i); - addr64a[i] = (uint32_t) a; - - if (a > 0xffffffffULL) - return; - } - } - } - - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - writemembl_no_mmut(addr, addr64a[0], val); - writemembl_no_mmut(addr + 1, addr64a[1], val >> 8); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint16_t *) (writelookup2[addr >> 12] + addr) = val; - return; - } - } - - if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { - page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); - mmu_perm = page_lookupp[addr >> 12]; - return; - } - - if (cr0 >> 31) { - a = mmutranslate_write(addr); - addr64a[0] = (uint32_t) a; - - if (a > 0xffffffffULL) - return; - } - - addr = addr64a[0] & rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->write_w) { - map->write_w(addr, val, map->p); - return; - } - - if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - return; - } -} - -/* Read a word from memory without MMU translation - results of previous MMU translation passed as array. */ -uint16_t -readmemwl_no_mmut(uint32_t addr, uint32_t *a64) -{ - mem_mapping_t *map; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[RWN] %08X\n", addr); - - GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2); - - mem_logical_addr = addr; - - if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xffff; - } - - return readmembl_no_mmut(addr, a64[0]) | (((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint16_t *) (readlookup2[addr >> 12] + addr); - } - } - - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xffff; - - addr = (uint32_t) (a64[0] & rammask); - } else - addr &= rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->read_w) - return map->read_w(addr, map->p); - - if (map && map->read_b) { - return map->read_b(addr, map->p) | ((uint16_t) (map->read_b(addr + 1, map->p)) << 8); - } - - return 0xffff; -} - -/* Write a word to memory without MMU translation - results of previous MMU translation passed as array. */ -void -writememwl_no_mmut(uint32_t addr, uint32_t *a64, uint16_t val) -{ - mem_mapping_t *map; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[WWN] %08X = %04X\n", addr, val); - - GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2); - - mem_logical_addr = addr; - - if (addr & 1) { - if (!cpu_cyrix_alignment || (addr & 7) == 7) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffe) { - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; - } - - writemembl_no_mmut(addr, a64[0], val); - writemembl_no_mmut(addr + 1, a64[1], val >> 8); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint16_t *) (writelookup2[addr >> 12] + addr) = val; - return; - } - } - - if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_w) { - mmu_perm = page_lookupp[addr >> 12]; - page_lookup[addr >> 12]->write_w(addr, val, page_lookup[addr >> 12]); - return; - } - - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; - - addr = (uint32_t) (a64[0] & rammask); - } else - addr &= rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->write_w) { - map->write_w(addr, val, map->p); - return; - } - - if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - return; - } -} - -uint32_t -readmemll(uint32_t addr) -{ - mem_mapping_t *map; - int i; - uint64_t a = 0x0000000000000000ULL; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[RL ] %08X\n", addr); - - for (i = 0; i < 4; i++) - addr64a[i] = (uint64_t) (addr + i); - GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4); - - mem_logical_addr = addr; - - high_page = 0; - - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { - for (i = 0; i < 4; i++) { - if (i == 0) { - a = mmutranslate_read(addr + i); - addr64a[i] = (uint32_t) a; - } else if (!((addr + i) & 0xfff)) { - a = mmutranslate_read(addr + 3); - addr64a[i] = (uint32_t) a; - if (!cpu_state.abrt) { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - } else { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - - if (a > 0xffffffffULL) - return 0xffff; - } - } - - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - return readmemwl_no_mmut(addr, addr64a) | (((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint32_t *) (readlookup2[addr >> 12] + addr); - } - } - - if (cr0 >> 31) { - a = mmutranslate_read(addr); - addr64a[0] = (uint32_t) a; - - if (a > 0xffffffffULL) - return 0xffffffff; - } - - addr = addr64a[0] & rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->read_l) - return map->read_l(addr, map->p); - - if (map && map->read_w) - return map->read_w(addr, map->p) | ((uint32_t) (map->read_w(addr + 2, map->p)) << 16); - - if (map && map->read_b) - return map->read_b(addr, map->p) | ((uint32_t) (map->read_b(addr + 1, map->p)) << 8) | ((uint32_t) (map->read_b(addr + 2, map->p)) << 16) | ((uint32_t) (map->read_b(addr + 3, map->p)) << 24); - - return 0xffffffff; -} - -void -writememll(uint32_t addr, uint32_t val) -{ - mem_mapping_t *map; - int i; - uint64_t a = 0x0000000000000000ULL; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[WL ] %08X = %08X\n", addr, val); - - for (i = 0; i < 4; i++) - addr64a[i] = (uint64_t) (addr + i); - GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4); - - mem_logical_addr = addr; - - high_page = 0; - - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { - for (i = 0; i < 4; i++) { - /* Do not translate a page that has a valid lookup, as that is by definition valid - and the whole purpose of the lookup is to avoid repeat identical translations. */ - if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { - if (i == 0) { - a = mmutranslate_write(addr + i); - addr64a[i] = (uint32_t) a; - } else if (!((addr + i) & 0xfff)) { - a = mmutranslate_write(addr + 3); - addr64a[i] = (uint32_t) a; - if (!cpu_state.abrt) { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - } else { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - - if (a > 0xffffffffULL) - return; - } - } - } - - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - writememwl_no_mmut(addr, &(addr64a[0]), val); - writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint32_t *) (writelookup2[addr >> 12] + addr) = val; - return; - } - } - - if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; - page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); - return; - } - - if (cr0 >> 31) { - a = mmutranslate_write(addr); - addr64a[0] = (uint32_t) a; - - if (a > 0xffffffffULL) - return; - } - - addr = addr64a[0] & rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[WL ] map = %08X\n", map); - - if (map && map->write_l) { - map->write_l(addr, val, map->p); - return; - } - if (map && map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - return; - } - if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - return; - } -} - -/* Read a long from memory without MMU translation - results of previous MMU translation passed as array. */ -uint32_t -readmemll_no_mmut(uint32_t addr, uint32_t *a64) -{ - mem_mapping_t *map; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[RLN] %08X\n", addr); - - GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4); - - mem_logical_addr = addr; - - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xffffffff; - } - - return readmemwl_no_mmut(addr, a64) | ((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint32_t *) (readlookup2[addr >> 12] + addr); - } - } - - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return 0xffffffff; - - addr = (uint32_t) (a64[0] & rammask); - } else - addr &= rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->read_l) - return map->read_l(addr, map->p); - - if (map && map->read_w) - return map->read_w(addr, map->p) | ((uint32_t) (map->read_w(addr + 2, map->p)) << 16); - - if (map && map->read_b) - return map->read_b(addr, map->p) | ((uint32_t) (map->read_b(addr + 1, map->p)) << 8) | ((uint32_t) (map->read_b(addr + 2, map->p)) << 16) | ((uint32_t) (map->read_b(addr + 3, map->p)) << 24); - - return 0xffffffff; -} - -/* Write a long to memory without MMU translation - results of previous MMU translation passed as array. */ -void -writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val) -{ - mem_mapping_t *map; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[WLN] %08X = %08X\n", addr, val); - - GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4); - - mem_logical_addr = addr; - - if (addr & 3) { - if (!cpu_cyrix_alignment || (addr & 7) > 4) - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xffc) { - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; - } - - writememwl_no_mmut(addr, &(a64[0]), val); - writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint32_t *) (writelookup2[addr >> 12] + addr) = val; - return; - } - } - - if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; - page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); - return; - } - - if (cr0 >> 31) { - if (cpu_state.abrt || high_page) - return; - - addr = (uint32_t) (a64[0] & rammask); - } else - addr &= rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->write_l) { - map->write_l(addr, val, map->p); - return; - } - if (map && map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - return; - } - if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - return; - } -} - -uint64_t -readmemql(uint32_t addr) -{ - mem_mapping_t *map; - int i; - uint64_t a = 0x0000000000000000ULL; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[RQ ] %08X\n", addr); - - for (i = 0; i < 8; i++) - addr64a[i] = (uint64_t) (addr + i); - GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8); - - mem_logical_addr = addr; - - high_page = 0; - - if (addr & 7) { - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xff8) { - if (cr0 >> 31) { - for (i = 0; i < 8; i++) { - if (i == 0) { - a = mmutranslate_read(addr + i); - addr64a[i] = (uint32_t) a; - } else if (!((addr + i) & 0xfff)) { - a = mmutranslate_read(addr + 7); - addr64a[i] = (uint32_t) a; - if (!cpu_state.abrt) { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - } else { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - - if (a > 0xffffffffULL) - return 0xffff; - } - } - - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - return readmemll_no_mmut(addr, addr64a) | (((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32); - } else if (readlookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = readlookupp[addr >> 12]; - return *(uint64_t *) (readlookup2[addr >> 12] + addr); - } - } - - if (cr0 >> 31) { - a = mmutranslate_read(addr); - addr64a[0] = (uint32_t) a; - - if (a > 0xffffffffULL) - return 0xffffffffffffffffULL; - } - - addr = addr64a[0] & rammask; - - map = read_mapping[addr >> MEM_GRANULARITY_BITS]; - if (map && map->read_l) - return map->read_l(addr, map->p) | ((uint64_t) map->read_l(addr + 4, map->p) << 32); - - return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32); -} - -void -writememql(uint32_t addr, uint64_t val) -{ - mem_mapping_t *map; - int i; - uint64_t a = 0x0000000000000000ULL; - - if ((addr >= 0xec000000) && (addr <= 0xecffffff)) - pclog("[WQ ] %08X = %016" PRIX64 "\n", addr, val); - - for (i = 0; i < 8; i++) - addr64a[i] = (uint64_t) (addr + i); - GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8); - - mem_logical_addr = addr; - - high_page = 0; - - if (addr & 7) { - cycles -= timing_misaligned; - if ((addr & 0xfff) > 0xff8) { - if (cr0 >> 31) { - for (i = 0; i < 8; i++) { - /* Do not translate a page that has a valid lookup, as that is by definition valid - and the whole purpose of the lookup is to avoid repeat identical translations. */ - if (!page_lookup[(addr + i) >> 12] || !page_lookup[(addr + i) >> 12]->write_b) { - if (i == 0) { - a = mmutranslate_write(addr + i); - addr64a[i] = (uint32_t) a; - } else if (!((addr + i) & 0xfff)) { - a = mmutranslate_write(addr + 7); - addr64a[i] = (uint32_t) a; - if (!cpu_state.abrt) { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - } else { - a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff)); - addr64a[i] = (uint32_t) a; - } - - if (addr64a[i] > 0xffffffffULL) - return; - } - } - } - - /* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass - their result as a parameter to be used if needed. */ - writememll_no_mmut(addr, addr64a, val); - writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32); - return; - } else if (writelookup2[addr >> 12] != (uintptr_t) LOOKUP_INV) { - mmu_perm = writelookupp[addr >> 12]; - *(uint64_t *) (writelookup2[addr >> 12] + addr) = val; - return; - } - } - - if (page_lookup[addr >> 12] && page_lookup[addr >> 12]->write_l) { - mmu_perm = page_lookupp[addr >> 12]; - page_lookup[addr >> 12]->write_l(addr, val, page_lookup[addr >> 12]); - page_lookup[addr >> 12]->write_l(addr + 4, val >> 32, page_lookup[addr >> 12]); - return; - } - - if (cr0 >> 31) { - addr64a[0] = mmutranslate_write(addr); - if (addr64a[0] > 0xffffffffULL) - return; - } - - addr = addr64a[0] & rammask; - - map = write_mapping[addr >> MEM_GRANULARITY_BITS]; - - if (map && map->write_l) { - map->write_l(addr, val, map->p); - map->write_l(addr + 4, val >> 32, map->p); - return; - } - if (map && map->write_w) { - map->write_w(addr, val, map->p); - map->write_w(addr + 2, val >> 16, map->p); - map->write_w(addr + 4, val >> 32, map->p); - map->write_w(addr + 6, val >> 48, map->p); - return; - } - if (map && map->write_b) { - map->write_b(addr, val, map->p); - map->write_b(addr + 1, val >> 8, map->p); - map->write_b(addr + 2, val >> 16, map->p); - map->write_b(addr + 3, val >> 24, map->p); - map->write_b(addr + 4, val >> 32, map->p); - map->write_b(addr + 5, val >> 40, map->p); - map->write_b(addr + 6, val >> 48, map->p); - map->write_b(addr + 7, val >> 56, map->p); - return; - } -} - -void -do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write) -{ - int i, cond = 1; - uint32_t last_addr = addr + (num - 1); - uint64_t a = 0x0000000000000000ULL; - - for (i = 0; i < num; i++) - a64[i] = (uint64_t) addr; - - for (i = 0; i < num; i++) { - if (cr0 >> 31) { - if (write && ((i == 0) || !(addr & 0xfff))) - cond = (!page_lookup[addr >> 12] || !page_lookup[addr >> 12]->write_b); - - if (cond) { - /* If we have encountered at least one page fault, mark all subsequent addresses as - having page faulted, prevents false negatives in readmem*l_no_mmut. */ - if ((i > 0) && cpu_state.abrt && !high_page) - a64[i] = a64[i - 1]; - /* If we are on the same page, there is no need to translate again, as we can just - reuse the previous result. */ - else if (i == 0) { - a = mmutranslatereal(addr, write); - a64[i] = (uint32_t) a; - - high_page = high_page || (!cpu_state.abrt && (a > 0xffffffffULL)); - } else if (!(addr & 0xfff)) { - a = mmutranslatereal(last_addr, write); - a64[i] = (uint32_t) a; - - high_page = high_page || (!cpu_state.abrt && (a64[i] > 0xffffffffULL)); - - if (!cpu_state.abrt) { - a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); - a64[i] = (uint32_t) a; - } - } else { - a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff)); - a64[i] = (uint32_t) a; - } - } else - mmu_perm = page_lookupp[addr >> 12]; - } - - addr++; - } -} - -uint8_t -mem_readb_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint8_t ret = 0xff; - - mem_logical_addr = 0xffffffff; - - if (map) { - if (map->exec) - ret = map->exec[(addr - map->base) & map->mask]; - else if (map->read_b) - ret = map->read_b(addr, map->p); - } - - return ret; -} - -uint16_t -mem_readw_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint16_t ret, *p; - - mem_logical_addr = 0xffffffff; - - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { - p = (uint16_t *) &(map->exec[(addr - map->base) & map->mask]); - ret = *p; - } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->read_w)) - ret = map->read_w(addr, map->p); - else { - ret = mem_readb_phys(addr + 1) << 8; - ret |= mem_readb_phys(addr); - } - - return ret; -} - -uint32_t -mem_readl_phys(uint32_t addr) -{ - mem_mapping_t *map = read_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint32_t ret, *p; - - mem_logical_addr = 0xffffffff; - - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { - p = (uint32_t *) &(map->exec[(addr - map->base) & map->mask]); - ret = *p; - } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->read_l)) - ret = map->read_l(addr, map->p); - else { - ret = mem_readw_phys(addr + 2) << 16; - ret |= mem_readw_phys(addr); - } - - return ret; -} - -void -mem_read_phys(void *dest, uint32_t addr, int transfer_size) -{ - uint8_t *pb; - uint16_t *pw; - uint32_t *pl; - - if (transfer_size == 4) { - pl = (uint32_t *) dest; - *pl = mem_readl_phys(addr); - } else if (transfer_size == 2) { - pw = (uint16_t *) dest; - *pw = mem_readw_phys(addr); - } else if (transfer_size == 1) { - pb = (uint8_t *) dest; - *pb = mem_readb_phys(addr); - } -} - -void -mem_writeb_phys(uint32_t addr, uint8_t val) -{ - mem_mapping_t *map = write_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - - mem_logical_addr = 0xffffffff; - - if (map) { - if (map->exec) - map->exec[(addr - map->base) & map->mask] = val; - else if (map->write_b) - map->write_b(addr, val, map->p); - } -} - -void -mem_writew_phys(uint32_t addr, uint16_t val) -{ - mem_mapping_t *map = write_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint16_t *p; - - mem_logical_addr = 0xffffffff; - - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->exec)) { - p = (uint16_t *) &(map->exec[(addr - map->base) & map->mask]); - *p = val; - } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_HBOUND) && (map && map->write_w)) - map->write_w(addr, val, map->p); - else { - mem_writeb_phys(addr, val & 0xff); - mem_writeb_phys(addr + 1, (val >> 8) & 0xff); - } -} - -void -mem_writel_phys(uint32_t addr, uint32_t val) -{ - mem_mapping_t *map = write_mapping_bus[addr >> MEM_GRANULARITY_BITS]; - uint32_t *p; - - mem_logical_addr = 0xffffffff; - - if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->exec)) { - p = (uint32_t *) &(map->exec[(addr - map->base) & map->mask]); - *p = val; - } else if (((addr & MEM_GRANULARITY_MASK) <= MEM_GRANULARITY_QBOUND) && (map && map->write_l)) - map->write_l(addr, val, map->p); - else { - mem_writew_phys(addr, val & 0xffff); - mem_writew_phys(addr + 2, (val >> 16) & 0xffff); - } -} - -void -mem_write_phys(void *src, uint32_t addr, int transfer_size) -{ - uint8_t *pb; - uint16_t *pw; - uint32_t *pl; - - if (transfer_size == 4) { - pl = (uint32_t *) src; - mem_writel_phys(addr, *pl); - } else if (transfer_size == 2) { - pw = (uint16_t *) src; - mem_writew_phys(addr, *pw); - } else if (transfer_size == 1) { - pb = (uint8_t *) src; - mem_writeb_phys(addr, *pb); - } -} - -uint8_t -mem_read_ram(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read B %02X from %08X\n", ram[addr], addr); -#endif - - if (is286) - addreadlookup(mem_logical_addr, addr); - - return ram[addr]; -} - -uint16_t -mem_read_ramw(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read W %04X from %08X\n", *(uint16_t *) &ram[addr], addr); -#endif - - if (is286) - addreadlookup(mem_logical_addr, addr); - - return *(uint16_t *) &ram[addr]; -} - -uint32_t -mem_read_raml(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read L %08X from %08X\n", *(uint32_t *) &ram[addr], addr); -#endif - - if (is286) - addreadlookup(mem_logical_addr, addr); - - return *(uint32_t *) &ram[addr]; -} - -uint8_t -mem_read_ram_2gb(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read B %02X from %08X\n", ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return ram2[addr - (1 << 30)]; -} - -uint16_t -mem_read_ram_2gbw(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read W %04X from %08X\n", *(uint16_t *) &ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return *(uint16_t *) &ram2[addr - (1 << 30)]; -} - -uint32_t -mem_read_ram_2gbl(uint32_t addr, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Read L %08X from %08X\n", *(uint32_t *) &ram[addr], addr); -#endif - - addreadlookup(mem_logical_addr, addr); - - return *(uint32_t *) &ram2[addr - (1 << 30)]; -} - -#ifdef USE_NEW_DYNAREC -static inline int -page_index(page_t *p) -{ - return ((uintptr_t) p - (uintptr_t) pages) / sizeof(page_t); -} - -void -page_add_to_evict_list(page_t *p) -{ - pages[purgable_page_list_head].evict_prev = page_index(p); - p->evict_next = purgable_page_list_head; - p->evict_prev = 0; - purgable_page_list_head = pages[purgable_page_list_head].evict_prev; - purgeable_page_count++; -} - -void -page_remove_from_evict_list(page_t *p) -{ - if (!page_in_evict_list(p)) - fatal("page_remove_from_evict_list: not in evict list!\n"); - if (p->evict_prev) - pages[p->evict_prev].evict_next = p->evict_next; - else - purgable_page_list_head = p->evict_next; - if (p->evict_next) - pages[p->evict_next].evict_prev = p->evict_prev; - p->evict_prev = EVICT_NOT_IN_LIST; - purgeable_page_count--; -} - -void -mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) -{ - if (p == NULL) - return; - -# ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { -# else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff])) { -# endif - uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t) 1 << (addr & PAGE_BYTE_MASK_MASK); - - p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - p->byte_dirty_mask[byte_offset] |= byte_mask; - if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } -} - -void -mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) -{ - if (p == NULL) - return; - -# ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *) &p->mem[addr & 0xfff]) || codegen_in_recompile) { -# else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *) &p->mem[addr & 0xfff])) { -# endif - uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t) 1 << (addr & PAGE_BYTE_MASK_MASK); - - if ((addr & 0xf) == 0xf) - mask |= (mask << 1); - *(uint16_t *) &p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - if ((p->code_present_mask & mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK) { - p->byte_dirty_mask[byte_offset + 1] |= 1; - if ((p->byte_code_present_mask[byte_offset + 1] & 1) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } else - byte_mask |= (byte_mask << 1); - - p->byte_dirty_mask[byte_offset] |= byte_mask; - - if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } -} - -void -mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) -{ - if (p == NULL) - return; - -# ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *) &p->mem[addr & 0xfff]) || codegen_in_recompile) { -# else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *) &p->mem[addr & 0xfff])) { -# endif - uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = (uint64_t) 0xf << (addr & PAGE_BYTE_MASK_MASK); - - if ((addr & 0xf) >= 0xd) - mask |= (mask << 1); - *(uint32_t *) &p->mem[addr & 0xfff] = val; - p->dirty_mask |= mask; - p->byte_dirty_mask[byte_offset] |= byte_mask; - if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask))) - page_add_to_evict_list(p); - if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK - 3)) { - uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3)); - - p->byte_dirty_mask[byte_offset + 1] |= byte_mask_2; - if ((p->byte_code_present_mask[byte_offset + 1] & byte_mask_2) && !page_in_evict_list(p)) - page_add_to_evict_list(p); - } - } -} -#else -void -mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p) -{ - if (p == NULL) - return; - -# ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff]) || codegen_in_recompile) { -# else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != p->mem[addr & 0xfff])) { -# endif - uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - p->mem[addr & 0xfff] = val; - } -} - -void -mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p) -{ - if (p == NULL) - return; - -# ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *) &p->mem[addr & 0xfff]) || codegen_in_recompile) { -# else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint16_t *) &p->mem[addr & 0xfff])) { -# endif - uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if ((addr & 0xf) == 0xf) - mask |= (mask << 1); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - *(uint16_t *) &p->mem[addr & 0xfff] = val; - } -} - -void -mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p) -{ - if (p == NULL) - return; - -# ifdef USE_DYNAREC - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *) &p->mem[addr & 0xfff]) || codegen_in_recompile) { -# else - if ((p->mem == NULL) || (p->mem == page_ff) || (val != *(uint32_t *) &p->mem[addr & 0xfff])) { -# endif - uint64_t mask = (uint64_t) 1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - if ((addr & 0xf) >= 0xd) - mask |= (mask << 1); - p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask; - *(uint32_t *) &p->mem[addr & 0xfff] = val; - } -} -#endif - -void -mem_write_ram(uint32_t addr, uint8_t val, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write B %02X to %08X\n", val, addr); -#endif - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[addr >> 12]); - } else - ram[addr] = val; -} - -void -mem_write_ramw(uint32_t addr, uint16_t val, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write W %04X to %08X\n", val, addr); -#endif - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[addr >> 12]); - } else - *(uint16_t *) &ram[addr] = val; -} - -void -mem_write_raml(uint32_t addr, uint32_t val, void *priv) -{ -#ifdef ENABLE_MEM_LOG - if ((addr >= 0xa0000) && (addr <= 0xbffff)) - mem_log("Write L %08X to %08X\n", val, addr); -#endif - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[addr >> 12]); - } else - *(uint32_t *) &ram[addr] = val; -} - -static uint8_t -mem_read_remapped(uint32_t addr, void *priv) -{ - addr = 0xA0000 + (addr - remap_start_addr); - if (is286) - addreadlookup(mem_logical_addr, addr); - return ram[addr]; -} - -static uint16_t -mem_read_remappedw(uint32_t addr, void *priv) -{ - addr = 0xA0000 + (addr - remap_start_addr); - if (is286) - addreadlookup(mem_logical_addr, addr); - return *(uint16_t *) &ram[addr]; -} - -static uint32_t -mem_read_remappedl(uint32_t addr, void *priv) -{ - addr = 0xA0000 + (addr - remap_start_addr); - if (is286) - addreadlookup(mem_logical_addr, addr); - return *(uint32_t *) &ram[addr]; -} - -static uint8_t -mem_read_remapped2(uint32_t addr, void *priv) -{ - addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) - addreadlookup(mem_logical_addr, addr); - return ram[addr]; -} - -static uint16_t -mem_read_remappedw2(uint32_t addr, void *priv) -{ - addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) - addreadlookup(mem_logical_addr, addr); - return *(uint16_t *) &ram[addr]; -} - -static uint32_t -mem_read_remappedl2(uint32_t addr, void *priv) -{ - addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) - addreadlookup(mem_logical_addr, addr); - return *(uint32_t *) &ram[addr]; -} - -static void -mem_write_remapped(uint32_t addr, uint8_t val, void *priv) -{ - uint32_t oldaddr = addr; - addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); - } else - ram[addr] = val; -} - -static void -mem_write_remappedw(uint32_t addr, uint16_t val, void *priv) -{ - uint32_t oldaddr = addr; - addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); - } else - *(uint16_t *) &ram[addr] = val; -} - -static void -mem_write_remappedl(uint32_t addr, uint32_t val, void *priv) -{ - uint32_t oldaddr = addr; - addr = 0xA0000 + (addr - remap_start_addr); - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); - } else - *(uint32_t *) &ram[addr] = val; -} - -static void -mem_write_remapped2(uint32_t addr, uint8_t val, void *priv) -{ - uint32_t oldaddr = addr; - addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramb_page(addr, val, &pages[oldaddr >> 12]); - } else - ram[addr] = val; -} - -static void -mem_write_remappedw2(uint32_t addr, uint16_t val, void *priv) -{ - uint32_t oldaddr = addr; - addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_ramw_page(addr, val, &pages[oldaddr >> 12]); - } else - *(uint16_t *) &ram[addr] = val; -} - -static void -mem_write_remappedl2(uint32_t addr, uint32_t val, void *priv) -{ - uint32_t oldaddr = addr; - addr = 0xD0000 + (addr - remap_start_addr2); - if (is286) { - addwritelookup(mem_logical_addr, addr); - mem_write_raml_page(addr, val, &pages[oldaddr >> 12]); - } else - *(uint32_t *) &ram[addr] = val; -} - -void -mem_invalidate_range(uint32_t start_addr, uint32_t end_addr) -{ -#ifdef USE_NEW_DYNAREC - page_t *p; - - start_addr &= ~PAGE_MASK_MASK; - end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; - - for (; start_addr <= end_addr; start_addr += 0x1000) { - if ((start_addr >> 12) >= pages_sz) - continue; - - p = &pages[start_addr >> 12]; - if (p) { - p->dirty_mask = 0xffffffffffffffffULL; - - if (p->byte_dirty_mask) - memset(p->byte_dirty_mask, 0xff, 64 * sizeof(uint64_t)); - - if (!page_in_evict_list(p)) - page_add_to_evict_list(p); - } - } -#else - uint32_t cur_addr; - start_addr &= ~PAGE_MASK_MASK; - end_addr = (end_addr + PAGE_MASK_MASK) & ~PAGE_MASK_MASK; - - for (; start_addr <= end_addr; start_addr += 0x1000) { - /* Do nothing if the pages array is empty or DMA reads/writes to/from PCI device memory addresses - may crash the emulator. */ - cur_addr = (start_addr >> 12); - if (cur_addr < pages_sz) - memset(pages[cur_addr].dirty_mask, 0xff, sizeof(pages[cur_addr].dirty_mask)); - } -#endif -} - -static __inline int -mem_mapping_access_allowed(uint32_t flags, uint16_t access) -{ - int ret = 0; - - if (!(access & ACCESS_DISABLED)) { - if (access & ACCESS_CACHE) - ret = (flags & MEM_MAPPING_CACHE); - else if (access & ACCESS_SMRAM) - ret = (flags & MEM_MAPPING_SMRAM); - else if (!(access & ACCESS_INTERNAL)) { - if (flags & MEM_MAPPING_IS_ROM) { - if (access & ACCESS_ROMCS) - ret = (flags & MEM_MAPPING_ROMCS); - else - ret = !(flags & MEM_MAPPING_ROMCS); - } else - ret = 1; - - ret = ret && !(flags & MEM_MAPPING_INTERNAL) && !(flags & MEM_MAPPING_SMRAM); - } else - ret = !(flags & MEM_MAPPING_EXTERNAL) && !(flags & MEM_MAPPING_SMRAM); - } else { - /* Still allow SMRAM if access is DISABLED but also has CACHE and/or SMRAM flags set. */ - if (access & ACCESS_CACHE) - ret = (flags & MEM_MAPPING_CACHE); - else if (access & ACCESS_SMRAM) - ret = (flags & MEM_MAPPING_SMRAM); - } - - return ret; -} - -void -mem_mapping_recalc(uint64_t base, uint64_t size) -{ - mem_mapping_t *map; - int n; - uint64_t c; - - if ((base >= 0xec000000) && (base <= 0xecffffff)) - pclog("mem_mapping_recalc(%016" PRIX64 ", %016" PRIX64 ")\n", base, size); - - if (!size || (base_mapping == NULL)) - return; - - map = base_mapping; - - /* Clear out old mappings. */ - for (c = base; c < base + size; c += MEM_GRANULARITY_SIZE) { - _mem_exec[c >> MEM_GRANULARITY_BITS] = NULL; - write_mapping[c >> MEM_GRANULARITY_BITS] = NULL; - read_mapping[c >> MEM_GRANULARITY_BITS] = NULL; - write_mapping_bus[c >> MEM_GRANULARITY_BITS] = NULL; - read_mapping_bus[c >> MEM_GRANULARITY_BITS] = NULL; - } - - /* Walk mapping list. */ - while (map != NULL) { - /* In range? */ - if (map->enable && (uint64_t) map->base < ((uint64_t) base + (uint64_t) size) && ((uint64_t) map->base + (uint64_t) map->size) > (uint64_t) base) { - uint64_t start = (map->base < base) ? map->base : base; - uint64_t end = (((uint64_t) map->base + (uint64_t) map->size) < (base + size)) ? ((uint64_t) map->base + (uint64_t) map->size) : (base + size); - if (start < map->base) - start = map->base; - - for (c = start; c < end; c += MEM_GRANULARITY_SIZE) { - /* CPU */ - n = !!in_smm; - if ((c >= 0xec000000) && (c <= 0xecffffff)) - pclog("mem_mapping_recalc(): map = %08X (%02X) (%02X, %02X, %02X)\n", map, map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].x); - if (map->exec && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].x)) - _mem_exec[c >> MEM_GRANULARITY_BITS] = map->exec + (c - map->base); - if ((map->write_b || map->write_w || map->write_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) - write_mapping[c >> MEM_GRANULARITY_BITS] = map; - if ((map->read_b || map->read_w || map->read_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) - read_mapping[c >> MEM_GRANULARITY_BITS] = map; - - /* Bus */ - n |= STATE_BUS; - if ((map->write_b || map->write_w || map->write_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].w)) - write_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; - if ((map->read_b || map->read_w || map->read_l) && mem_mapping_access_allowed(map->flags, _mem_state[c >> MEM_GRANULARITY_BITS].states[n].r)) - read_mapping_bus[c >> MEM_GRANULARITY_BITS] = map; - } - } - map = map->next; - } - - flushmmucache_cr3(); - -#ifdef ENABLE_MEM_LOG - pclog("\nMemory map:\n"); - mem_mapping_t *write = (mem_mapping_t *) -1, *read = (mem_mapping_t *) -1, *write_bus = (mem_mapping_t *) -1, *read_bus = (mem_mapping_t *) -1; - for (c = 0; c < (sizeof(write_mapping) / sizeof(write_mapping[0])); c++) { - if ((write_mapping[c] == write) && (read_mapping[c] == read) && (write_mapping_bus[c] == write_bus) && (read_mapping_bus[c] == read_bus)) - continue; - write = write_mapping[c]; - read = read_mapping[c]; - write_bus = write_mapping_bus[c]; - read_bus = read_mapping_bus[c]; - - pclog("%08X | ", c << MEM_GRANULARITY_BITS); - if (read) { - pclog("R%c%c%c %08X+% 8X", - read->read_b ? 'b' : ' ', read->read_w ? 'w' : ' ', read->read_l ? 'l' : ' ', - read->base, read->size); - } else { - pclog(" "); - } - if (write) { - pclog(" | W%c%c%c %08X+% 8X", - write->write_b ? 'b' : ' ', write->write_w ? 'w' : ' ', write->write_l ? 'l' : ' ', - write->base, write->size); - } else { - pclog(" | "); - } - pclog(" | %c\n", _mem_exec[c] ? 'X' : ' '); - - if ((write != write_bus) || (read != read_bus)) { - pclog(" ^ bus | "); - if (read_bus) { - pclog("R%c%c%c %08X+% 8X", - read_bus->read_b ? 'b' : ' ', read_bus->read_w ? 'w' : ' ', read_bus->read_l ? 'l' : ' ', - read_bus->base, read_bus->size); - } else { - pclog(" "); - } - if (write_bus) { - pclog(" | W%c%c%c %08X+% 8X", - write_bus->write_b ? 'b' : ' ', write_bus->write_w ? 'w' : ' ', write_bus->write_l ? 'l' : ' ', - write_bus->base, write_bus->size); - } else { - pclog(" | "); - } - pclog(" |\n"); - } - } - pclog("\n"); -#endif -} - -void -mem_mapping_set(mem_mapping_t *map, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t fl, - void *p) -{ - if (size != 0x00000000) - map->enable = 1; - else - map->enable = 0; - map->base = base; - map->size = size; - map->mask = (map->size ? 0xffffffff : 0x00000000); - map->read_b = read_b; - map->read_w = read_w; - map->read_l = read_l; - map->write_b = write_b; - map->write_w = write_w; - map->write_l = write_l; - map->exec = exec; - map->flags = fl; - map->p = p; - map->next = NULL; - mem_log("mem_mapping_add(): Linked list structure: %08X -> %08X -> %08X\n", map->prev, map, map->next); - - /* If the mapping is disabled, there is no need to recalc anything. */ - if (size != 0x00000000) - mem_mapping_recalc(map->base, map->size); -} - -void -mem_mapping_add(mem_mapping_t *map, - uint32_t base, - uint32_t size, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p), - uint8_t *exec, - uint32_t fl, - void *p) -{ - /* Do a sanity check */ - if ((base_mapping == NULL) && (last_mapping != NULL)) { - fatal("mem_mapping_add(): NULL base mapping with non-NULL last mapping\n"); - return; - } else if ((base_mapping != NULL) && (last_mapping == NULL)) { - fatal("mem_mapping_add(): Non-NULL base mapping with NULL last mapping\n"); - return; - } else if ((base_mapping != NULL) && (base_mapping->prev != NULL)) { - fatal("mem_mapping_add(): Base mapping with a preceding mapping\n"); - return; - } else if ((last_mapping != NULL) && (last_mapping->next != NULL)) { - fatal("mem_mapping_add(): Last mapping with a following mapping\n"); - return; - } - - /* Add mapping to the beginning of the list if necessary.*/ - if (base_mapping == NULL) - base_mapping = map; - - /* Add mapping to the end of the list.*/ - if (last_mapping == NULL) - map->prev = NULL; - else { - map->prev = last_mapping; - last_mapping->next = map; - } - last_mapping = map; - - mem_mapping_set(map, base, size, read_b, read_w, read_l, - write_b, write_w, write_l, exec, fl, p); -} - -void -mem_mapping_do_recalc(mem_mapping_t *map) -{ - mem_mapping_recalc(map->base, map->size); -} - -void -mem_mapping_set_handler(mem_mapping_t *map, - uint8_t (*read_b)(uint32_t addr, void *p), - uint16_t (*read_w)(uint32_t addr, void *p), - uint32_t (*read_l)(uint32_t addr, void *p), - void (*write_b)(uint32_t addr, uint8_t val, void *p), - void (*write_w)(uint32_t addr, uint16_t val, void *p), - void (*write_l)(uint32_t addr, uint32_t val, void *p)) -{ - map->read_b = read_b; - map->read_w = read_w; - map->read_l = read_l; - map->write_b = write_b; - map->write_w = write_w; - map->write_l = write_l; - - mem_mapping_recalc(map->base, map->size); -} - -void -mem_mapping_set_addr(mem_mapping_t *map, uint32_t base, uint32_t size) -{ - if ((base >= 0xec000000) && (base <= 0xecffffff)) - pclog("[0] mem_mapping_set_addr(%08X, %08X)\n", base, size); - - /* Remove old mapping. */ - map->enable = 0; - mem_mapping_recalc(map->base, map->size); - - if ((base >= 0xec000000) && (base <= 0xecffffff)) - pclog("[1] mem_mapping_set_addr(%08X, %08X)\n", base, size); - - /* Set new mapping. */ - map->enable = 1; - map->base = base; - map->size = size; - - if ((base >= 0xec000000) && (base <= 0xecffffff)) - pclog("[2] mem_mapping_set_addr(%08X, %08X)\n", base, size); - - mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); -} - -void -mem_mapping_set_exec(mem_mapping_t *map, uint8_t *exec) -{ - map->exec = exec; - - mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); -} - -void -mem_mapping_set_mask(mem_mapping_t *map, uint32_t mask) -{ - map->mask = mask; - - mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); -} - -void -mem_mapping_set_p(mem_mapping_t *map, void *p) -{ - map->p = p; -} - -void -mem_mapping_disable(mem_mapping_t *map) -{ - map->enable = 0; - - mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); -} - -void -mem_mapping_enable(mem_mapping_t *map) -{ - map->enable = 1; - - mem_mapping_recalc((uint64_t) map->base, (uint64_t) map->size); -} - -void -mem_set_access(uint8_t bitmap, int mode, uint32_t base, uint32_t size, uint16_t access) -{ - uint32_t c; - uint16_t mask, smstate = 0x0000; - const uint16_t smstates[4] = { 0x0000, (MEM_READ_SMRAM | MEM_WRITE_SMRAM), - MEM_READ_SMRAM_EX, (MEM_READ_DISABLED_EX | MEM_WRITE_DISABLED_EX) }; - - int i; - - if (mode) - mask = 0x2d6b; - else - mask = 0x1084; - - if (mode) { - if (mode == 1) - access = !!access; - - if (mode == 3) { - if (access & ACCESS_SMRAM_X) - smstate |= MEM_EXEC_SMRAM; - if (access & ACCESS_SMRAM_R) - smstate |= MEM_READ_SMRAM_2; - if (access & ACCESS_SMRAM_W) - smstate |= MEM_WRITE_SMRAM; - } else - smstate = smstates[access & 0x07]; - } else - smstate = access & 0x6f7b; - - for (c = 0; c < size; c += MEM_GRANULARITY_SIZE) { - for (i = 0; i < 4; i++) { - if (bitmap & (1 << i)) { - _mem_state[(c + base) >> MEM_GRANULARITY_BITS].vals[i] = (_mem_state[(c + base) >> MEM_GRANULARITY_BITS].vals[i] & mask) | smstate; - } - } - -#ifdef ENABLE_MEM_LOG - if (((c + base) >= 0xa0000) && ((c + base) <= 0xbffff)) { - mem_log("Set mem state for block at %08X to %04X with bitmap %02X\n", - c + base, smstate, bitmap); - } -#endif - } - - mem_mapping_recalc(base, size); -} - -void -mem_a20_init(void) -{ - if (is286) { - mem_a20_key = mem_a20_alt = mem_a20_state = 0; - rammask = cpu_16bitbus ? 0xffffff : 0xffffffff; - if (is6117) - rammask |= 0x03000000; - flushmmucache(); - // mem_a20_state = mem_a20_key | mem_a20_alt; - } else { - rammask = 0xfffff; - flushmmucache(); - mem_a20_key = mem_a20_alt = mem_a20_state = 0; - } -} - -/* Close all the memory mappings. */ -void -mem_close(void) -{ - mem_mapping_t *map = base_mapping, *next; - - while (map != NULL) { - next = map->next; - map->prev = map->next = NULL; - map = next; - } - - base_mapping = last_mapping = 0; -} - -static void -mem_add_ram_mapping(mem_mapping_t *mapping, uint32_t base, uint32_t size) -{ - mem_mapping_add(mapping, base, size, - mem_read_ram, mem_read_ramw, mem_read_raml, - mem_write_ram, mem_write_ramw, mem_write_raml, - ram + base, MEM_MAPPING_INTERNAL, NULL); -} - -static void -mem_init_ram_mapping(mem_mapping_t *mapping, uint32_t base, uint32_t size) -{ - mem_set_mem_state_both(base, size, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_add_ram_mapping(mapping, base, size); -} - -/* Reset the memory state. */ -void -mem_reset(void) -{ - uint32_t c; - size_t m; - - memset(page_ff, 0xff, sizeof(page_ff)); - -#ifdef USE_NEW_DYNAREC - if (byte_dirty_mask) { - free(byte_dirty_mask); - byte_dirty_mask = NULL; - } - - if (byte_code_present_mask) { - free(byte_code_present_mask); - byte_code_present_mask = NULL; - } -#endif - - /* Free the old pages array, if necessary. */ - if (pages) { - free(pages); - pages = NULL; - } - - if (ram != NULL) { - plat_munmap(ram, ram_size); - ram = NULL; - ram_size = 0; - } -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - if (ram2 != NULL) { - plat_munmap(ram2, ram2_size); - ram2 = NULL; - ram2_size = 0; - } - - if (mem_size > 2097152) - mem_size = 2097152; -#endif - - m = 1024UL * (size_t) mem_size; - -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - if (mem_size > 1048576) { - ram_size = 1 << 30; - ram = (uint8_t *) plat_mmap(ram_size, 0); /* allocate and clear the RAM block of the first 1 GB */ - if (ram == NULL) { - fatal("Failed to allocate primary RAM block. Make sure you have enough RAM available.\n"); - return; - } - memset(ram, 0x00, ram_size); - ram2_size = m - (1 << 30); - ram2 = (uint8_t *) plat_mmap(ram2_size, 0); /* allocate and clear the RAM block above 1 GB */ - if (ram2 == NULL) { - if (config_changed == 2) - fatal(EMU_NAME " must be restarted for the memory amount change to be applied.\n"); - else - fatal("Failed to allocate secondary RAM block. Make sure you have enough RAM available.\n"); - return; - } - memset(ram2, 0x00, ram2_size); - } else -#endif - { - ram_size = m; - ram = (uint8_t *) plat_mmap(ram_size, 0); /* allocate and clear the RAM block */ - if (ram == NULL) { - fatal("Failed to allocate RAM block. Make sure you have enough RAM available.\n"); - return; - } - memset(ram, 0x00, ram_size); - if (mem_size > 1048576) - ram2 = &(ram[1 << 30]); - } - - /* - * Allocate the page table based on how much RAM we have. - * We re-allocate the table on each (hard) reset, as the - * memory amount could have changed. - */ - if (is286) { - if (cpu_16bitbus) { - /* 80286/386SX; maximum address space is 16MB. */ - m = 4096; - /* ALi M6117; maximum address space is 64MB. */ - if (is6117) - m <<= 2; - } else { - /* 80386DX+; maximum address space is 4GB. */ - m = 1048576; - } - } else { - /* 8088/86; maximum address space is 1MB. */ - m = 256; - } - - addr_space_size = m; - - /* - * Allocate and initialize the (new) page table. - */ - pages_sz = m; - pages = (page_t *) malloc(m * sizeof(page_t)); - - memset(page_lookup, 0x00, (1 << 20) * sizeof(page_t *)); - memset(page_lookupp, 0x04, (1 << 20) * sizeof(uint8_t)); - - memset(pages, 0x00, pages_sz * sizeof(page_t)); - -#ifdef USE_NEW_DYNAREC - byte_dirty_mask = malloc((mem_size * 1024) / 8); - memset(byte_dirty_mask, 0, (mem_size * 1024) / 8); - - byte_code_present_mask = malloc((mem_size * 1024) / 8); - memset(byte_code_present_mask, 0, (mem_size * 1024) / 8); -#endif - - for (c = 0; c < pages_sz; c++) { - if ((c << 12) >= (mem_size << 10)) - pages[c].mem = page_ff; - else { -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - if (mem_size > 1048576) { - if ((c << 12) < (1 << 30)) - pages[c].mem = &ram[c << 12]; - else - pages[c].mem = &ram2[(c << 12) - (1 << 30)]; - } else - pages[c].mem = &ram[c << 12]; -#else - pages[c].mem = &ram[c << 12]; -#endif - } - if (c < m) { - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; - } -#ifdef USE_NEW_DYNAREC - pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; -#endif - } - - memset(_mem_exec, 0x00, sizeof(_mem_exec)); - memset(write_mapping, 0x00, sizeof(write_mapping)); - memset(read_mapping, 0x00, sizeof(read_mapping)); - memset(write_mapping_bus, 0x00, sizeof(write_mapping_bus)); - memset(read_mapping_bus, 0x00, sizeof(read_mapping_bus)); - - base_mapping = last_mapping = NULL; - - /* Set the entire memory space as external. */ - memset(_mem_state, 0x00, sizeof(_mem_state)); - - /* Set the low RAM space as internal. */ - mem_init_ram_mapping(&ram_low_mapping, 0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024); - - if (mem_size > 1024) { - if (cpu_16bitbus && !is6117 && mem_size > 16256) - mem_init_ram_mapping(&ram_high_mapping, 0x100000, (16256 - 1024) * 1024); - else if (cpu_16bitbus && is6117 && mem_size > 65408) - mem_init_ram_mapping(&ram_high_mapping, 0x100000, (65408 - 1024) * 1024); - else { - if (mem_size > 1048576) { - mem_init_ram_mapping(&ram_high_mapping, 0x100000, (1048576 - 1024) * 1024); - - mem_set_mem_state_both((1 << 30), (mem_size - 1048576) * 1024, - MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_mapping_add(&ram_2gb_mapping, (1 << 30), - ((mem_size - 1048576) * 1024), - mem_read_ram_2gb, mem_read_ram_2gbw, mem_read_ram_2gbl, - mem_write_ram, mem_write_ramw, mem_write_raml, - ram2, MEM_MAPPING_INTERNAL, NULL); - } else - mem_init_ram_mapping(&ram_high_mapping, 0x100000, (mem_size - 1024) * 1024); - } - } - - if (mem_size > 768) { - mem_add_ram_mapping(&ram_mid_mapping, 0xa0000, 0x60000); - - mem_add_ram_mapping(&ram_mid_mapping2, 0xa0000, 0x60000); - mem_mapping_disable(&ram_mid_mapping2); - } - - mem_mapping_add(&ram_remapped_mapping, mem_size * 1024, 256 * 1024, - mem_read_remapped, mem_read_remappedw, mem_read_remappedl, - mem_write_remapped, mem_write_remappedw, mem_write_remappedl, - ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_remapped_mapping); - - /* Mapping for SiS 471 relocation which relocates A0000-BFFFF, D0000-EFFFF, which is non-contiguous. */ - mem_mapping_add(&ram_remapped_mapping2, mem_size * 1024, 256 * 1024, - mem_read_remapped2, mem_read_remappedw2, mem_read_remappedl2, - mem_write_remapped2, mem_write_remappedw2, mem_write_remappedl2, - ram + 0xd0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_disable(&ram_remapped_mapping2); - - mem_a20_init(); - -#ifdef USE_NEW_DYNAREC - purgable_page_list_head = 0; - purgeable_page_count = 0; -#endif -} - -void -mem_init(void) -{ - /* Perform a one-time init. */ - ram = rom = NULL; - ram2 = NULL; - pages = NULL; - - /* Allocate the lookup tables. */ - page_lookup = (page_t **) malloc((1 << 20) * sizeof(page_t *)); - page_lookupp = (uint8_t *) malloc((1 << 20) * sizeof(uint8_t)); - readlookup2 = malloc((1 << 20) * sizeof(uintptr_t)); - readlookupp = malloc((1 << 20) * sizeof(uint8_t)); - writelookup2 = malloc((1 << 20) * sizeof(uintptr_t)); - writelookupp = malloc((1 << 20) * sizeof(uint8_t)); -} - -void -mem_remap_top(int kb) -{ - uint32_t c; - uint32_t start = (mem_size >= 1024) ? mem_size : 1024; - int offset, size = mem_size - 640; - int set = 1; - static int old_kb = 0; - int sis_mode = 0; - uint32_t start_addr = 0, addr = 0; - - mem_log("MEM: remapping top %iKB (mem=%i)\n", kb, mem_size); - if (mem_size <= 640) - return; - - /* SiS 471 special mode. */ - if (kb == -256) { - kb = 256; - sis_mode = 1; - } - - /* Do not remap if we're have more than (16 MB - RAM) memory. */ - if ((kb != 0) && (mem_size >= (16384 - kb))) - return; - - if (kb == 0) { - kb = old_kb; - set = 0; - } else - old_kb = kb; - - if (size > kb) - size = kb; - - remap_start_addr = start << 10; - remap_start_addr2 = (start << 10) + 0x00020000; - - for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++) { - offset = c - ((start * 1024) >> 12); - /* Use A0000-BFFFF, D0000-EFFFF instead of C0000-DFFFF, E0000-FFFFF. */ - addr = 0xa0000 + (offset << 12); - if (sis_mode) { - /* A0000-DFFFF -> A0000-BFFFF, D0000-EFFFF */ - if (addr >= 0x000c0000) - addr += 0x00010000; - } - if (start_addr == 0) - start_addr = addr; - pages[c].mem = set ? &ram[addr] : page_ff; - pages[c].write_b = set ? mem_write_ramb_page : NULL; - pages[c].write_w = set ? mem_write_ramw_page : NULL; - pages[c].write_l = set ? mem_write_raml_page : NULL; -#ifdef USE_NEW_DYNAREC - pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[(addr >> 12) * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[(addr >> 12) * 64]; -#endif - } - - mem_set_mem_state_both(start * 1024, size * 1024, set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); - - for (c = 0xa0; c < 0xf0; c++) { - if ((c >= 0xc0) && (c <= 0xcf)) - continue; - - if (sis_mode || ((c << 12) >= (mem_size << 10))) - pages[c].mem = page_ff; - else { -#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)) - if (mem_size > 1048576) { - if ((c << 12) < (1 << 30)) - pages[c].mem = &ram[c << 12]; - else - pages[c].mem = &ram2[(c << 12) - (1 << 30)]; - } else - pages[c].mem = &ram[c << 12]; -#else - pages[c].mem = &ram[c << 12]; -#endif - } - if (!sis_mode && (c < addr_space_size)) { - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; - } else { - pages[c].write_b = NULL; - pages[c].write_w = NULL; - pages[c].write_l = NULL; - } -#ifdef USE_NEW_DYNAREC - pages[c].evict_prev = EVICT_NOT_IN_LIST; - pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64]; - pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64]; -#endif - } - - if (set) { - if (sis_mode) { - mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, 0x00020000); - mem_mapping_set_exec(&ram_remapped_mapping, ram + 0x000a0000); - mem_mapping_set_addr(&ram_remapped_mapping2, (start * 1024) + 0x00020000, 0x00020000); - mem_mapping_set_exec(&ram_remapped_mapping2, ram + 0x000d0000); - - mem_mapping_set_addr(&ram_mid_mapping, 0x000c0000, 0x00010000); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000c0000); - mem_mapping_set_addr(&ram_mid_mapping2, 0x000f0000, 0x00010000); - mem_mapping_set_exec(&ram_mid_mapping2, ram + 0x000f0000); - } else { - mem_mapping_set_addr(&ram_remapped_mapping, start * 1024, size * 1024); - mem_mapping_set_exec(&ram_remapped_mapping, ram + start_addr); - mem_mapping_disable(&ram_remapped_mapping2); - - mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); - mem_mapping_disable(&ram_mid_mapping2); - } - } else { - mem_mapping_disable(&ram_remapped_mapping); - mem_mapping_disable(&ram_remapped_mapping2); - - mem_mapping_set_addr(&ram_mid_mapping, 0x000a0000, 0x00060000); - mem_mapping_set_exec(&ram_mid_mapping, ram + 0x000a0000); - mem_mapping_disable(&ram_mid_mapping2); - } - - flushmmucache(); -} - -void -mem_reset_page_blocks(void) -{ - uint32_t c; - - if (pages == NULL) - return; - - for (c = 0; c < pages_sz; c++) { - pages[c].write_b = mem_write_ramb_page; - pages[c].write_w = mem_write_ramw_page; - pages[c].write_l = mem_write_raml_page; -#ifdef USE_NEW_DYNAREC - pages[c].block = BLOCK_INVALID; - pages[c].block_2 = BLOCK_INVALID; - pages[c].head = BLOCK_INVALID; -#else - pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL; - pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL; - pages[c].head = NULL; -#endif - } -} - -void -mem_a20_recalc(void) -{ - int state; - - if (!is286) { - rammask = 0xfffff; - flushmmucache(); - mem_a20_key = mem_a20_alt = mem_a20_state = 0; - - return; - } - - state = mem_a20_key | mem_a20_alt; - if (state && !mem_a20_state) { - rammask = (cpu_16bitbus) ? 0xffffff : 0xffffffff; - if (is6117) - rammask |= 0x03000000; - flushmmucache(); - } else if (!state && mem_a20_state) { - rammask = (cpu_16bitbus) ? 0xefffff : 0xffefffff; - if (is6117) - rammask |= 0x03000000; - flushmmucache(); - } - - mem_a20_state = state; -} diff --git a/src/mouse.patch b/src/mouse.patch deleted file mode 100644 index 4d9d67d2a..000000000 --- a/src/mouse.patch +++ /dev/null @@ -1,69 +0,0 @@ -diff --git a/src/86box.c b/src/86box.c -index a14f51c41..3c96d88a4 100644 ---- a/src/86box.c -+++ b/src/86box.c -@@ -1263,9 +1263,9 @@ pc_run(void) - startblit(); - cpu_exec(cpu_s->rspeed / 100); - #ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ -- if (gdbstub_step == GDBSTUB_EXEC) -+ // if (gdbstub_step == GDBSTUB_EXEC) - #endif -- mouse_process(); -+ // mouse_process(); - joystick_process(); - endblit(); - -diff --git a/src/device/mouse.c b/src/device/mouse.c -index 7eb6a08a9..329397d43 100644 ---- a/src/device/mouse.c -+++ b/src/device/mouse.c -@@ -27,6 +27,8 @@ - #define HAVE_STDARG_H - #include <86box/86box.h> - #include <86box/device.h> -+#include <86box/timer.h> -+#include <86box/gdbstub.h> - #include <86box/mouse.h> - - typedef struct { -@@ -45,6 +47,8 @@ int mouse_x, - double mouse_x_abs, - mouse_y_abs; - -+pc_timer_t mouse_timer; /* mouse event timer */ -+ - static const device_t mouse_none_device = { - .name = "None", - .internal_name = "none", -@@ -141,6 +145,20 @@ mouse_close(void) - mouse_priv = NULL; - mouse_nbut = 0; - mouse_dev_poll = NULL; -+ -+ timer_stop(&mouse_timer); -+} -+ -+static void -+mouse_timer_poll(void *priv) -+{ -+ // timer_on_auto(&mouse_timer, 1388.0 + (8.0 / 9.0)); -+ timer_on_auto(&mouse_timer, 277.0 + (7.0 / 9.0)); -+ -+#ifdef USE_GDBSTUB /* avoid a KBC FIFO overflow when CPU emulation is stalled */ -+ if (gdbstub_step == GDBSTUB_EXEC) -+#endif -+ mouse_process(); - } - - void -@@ -165,6 +183,9 @@ mouse_reset(void) - - if (mouse_curr != NULL) - mouse_priv = device_add(mouse_curr); -+ -+ timer_add(&mouse_timer, mouse_timer_poll, NULL, 0); -+ timer_on_auto(&mouse_timer, 10000.0); - } - - /* Callback from the hardware driver. */ diff --git a/src/pic - Cópia.c b/src/pic - Cópia.c deleted file mode 100644 index 70a8a7805..000000000 --- a/src/pic - Cópia.c +++ /dev/null @@ -1,838 +0,0 @@ -/* - * 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. - * - * Implementation of the Intel PIC chip emulation, partially - * ported from reenigne's XTCE. - * - * - * - * Authors: Andrew Jenner, - * Miran Grca, - * - * Copyright 2015-2020 Andrew Jenner. - * Copyright 2016-2020 Miran Grca. - */ -#include -#include -#include -#include -#include -#include - -#define HAVE_STDARG_H -#include <86box/86box.h> -#include "cpu.h" -#include <86box/machine.h> -#include <86box/io.h> -#include <86box/pci.h> -#include <86box/pic.h> -#include <86box/timer.h> -#include <86box/pit.h> -#include <86box/device.h> -#include <86box/apm.h> -#include <86box/nvr.h> -#include <86box/acpi.h> - -enum { - STATE_NONE = 0, - STATE_ICW2, - STATE_ICW3, - STATE_ICW4 -}; - -pic_t pic, pic2; - -static pc_timer_t pic_timer; - -static int shadow = 0, elcr_enabled = 0, - tmr_inited = 0, latched = 0, - pic_pci = 0, kbd_latch = 0, - mouse_latch = 0; - -static uint16_t smi_irq_mask = 0x0000, - smi_irq_status = 0x0000; - -static uint16_t latched_irqs = 0x0000; - -static void (*update_pending)(void); - -#ifdef ENABLE_PIC_LOG -int pic_do_log = ENABLE_PIC_LOG; - -static void -pic_log(const char *fmt, ...) -{ - va_list ap; - - if (pic_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -} -#else -# define pic_log(fmt, ...) -#endif - -void -pic_reset_smi_irq_mask(void) -{ - smi_irq_mask = 0x0000; -} - -void -pic_set_smi_irq_mask(int irq, int set) -{ - if ((irq >= 0) && (irq <= 15)) { - if (set) - smi_irq_mask |= (1 << irq); - else - smi_irq_mask &= ~(1 << irq); - } -} - -uint16_t -pic_get_smi_irq_status(void) -{ - return smi_irq_status; -} - -void -pic_clear_smi_irq_status(int irq) -{ - if ((irq >= 0) && (irq <= 15)) - smi_irq_status &= ~(1 << irq); -} - -void -pic_elcr_write(uint16_t port, uint8_t val, void *priv) -{ - pic_t *dev = (pic_t *) priv; - - pic_log("ELCR%i: WRITE %02X\n", port & 1, val); - - if (port & 1) - val &= 0xde; - else - val &= 0xf8; - - dev->elcr = val; - - pic_log("ELCR %i: %c %c %c %c %c %c %c %c\n", - port & 1, - (val & 1) ? 'L' : 'E', - (val & 2) ? 'L' : 'E', - (val & 4) ? 'L' : 'E', - (val & 8) ? 'L' : 'E', - (val & 0x10) ? 'L' : 'E', - (val & 0x20) ? 'L' : 'E', - (val & 0x40) ? 'L' : 'E', - (val & 0x80) ? 'L' : 'E'); -} - -uint8_t -pic_elcr_read(uint16_t port, void *priv) -{ - pic_t *dev = (pic_t *) priv; - - pic_log("ELCR%i: READ %02X\n", port & 1, dev->elcr); - - return dev->elcr; -} - -int -pic_elcr_get_enabled(void) -{ - return elcr_enabled; -} - -void -pic_elcr_set_enabled(int enabled) -{ - elcr_enabled = enabled; -} - -void -pic_elcr_io_handler(int set) -{ - io_handler(set, 0x04d0, 0x0001, - pic_elcr_read, NULL, NULL, - pic_elcr_write, NULL, NULL, &pic); - io_handler(set, 0x04d1, 0x0001, - pic_elcr_read, NULL, NULL, - pic_elcr_write, NULL, NULL, &pic2); -} - -static uint8_t -pic_cascade_mode(pic_t *dev) -{ - return !(dev->icw1 & 2); -} - -static __inline uint8_t -pic_slave_on(pic_t *dev, int channel) -{ - pic_log("pic_slave_on(%i): %i, %02X, %02X\n", channel, pic_cascade_mode(dev), dev->icw4 & 0x0c, dev->icw3 & (1 << channel)); - - return pic_cascade_mode(dev) && (dev->is_master || ((dev->icw4 & 0x0c) == 0x0c)) && (dev->icw3 & (1 << channel)); -} - -static __inline int -find_best_interrupt(pic_t *dev) -{ - uint8_t b; - uint8_t intr; - int i, j; - int ret = -1; - - for (i = 0; i < 8; i++) { - j = (i + dev->priority) & 7; - b = 1 << j; - - if (dev->isr & b) - break; - else if ((dev->state == 0) && ((dev->irr & ~dev->imr) & b)) { - ret = j; - break; - } - } - - intr = dev->interrupt = (ret == -1) ? 0x17 : ret; - - if (dev->at && (ret != -1)) { - if (dev == &pic2) - intr += 8; - - if (cpu_fast_off_flags & (1u << intr)) - cpu_fast_off_advance(); - } - - return ret; -} - -static __inline void -pic_update_pending_xt(void) -{ - if (find_best_interrupt(&pic) != -1) { - latched++; - if (latched == 1) - timer_on_auto(&pic_timer, 0.35); - } else if (latched == 0) - pic.int_pending = 0; -} - -static __inline void -pic_update_pending_at(void) -{ - pic2.int_pending = (find_best_interrupt(&pic2) != -1); - - if (pic2.int_pending) - pic.irr |= (1 << pic2.icw3); - else - pic.irr &= ~(1 << pic2.icw3); - - pic.int_pending = (find_best_interrupt(&pic) != -1); -} - -static void -pic_callback(void *priv) -{ - pic_t *dev = (pic_t *) priv; - - dev->int_pending = 1; - - latched--; - if (latched > 0) - timer_on_auto(&pic_timer, 0.35); -} - -void -pic_reset(void) -{ - int is_at = IS_AT(machine); - is_at = is_at || !strcmp(machine_get_internal_name(), "xi8088"); - - memset(&pic, 0, sizeof(pic_t)); - memset(&pic2, 0, sizeof(pic_t)); - - pic.is_master = 1; - pic.interrupt = pic2.interrupt = 0x17; - - if (is_at) - pic.slaves[2] = &pic2; - - if (tmr_inited) - timer_on_auto(&pic_timer, 0.0); - memset(&pic_timer, 0x00, sizeof(pc_timer_t)); - timer_add(&pic_timer, pic_callback, &pic, 0); - tmr_inited = 1; - - update_pending = is_at ? pic_update_pending_at : pic_update_pending_xt; - pic.at = pic2.at = is_at; - - smi_irq_mask = smi_irq_status = 0x0000; - - shadow = 0; - pic_pci = 0; -} - -void -pic_set_shadow(int sh) -{ - shadow = sh; -} - -int -pic_get_pci_flag(void) -{ - return pic_pci; -} - -void -pic_set_pci_flag(int pci) -{ - pic_pci = pci; -} - -static uint8_t -pic_level_triggered(pic_t *dev, int irq) -{ - if (elcr_enabled) - return !!(dev->elcr & (1 << irq)); - else - return !!(dev->icw1 & 8); -} - -int -picint_is_level(int irq) -{ - return pic_level_triggered(((irq > 7) ? &pic2 : &pic), irq & 7); -} - -static void -pic_acknowledge(pic_t *dev) -{ - int pic_int = dev->interrupt & 7; - int pic_int_num = 1 << pic_int; - - dev->isr |= pic_int_num; - if (!pic_level_triggered(dev, pic_int) || !(dev->lines & pic_int_num)) - dev->irr &= ~pic_int_num; -} - -/* Find IRQ for non-specific EOI (either by command or automatic) by finding the highest IRQ - priority with ISR bit set, that is also not masked if the PIC is in special mask mode. */ -static uint8_t -pic_non_specific_find(pic_t *dev) -{ - int i, j; - uint8_t b, irq = 0xff; - - for (i = 0; i < 8; i++) { - j = (i + dev->priority) & 7; - b = (1 << j); - - if ((dev->isr & b) && (!dev->special_mask_mode || !(dev->imr & b))) { - irq = j; - break; - } - } - - return irq; -} - -/* Do the EOI and rotation, if either is requested, on the given IRQ. */ -static void -pic_action(pic_t *dev, uint8_t irq, uint8_t eoi, uint8_t rotate) -{ - uint8_t b = (1 << irq); - - if (irq != 0xff) { - if (eoi) - dev->isr &= ~b; - if (rotate) - dev->priority = (irq + 1) & 7; - - update_pending(); - } -} - -/* Automatic non-specific EOI. */ -static __inline void -pic_auto_non_specific_eoi(pic_t *dev) -{ - uint8_t irq; - - if (dev->icw4 & 2) { - irq = pic_non_specific_find(dev); - - pic_action(dev, irq, 1, dev->auto_eoi_rotate); - } -} - -/* Do the PIC command specified by bits 7-5 of the value written to the OCW2 register. */ -static void -pic_command(pic_t *dev) -{ - uint8_t irq = 0xff; - - if (dev->ocw2 & 0x60) { /* SL and/or EOI set */ - if (dev->ocw2 & 0x40) /* SL set, specific priority level */ - irq = (dev->ocw2 & 0x07); - else /* SL clear, non-specific priority level (find highest with ISR set) */ - irq = pic_non_specific_find(dev); - - pic_action(dev, irq, dev->ocw2 & 0x20, dev->ocw2 & 0x80); - } else /* SL and EOI clear */ - dev->auto_eoi_rotate = !!(dev->ocw2 & 0x80); -} - -uint8_t -pic_latch_read(uint16_t addr, void *priv) -{ - uint8_t ret = 0xff; - - pic_log("pic_latch_read(%i, %i): %02X%02X\n", kbd_latch, mouse_latch, pic2.lines & 0x10, pic.lines & 0x02); - - if (kbd_latch && (latched_irqs & 0x0002)) - picintc(0x0002); - - if (mouse_latch && (latched_irqs & 0x1000)) - picintc(0x1000); - - /* Return FF - we just lower IRQ 1 and IRQ 12. */ - return ret; -} - -uint8_t -pic_read(uint16_t addr, void *priv) -{ - pic_t *dev = (pic_t *) priv; - - if (shadow) { - /* VIA PIC shadow read */ - if (addr & 0x0001) - dev->data_bus = ((dev->icw2 & 0xf8) >> 3) << 0; - else { - dev->data_bus = ((dev->ocw3 & 0x20) >> 5) << 4; - dev->data_bus |= ((dev->ocw2 & 0x80) >> 7) << 3; - dev->data_bus |= ((dev->icw4 & 0x10) >> 4) << 2; - dev->data_bus |= ((dev->icw4 & 0x02) >> 1) << 1; - dev->data_bus |= ((dev->icw4 & 0x08) >> 3) << 0; - } - } else { - /* Standard 8259 PIC read */ -#ifndef UNDEFINED_READ - /* Put the IRR on to the data bus by default until the real PIC is probed. */ - dev->data_bus = dev->irr; -#endif - if (dev->ocw3 & 0x04) { - dev->interrupt &= ~0x20; /* Freeze the interrupt until the poll is over. */ - if (dev->int_pending) { - dev->data_bus = 0x80 | (dev->interrupt & 7); - pic_acknowledge(dev); - dev->int_pending = 0; - update_pending(); - } else - dev->data_bus = 0x00; - dev->ocw3 &= ~0x04; - } else if (addr & 0x0001) - dev->data_bus = dev->imr; - else if (dev->ocw3 & 0x02) { - if (dev->ocw3 & 0x01) - dev->data_bus = dev->isr; -#ifdef UNDEFINED_READ - else - dev->data_bus = 0x00; -#endif - } - /* If A0 = 0, VIA shadow is disabled, and poll mode is disabled, - simply read whatever is currently on the data bus. */ - } - - pic_log("pic_read(%04X, %08X) = %02X\n", addr, priv, dev->data_bus); - - return dev->data_bus; -} - -static void -pic_write(uint16_t addr, uint8_t val, void *priv) -{ - pic_t *dev = (pic_t *) priv; - - pic_log("pic_write(%04X, %02X, %08X)\n", addr, val, priv); - - dev->data_bus = val; - - if (addr & 0x0001) { - switch (dev->state) { - case STATE_ICW2: - dev->icw2 = val; - if (pic_cascade_mode(dev)) - dev->state = STATE_ICW3; - else - dev->state = (dev->icw1 & 1) ? STATE_ICW4 : STATE_NONE; - break; - case STATE_ICW3: - dev->icw3 = val; - dev->state = (dev->icw1 & 1) ? STATE_ICW4 : STATE_NONE; - break; - case STATE_ICW4: - dev->icw4 = val; - dev->state = STATE_NONE; - break; - case STATE_NONE: - dev->imr = val; - update_pending(); - break; - } - } else { - if (val & 0x10) { - /* Treat any write with any of the bits 7 to 5 set as invalid if PCI. */ - if (pic_pci && (val & 0xe0)) - return; - - dev->icw1 = val; - dev->icw2 = dev->icw3 = 0x00; - if (!(dev->icw1 & 1)) - dev->icw4 = 0x00; - dev->ocw2 = dev->ocw3 = 0x00; - dev->irr = dev->lines; - dev->imr = dev->isr = 0x00; - dev->ack_bytes = dev->priority = 0x00; - dev->auto_eoi_rotate = dev->special_mask_mode = 0x00; - dev->interrupt = 0x17; - dev->int_pending = 0x00; - dev->state = STATE_ICW2; - update_pending(); - } else if (val & 0x08) { - dev->ocw3 = val; - if (dev->ocw3 & 0x04) - dev->interrupt |= 0x20; /* Freeze the interrupt until the poll is over. */ - if (dev->ocw3 & 0x40) - dev->special_mask_mode = !!(dev->ocw3 & 0x20); - } else { - dev->ocw2 = val; - pic_command(dev); - } - } -} - -void -pic_set_pci(void) -{ - int i; - - for (i = 0x0024; i < 0x0040; i += 4) { - io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); - io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); - } - - for (i = 0x1120; i < 0x1140; i += 4) { - io_sethandler(i, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); - io_sethandler(i + 0x0080, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); - } -} - -void -pic_kbd_latch(int enable) -{ - pic_log("PIC keyboard latch now %sabled\n", enable ? "en" : "dis"); - - if (!!(enable | mouse_latch) != !!(kbd_latch | mouse_latch)) - io_handler(!!(enable | mouse_latch), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); - - kbd_latch = !!enable; - - if (!enable) - picintc(0x0002); -} - -void -pic_mouse_latch(int enable) -{ - pic_log("PIC mouse latch now %sabled\n", enable ? "en" : "dis"); - - if (!!(kbd_latch | enable) != !!(kbd_latch | mouse_latch)) - io_handler(!!(kbd_latch | enable), 0x0060, 0x0001, pic_latch_read, NULL, NULL, NULL, NULL, NULL, NULL); - - mouse_latch = !!enable; - - if (!enable) - picintc(0x1000); -} - -static void -pic_reset_hard(void) -{ - pic_reset(); - - /* Explicitly reset the latches. */ - kbd_latch = mouse_latch = 0; - - /* The situation is as follows: There is a giant mess when it comes to these latches on real hardware, - to the point that there's even boards with board-level latched that get used in place of the latches - on the chipset, therefore, I'm just doing this here for the sake of simplicity. */ - if (machine_has_bus(machine, MACHINE_BUS_PS2)) { - pic_kbd_latch(0x01); - pic_mouse_latch(0x01); - } else { - pic_kbd_latch(0x00); - pic_mouse_latch(0x00); - } -} - -void -pic_init(void) -{ - pic_reset_hard(); - - shadow = 0; - io_sethandler(0x0020, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); -} - -void -pic_init_pcjr(void) -{ - pic_reset_hard(); - - shadow = 0; - io_sethandler(0x0020, 0x0008, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic); -} - -void -pic2_init(void) -{ - io_sethandler(0x00a0, 0x0002, pic_read, NULL, NULL, pic_write, NULL, NULL, &pic2); - pic.slaves[2] = &pic2; -} - -void -picint_common(uint16_t num, int level, int set) -{ - int i, raise; - uint8_t b, slaves = 0; - - /* Make sure to ignore all slave IRQ's, and in case of AT+, - translate IRQ 2 to IRQ 9. */ - for (i = 0; i < 8; i++) { - b = (1 << i); - raise = num & b; - - if (pic.icw3 & b) { - slaves++; - - if (raise) { - num &= ~b; - if (pic.at && (i == 2)) - num |= (1 << 9); - } - } - } - - if (!slaves) - num &= 0x00ff; - - if (!num) { - pic_log("Attempting to %s null IRQ\n", set ? "raise" : "lower"); - return; - } - - if (num & 0x0100) - acpi_rtc_status = !!set; - - if (set) { - if (smi_irq_mask & num) { - smi_raise(); - smi_irq_status |= num; - } - - if (num & 0xff00) { - if (level) - pic2.lines |= (num >> 8); - - /* Latch IRQ 12 if the mouse latch is enabled. */ - if ((num & 0x1000) && mouse_latch) - latched_irqs |= 0x1000; - - pic2.irr |= (num >> 8); - } - - if (num & 0x00ff) { - if (level) - pic.lines |= (num & 0x00ff); - - /* Latch IRQ 1 if the keyboard latch is enabled. */ - if (kbd_latch && (num & 0x0002)) - latched_irqs |= 0x0002; - - pic.irr |= (num & 0x00ff); - } - } else { - smi_irq_status &= ~num; - - if (num & 0xff00) { - pic2.lines &= ~(num >> 8); - - /* Unlatch IRQ 12 if the mouse latch is enabled. */ - if ((num & 0x1000) && mouse_latch) - latched_irqs &= 0xefff; - - pic2.irr &= ~(num >> 8); - } - - if (num & 0x00ff) { - pic.lines &= ~(num & 0x00ff); - - /* Unlatch IRQ 1 if the keyboard latch is enabled. */ - if (kbd_latch && (num & 0x0002)) - latched_irqs &= 0xfffd; - - pic.irr &= ~(num & 0x00ff); - } - } - - if (!(pic.interrupt & 0x20) && !(pic2.interrupt & 0x20)) - update_pending(); -} - -void -picint(uint16_t num) -{ - picint_common(num, 0, 1); -} - -void -picintlevel(uint16_t num) -{ - picint_common(num, 1, 1); -} - -void -picintc(uint16_t num) -{ - picint_common(num, 0, 0); -} - -static uint8_t -pic_i86_mode(pic_t *dev) -{ - return !!(dev->icw4 & 1); -} - -static uint8_t -pic_irq_ack_read(pic_t *dev, int phase) -{ - uint8_t intr = dev->interrupt & 0x47; - uint8_t slave = intr & 0x40; - intr &= 0x07; - pic_log(" pic_irq_ack_read(%08X, %i)\n", dev, phase); - - if (dev != NULL) { - if (phase == 0) { - dev->interrupt |= 0x20; /* Freeze it so it still takes interrupts but they do not - override the one currently being processed. */ - pic_acknowledge(dev); - if (slave) - dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); - else - dev->data_bus = pic_i86_mode(dev) ? 0xff : 0xcd; - } else if (pic_i86_mode(dev)) { - dev->int_pending = 0; - if (slave) - dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); - else - dev->data_bus = intr + (dev->icw2 & 0xf8); - pic_auto_non_specific_eoi(dev); - } else if (phase == 1) { - if (slave) - dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); - else if (dev->icw1 & 0x04) - dev->data_bus = (intr << 2) + (dev->icw1 & 0xe0); - else - dev->data_bus = (intr << 3) + (dev->icw1 & 0xc0); - } else if (phase == 2) { - dev->int_pending = 0; - if (slave) - dev->data_bus = pic_irq_ack_read(dev->slaves[intr], phase); - else - dev->data_bus = dev->icw2; - pic_auto_non_specific_eoi(dev); - } - } - - return dev->data_bus; -} - -uint8_t -pic_irq_ack(void) -{ - int ret; - - /* Needed for Xi8088. */ - if ((pic.ack_bytes == 0) && pic.int_pending && pic_slave_on(&pic, pic.interrupt)) { - if (!pic.slaves[pic.interrupt]->int_pending) { - /* If we are on AT, IRQ 2 is pending, and we cannot find a pending IRQ on PIC 2, fatal out. */ - fatal("IRQ %i pending on AT without a pending IRQ on PIC %i (normal)\n", pic.interrupt, pic.interrupt); - exit(-1); - return -1; - } - - pic.interrupt |= 0x40; /* Mark slave pending. */ - } - - ret = pic_irq_ack_read(&pic, pic.ack_bytes); - pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3); - - if (pic.ack_bytes == 0) { - /* Needed for Xi8088. */ - if (pic.interrupt & 0x40) - pic2.interrupt = 0x17; - pic.interrupt = 0x17; - update_pending(); - } - - return ret; -} - -int -picinterrupt(void) -{ - int i, ret = -1; - - if (pic.int_pending) { - if (pic_slave_on(&pic, pic.interrupt)) { - if (!pic.slaves[pic.interrupt]->int_pending) { - /* If we are on AT, IRQ 2 is pending, and we cannot find a pending IRQ on PIC 2, fatal out. */ - fatal("IRQ %i pending on AT without a pending IRQ on PIC %i (normal)\n", pic.interrupt, pic.interrupt); - exit(-1); - return -1; - } - - pic.interrupt |= 0x40; /* Mark slave pending. */ - } - - if ((pic.interrupt == 0) && (pit_devs[1].data != NULL)) - pit_devs[1].set_gate(pit_devs[1].data, 0, 0); - - /* Two ACK's - do them in a loop to avoid potential compiler misoptimizations. */ - for (i = 0; i < 2; i++) { - ret = pic_irq_ack_read(&pic, pic.ack_bytes); - pic.ack_bytes = (pic.ack_bytes + 1) % (pic_i86_mode(&pic) ? 2 : 3); - - if (pic.ack_bytes == 0) { - if (pic.interrupt & 0x40) - pic2.interrupt = 0x17; - pic.interrupt = 0x17; - update_pending(); - } - } - } - - return ret; -} From a395a5bae88dad1339f1c7bc030cda5daa23614f Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 7 May 2023 12:42:39 +0200 Subject: [PATCH 31/34] Removed some excess code from usb.c. --- src/usb.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/usb.c b/src/usb.c index e45f82ae8..5b5e68bf2 100644 --- a/src/usb.c +++ b/src/usb.c @@ -617,11 +617,8 @@ ohci_update_mem_mapping(usb_t *dev, uint8_t base1, uint8_t base2, uint8_t base3, dev->ohci_mem_base = ((base1 << 8) | (base2 << 16) | (base3 << 24)) & 0xfffff000; dev->ohci_enable = enable; - if (dev->ohci_enable && (dev->ohci_mem_base != 0x00000000)) { - dev->ohci_mmio_mapping.flags = MEM_MAPPING_EXTERNAL; + if (dev->ohci_enable && (dev->ohci_mem_base != 0x00000000)) mem_mapping_set_addr(&dev->ohci_mmio_mapping, dev->ohci_mem_base, 0x1000); - mem_mapping_enable(&dev->ohci_mmio_mapping); - } usb_log("ohci_update_mem_mapping(): OHCI %sabled at %08X\n", dev->ohci_enable ? "en" : "dis", dev->ohci_mem_base); } From ae123f1f380e00f85215b99e289838a7ccf115a3 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 7 May 2023 16:55:15 +0600 Subject: [PATCH 32/34] usb: Implement HCCA reads and writes --- src/include/86box/usb.h | 4 ++-- src/usb.c | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index 6582f05e4..d8101c880 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -58,6 +58,7 @@ typedef struct usb_t } usb_t; #pragma pack(push, 1) + /* Base USB descriptor struct. */ typedef struct { @@ -76,6 +77,7 @@ typedef struct uint8_t bmAttributes; uint8_t bMaxPower; } usb_desc_conf_t; + #pragma pack(pop) typedef struct @@ -84,9 +86,7 @@ typedef struct uint16_t HccaFrameNumber; uint16_t HccaPad1; uint32_t HccaDoneHead; - uint32_t Reserved[29]; } usb_hcca_t; - /* USB endpoint device struct. Incomplete and unused. */ typedef struct { diff --git a/src/usb.c b/src/usb.c index 5b5e68bf2..0b3b5efe1 100644 --- a/src/usb.c +++ b/src/usb.c @@ -300,8 +300,13 @@ ohci_set_interrupt(usb_t *dev, uint8_t bit) void ohci_end_of_frame(usb_t* dev) { + usb_hcca_t hcca; /* TODO: Put endpoint and transfer descriptor processing here. */ + dma_bm_read(dev->ohci_mmio[OHCI_HcHCCA].l, (uint8_t*)&hcca, sizeof(usb_hcca_t), 4); + dev->ohci_mmio[OHCI_HcFmNumber].w[0]++; + + dma_bm_write(dev->ohci_mmio[OHCI_HcHCCA].l, (uint8_t*)&hcca, sizeof(usb_hcca_t), 4); } void From 708f00699b7c3dfee2086dd7d6e076ba2916a330 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 7 May 2023 17:29:06 +0600 Subject: [PATCH 33/34] usb: Transfer and endpoint descriptor structure --- src/include/86box/usb.h | 19 +++++++++++++++++++ src/usb.c | 1 - 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index d8101c880..bd94322ae 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -87,6 +87,25 @@ typedef struct uint16_t HccaPad1; uint32_t HccaDoneHead; } usb_hcca_t; + +/* Transfer descriptors */ +typedef struct +{ + uint32_t Control; + uint32_t CBP; + uint32_t NextTD; + uint32_t BE; +} usb_td_t; + +/* Endpoint descriptors */ +typedef struct +{ + uint32_t Control; + uint32_t TailP; + uint32_t HeadP; + uint32_t NextED; +} usb_ed_t; + /* USB endpoint device struct. Incomplete and unused. */ typedef struct { diff --git a/src/usb.c b/src/usb.c index 0b3b5efe1..3994f60c3 100644 --- a/src/usb.c +++ b/src/usb.c @@ -341,7 +341,6 @@ ohci_poll_interrupt_descriptors(void* priv) /* TODO: Actually poll the interrupt descriptors. */ - dev->ohci_interrupt_counter++; timer_on_auto(&dev->ohci_interrupt_desc_poll_timer, 1000.); } From 9ce81ac27561e96b771e56fccd477b582878aba6 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Sun, 7 May 2023 23:07:03 +0600 Subject: [PATCH 34/34] usb: Start implementing Endpoint/Transfer descriptor parsing --- src/include/86box/usb.h | 29 +-------- src/usb.c | 141 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 128 insertions(+), 42 deletions(-) diff --git a/src/include/86box/usb.h b/src/include/86box/usb.h index bd94322ae..4c6fc289b 100644 --- a/src/include/86box/usb.h +++ b/src/include/86box/usb.h @@ -50,9 +50,8 @@ typedef struct usb_t uint32_t ohci_mem_base, irq_level; mem_mapping_t ohci_mmio_mapping; pc_timer_t ohci_frame_timer; - pc_timer_t ohci_interrupt_desc_poll_timer; pc_timer_t ohci_port_reset_timer[2]; - uint8_t ohci_interrupt_counter : 5; + uint8_t ohci_interrupt_counter : 3; usb_params_t* usb_params; } usb_t; @@ -80,32 +79,6 @@ typedef struct #pragma pack(pop) -typedef struct -{ - uint32_t HccaInterrruptTable[32]; - uint16_t HccaFrameNumber; - uint16_t HccaPad1; - uint32_t HccaDoneHead; -} usb_hcca_t; - -/* Transfer descriptors */ -typedef struct -{ - uint32_t Control; - uint32_t CBP; - uint32_t NextTD; - uint32_t BE; -} usb_td_t; - -/* Endpoint descriptors */ -typedef struct -{ - uint32_t Control; - uint32_t TailP; - uint32_t HeadP; - uint32_t NextED; -} usb_ed_t; - /* USB endpoint device struct. Incomplete and unused. */ typedef struct { diff --git a/src/usb.c b/src/usb.c index 3994f60c3..03b5f6546 100644 --- a/src/usb.c +++ b/src/usb.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #define HAVE_STDARG_H #include <86box/86box.h> @@ -117,6 +118,16 @@ enum OHCI_HcInterruptEnable_RHSC = 1 << 6, }; +/* OHCI HcControl bits */ +enum +{ + OHCI_HcControl_ControlBulkServiceRatio = 1 << 0, + OHCI_HcControl_PeriodicListEnable = 1 << 1, + OHCI_HcControl_IsochronousEnable = 1 << 2, + OHCI_HcControl_ControlListEnable = 1 << 3, + OHCI_HcControl_BulkListEnable = 1 << 4 +}; + static void usb_interrupt_ohci(usb_t *dev, uint32_t level) { @@ -216,6 +227,69 @@ uhci_update_io_mapping(usb_t *dev, uint8_t base_l, uint8_t base_h, int enable) io_sethandler(dev->uhci_io_base, 0x20, uhci_reg_read, NULL, NULL, uhci_reg_write, uhci_reg_writew, NULL, dev); } +typedef struct +{ + uint32_t HccaInterrruptTable[32]; + uint16_t HccaFrameNumber; + uint16_t HccaPad1; + uint32_t HccaDoneHead; +} usb_hcca_t; + +/* Transfer descriptors */ +typedef struct +{ + union + { + uint32_t Control; + struct + { + uint32_t Reserved : 18; + uint8_t bufferRounding : 1; + uint8_t Direction : 2; + uint8_t DelayInterrupt : 3; + uint8_t DataToggle : 2; + uint8_t ErrorCount : 2; + uint8_t ConditionCode : 4; + } flags; + }; + uint32_t CBP; + uint32_t NextTD; + uint32_t BE; +} usb_td_t; + +/* Endpoint descriptors */ +typedef struct +{ + union + { + uint32_t Control; + struct + { + uint8_t FunctionAddress : 7; + uint8_t EndpointNumber : 4; + uint8_t Direction : 2; + bool Speed : 1; + bool Skip : 1; + bool Format : 1; + uint16_t MaximumPacketSize : 11; + uint8_t Reserved : 5; + } flags; + }; + uint32_t TailP; + union + { + uint32_t HeadP; + struct + { + bool Halted : 1; + bool toggleCarry : 1; + } flags_2; + }; + uint32_t NextED; +} usb_ed_t; + +#define ENDPOINT_DESC_LIMIT 32 + static uint8_t ohci_mmio_read(uint32_t addr, void *p) { @@ -297,6 +371,14 @@ ohci_set_interrupt(usb_t *dev, uint8_t bit) ohci_update_irq(dev); } +uint8_t +ohci_service_endpoint_desc(usb_t* dev, uint32_t head) +{ + usb_ed_t endpoint_desc; + + return 0; +} + void ohci_end_of_frame(usb_t* dev) { @@ -304,7 +386,49 @@ ohci_end_of_frame(usb_t* dev) /* TODO: Put endpoint and transfer descriptor processing here. */ dma_bm_read(dev->ohci_mmio[OHCI_HcHCCA].l, (uint8_t*)&hcca, sizeof(usb_hcca_t), 4); + if (dev->ohci_mmio[OHCI_HcControl].l & OHCI_HcControl_PeriodicListEnable) { + ohci_service_endpoint_desc(dev, hcca.HccaInterrruptTable[dev->ohci_mmio[OHCI_HcFmNumber].l & 0x1f]); + } + + if ((dev->ohci_mmio[OHCI_HcControl].l & OHCI_HcControl_ControlListEnable) + && (dev->ohci_mmio[OHCI_HcCommandStatus].l & 0x2)) { + uint8_t result = ohci_service_endpoint_desc(dev, dev->ohci_mmio[OHCI_HcControlHeadED].l); + if (!result) { + dev->ohci_mmio[OHCI_HcControlHeadED].l = 0; + dev->ohci_mmio[OHCI_HcCommandStatus].l &= ~0x2; + } + } + + if ((dev->ohci_mmio[OHCI_HcControl].l & OHCI_HcControl_BulkListEnable) + && (dev->ohci_mmio[OHCI_HcCommandStatus].l & 0x4)) { + uint8_t result = ohci_service_endpoint_desc(dev, dev->ohci_mmio[OHCI_HcBulkHeadED].l); + if (!result) { + dev->ohci_mmio[OHCI_HcBulkHeadED].l = 0; + dev->ohci_mmio[OHCI_HcCommandStatus].l &= ~0x4; + } + } + + if (dev->ohci_interrupt_counter == 0 && !(dev->ohci_mmio[OHCI_HcInterruptStatus].l & OHCI_HcInterruptEnable_WDH)) { + if (dev->ohci_mmio[OHCI_HcDoneHead].l == 0) { + fatal("OHCI: HcDoneHead is still NULL!"); + } + + if (dev->ohci_mmio[OHCI_HcInterruptStatus].l & dev->ohci_mmio[OHCI_HcInterruptEnable].l) { + dev->ohci_mmio[OHCI_HcDoneHead].l |= 1; + } + + hcca.HccaDoneHead = dev->ohci_mmio[OHCI_HcDoneHead].l; + dev->ohci_mmio[OHCI_HcDoneHead].l = 0; + dev->ohci_interrupt_counter = 7; + ohci_set_interrupt(dev, OHCI_HcInterruptEnable_WDH); + } + + if (dev->ohci_interrupt_counter != 0 && dev->ohci_interrupt_counter != 7) { + dev->ohci_interrupt_counter--; + } + dev->ohci_mmio[OHCI_HcFmNumber].w[0]++; + hcca.HccaFrameNumber = dev->ohci_mmio[OHCI_HcFmNumber].w[0]; dma_bm_write(dev->ohci_mmio[OHCI_HcHCCA].l, (uint8_t*)&hcca, sizeof(usb_hcca_t), 4); } @@ -327,21 +451,11 @@ ohci_update_frame_counter(void* priv) dev->ohci_mmio[OHCI_HcFmRemaining].l &= ~(1 << 31); dev->ohci_mmio[OHCI_HcFmRemaining].l |= dev->ohci_mmio[OHCI_HcFmInterval].l & (1 << 31); ohci_start_of_frame(dev); - timer_on_auto(&dev->ohci_frame_timer, 1. / (12. * 1000. * 1000.)); + timer_on_auto(&dev->ohci_frame_timer, 1. / 12.); return; } - if (dev->ohci_mmio[OHCI_HcFmRemaining].w[0]) dev->ohci_mmio[OHCI_HcFmRemaining].w[0]--; - timer_on_auto(&dev->ohci_frame_timer, 1. / (12. * 1000. * 1000.)); -} - -void -ohci_poll_interrupt_descriptors(void* priv) -{ - usb_t *dev = (usb_t *) priv; - - /* TODO: Actually poll the interrupt descriptors. */ - - timer_on_auto(&dev->ohci_interrupt_desc_poll_timer, 1000.); + dev->ohci_mmio[OHCI_HcFmRemaining].w[0]--; + timer_on_auto(&dev->ohci_frame_timer, 1. / 12.); } void @@ -694,7 +808,6 @@ usb_init_ext(const device_t *info, void *params) timer_add(&dev->ohci_frame_timer, ohci_update_frame_counter, dev, 0); /* Unused for now, to be used for frame counting. */ timer_add(&dev->ohci_port_reset_timer[0], ohci_port_reset_callback, dev, 0); timer_add(&dev->ohci_port_reset_timer[1], ohci_port_reset_callback_2, dev, 0); - timer_add(&dev->ohci_interrupt_desc_poll_timer, ohci_poll_interrupt_descriptors, dev, 0); usb_reset(dev);