diff --git a/src/config - Cópia.c b/src/config - Cópia.c deleted file mode 100644 index 733666e3e..000000000 --- a/src/config - Cópia.c +++ /dev/null @@ -1,2263 +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. - * - * Configuration file handler. - * - * Version: @(#)config.c 1.0.52 2018/09/06 - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * Overdoze, - * David Hrdlička, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2018 David Hrdlička. - * - * NOTE: Forcing config files to be in Unicode encoding breaks - * it on Windows XP, and possibly also Vista. Use the - * -DANSI_CFG for use on these systems. - */ -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "86box.h" -#include "cpu/cpu.h" -#include "device.h" -#include "nvr.h" -#include "config.h" -#include "isamem.h" -#include "isartc.h" -#include "lpt.h" -#include "disk/hdd.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" -#include "game/gameport.h" -#include "machine/machine.h" -#include "mouse.h" -#include "network/network.h" -#include "scsi/scsi.h" -#include "cdrom/cdrom.h" -#include "disk/zip.h" -#include "sound/sound.h" -#include "sound/midi.h" -#include "sound/snd_dbopl.h" -#include "sound/snd_mpu401.h" -#include "sound/snd_opl.h" -#include "sound/sound.h" -#include "video/video.h" -#include "plat.h" -#include "plat_midi.h" -#include "ui.h" - - -typedef struct _list_ { - struct _list_ *next; -} list_t; - -typedef struct { - list_t list; - - char name[128]; - - list_t entry_head; -} section_t; - -typedef struct { - list_t list; - - char name[128]; - char data[256]; - wchar_t wdata[512]; -} entry_t; - -#define list_add(new, head) { \ - list_t *next = head; \ - \ - while (next->next != NULL) \ - next = next->next; \ - \ - (next)->next = new; \ - (new)->next = NULL; \ -} - -#define list_delete(old, head) { \ - list_t *next = head; \ - \ - while ((next)->next != old) { \ - next = (next)->next; \ - } \ - \ - (next)->next = (old)->next; \ -} - - -static list_t config_head; - - -#ifdef ENABLE_CONFIG_LOG -int config_do_log = ENABLE_CONFIG_LOG; -#endif - - -static void -config_log(const char *format, ...) -{ -#ifdef ENABLE_CONFIG_LOG - va_list ap; - - if (config_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } -#endif -} - - -static section_t * -find_section(char *name) -{ - section_t *sec; - char blank[] = ""; - - sec = (section_t *)config_head.next; - if (name == NULL) - name = blank; - - while (sec != NULL) { - if (! strncmp(sec->name, name, sizeof(sec->name))) - return(sec); - - sec = (section_t *)sec->list.next; - } - - return(NULL); -} - - -static entry_t * -find_entry(section_t *section, char *name) -{ - entry_t *ent; - - ent = (entry_t *)section->entry_head.next; - - while (ent != NULL) { - if (! strncmp(ent->name, name, sizeof(ent->name))) - return(ent); - - ent = (entry_t *)ent->list.next; - } - - return(NULL); -} - - -static int -entries_num(section_t *section) -{ - entry_t *ent; - int i = 0; - - ent = (entry_t *)section->entry_head.next; - - while (ent != NULL) { - if (strlen(ent->name) > 0) i++; - - ent = (entry_t *)ent->list.next; - } - - return(i); -} - - -static void -delete_section_if_empty(char *head) -{ - section_t *section; - - section = find_section(head); - if (section == NULL) return; - - if (entries_num(section) == 0) { - list_delete(§ion->list, &config_head); - free(section); - } -} - - -static section_t * -create_section(char *name) -{ - section_t *ns = malloc(sizeof(section_t)); - - memset(ns, 0x00, sizeof(section_t)); - strncpy(ns->name, name, sizeof(ns->name)); - list_add(&ns->list, &config_head); - - return(ns); -} - - -static entry_t * -create_entry(section_t *section, char *name) -{ - entry_t *ne = malloc(sizeof(entry_t)); - - memset(ne, 0x00, sizeof(entry_t)); - strncpy(ne->name, name, sizeof(ne->name)); - list_add(&ne->list, §ion->entry_head); - - return(ne); -} - - -#if 0 -static void -config_free(void) -{ - section_t *sec, *ns; - entry_t *ent; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - ns = (section_t *)sec->list.next; - ent = (entry_t *)sec->entry_head.next; - - while (ent != NULL) { - entry_t *nent = (entry_t *)ent->list.next; - - free(ent); - ent = nent; - } - - free(sec); - sec = ns; - } -} -#endif - - -/* Read and parse the configuration file into memory. */ -static int -config_read(wchar_t *fn) -{ - char sname[128], ename[128]; - wchar_t buff[1024]; - section_t *sec, *ns; - entry_t *ne; - int c, d; - FILE *f; - -#if defined(ANSI_CFG) || !defined(_WIN32) - f = plat_fopen(fn, L"rt"); -#else - f = plat_fopen(fn, L"rt, ccs=UNICODE"); -#endif - if (f == NULL) return(0); - - sec = malloc(sizeof(section_t)); - memset(sec, 0x00, sizeof(section_t)); - memset(&config_head, 0x00, sizeof(list_t)); - list_add(&sec->list, &config_head); - - while (1) { - memset(buff, 0x00, sizeof(buff)); - fgetws(buff, sizeof_w(buff), f); - if (feof(f)) break; - - /* Make sure there are no stray newlines or hard-returns in there. */ - if (buff[wcslen(buff)-1] == L'\n') buff[wcslen(buff)-1] = L'\0'; - if (buff[wcslen(buff)-1] == L'\r') buff[wcslen(buff)-1] = L'\0'; - - /* Skip any leading whitespace. */ - c = 0; - while ((buff[c] == L' ') || (buff[c] == L'\t')) - c++; - - /* Skip empty lines. */ - if (buff[c] == L'\0') continue; - - /* Skip lines that (only) have a comment. */ - if ((buff[c] == L'#') || (buff[c] == L';')) continue; - - if (buff[c] == L'[') { /*Section*/ - c++; - d = 0; - while (buff[c] != L']' && buff[c]) - wctomb(&(sname[d++]), buff[c++]); - sname[d] = L'\0'; - - /* Is the section name properly terminated? */ - if (buff[c] != L']') continue; - - /* Create a new section and insert it. */ - ns = malloc(sizeof(section_t)); - memset(ns, 0x00, sizeof(section_t)); - strncpy(ns->name, sname, sizeof(ns->name)); - list_add(&ns->list, &config_head); - - /* New section is now the current one. */ - sec = ns; - continue; - } - - /* Get the variable name. */ - d = 0; - while ((buff[c] != L'=') && (buff[c] != L' ') && buff[c]) - wctomb(&(ename[d++]), buff[c++]); - ename[d] = L'\0'; - - /* Skip incomplete lines. */ - if (buff[c] == L'\0') continue; - - /* Look for =, skip whitespace. */ - while ((buff[c] == L'=' || buff[c] == L' ') && buff[c]) - c++; - - /* Skip incomplete lines. */ - if (buff[c] == L'\0') continue; - - /* This is where the value part starts. */ - d = c; - - /* Allocate a new variable entry.. */ - ne = malloc(sizeof(entry_t)); - memset(ne, 0x00, sizeof(entry_t)); - strncpy(ne->name, ename, sizeof(ne->name)); - wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata)-1); - ne->wdata[sizeof_w(ne->wdata)-1] = L'\0'; - wcstombs(ne->data, ne->wdata, sizeof(ne->data)); - ne->data[sizeof(ne->data)-1] = '\0'; - - /* .. and insert it. */ - list_add(&ne->list, &sec->entry_head); - } - - (void)fclose(f); - - if (do_dump_config) - config_dump(); - - return(1); -} - - -/* - * Write the in-memory configuration to disk. - * This is a public function, because the Settings UI - * want to directly write the configuration after it - * has changed it. - */ -void -config_write(wchar_t *fn) -{ - wchar_t wtemp[512]; - section_t *sec; - FILE *f; - int fl = 0; - -#if defined(ANSI_CFG) || !defined(_WIN32) - f = plat_fopen(fn, L"wt"); -#else - f = plat_fopen(fn, L"wt, ccs=UNICODE"); -#endif - if (f == NULL) return; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - entry_t *ent; - - if (sec->name[0]) { - mbstowcs(wtemp, sec->name, strlen(sec->name)+1); - if (fl) - fwprintf(f, L"\n[%ls]\n", wtemp); - else - fwprintf(f, L"[%ls]\n", wtemp); - fl++; - } - - ent = (entry_t *)sec->entry_head.next; - while (ent != NULL) { - if (ent->name[0] != '\0') { - mbstowcs(wtemp, ent->name, sizeof_w(wtemp)); - if (ent->wdata[0] == L'\0') - fwprintf(f, L"%ls = \n", wtemp); - else - fwprintf(f, L"%ls = %ls\n", wtemp, ent->wdata); - fl++; - } - - ent = (entry_t *)ent->list.next; - } - - sec = (section_t *)sec->list.next; - } - - (void)fclose(f); -} - - -#if NOT_USED -static void -config_new(void) -{ -#if defined(ANSI_CFG) || !defined(_WIN32) - FILE *f = _wfopen(config_file, L"wt"); -#else - FILE *f = _wfopen(config_file, L"wt, ccs=UNICODE"); -#endif - - if (file != NULL) - (void)fclose(f); -} -#endif - - -/* Load "General" section. */ -static void -load_general(void) -{ - char *cat = "General"; - char temp[512]; - char *p; - - vid_resize = !!config_get_int(cat, "vid_resize", 0); - - memset(temp, '\0', sizeof(temp)); - p = config_get_string(cat, "vid_renderer", "default"); - vid_api = plat_vidapi(p); - config_delete_var(cat, "vid_api"); - - video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0); - - video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 0); - - force_43 = !!config_get_int(cat, "force_43", 0); - scale = config_get_int(cat, "scale", 1); - if (scale > 3) - scale = 3; - - enable_overscan = !!config_get_int(cat, "enable_overscan", 0); - vid_cga_contrast = !!config_get_int(cat, "vid_cga_contrast", 0); - video_grayscale = config_get_int(cat, "video_grayscale", 0); - video_graytype = config_get_int(cat, "video_graytype", 0); - - rctrl_is_lalt = config_get_int(cat, "rctrl_is_lalt", 0); - update_icons = config_get_int(cat, "update_icons", 1); - - window_remember = config_get_int(cat, "window_remember", 0); - if (window_remember) { - p = config_get_string(cat, "window_coordinates", NULL); - if (p == NULL) - p = "0, 0, 0, 0"; - sscanf(p, "%i, %i, %i, %i", &window_w, &window_h, &window_x, &window_y); - } else { - config_delete_var(cat, "window_remember"); - config_delete_var(cat, "window_coordinates"); - - window_w = window_h = window_x = window_y = 0; - } - - sound_gain = config_get_int(cat, "sound_gain", 0); - -#ifdef USE_LANGUAGE - /* - * Currently, 86Box is English (US) only, but in the future - * (version 3.0 at the earliest) other languages will be - * added, therefore it is better to future-proof the code. - */ - plat_langid = config_get_hex16(cat, "language", 0x0409); -#endif -} - - -/* Load "Machine" section. */ -static void -load_machine(void) -{ - char *cat = "Machine"; - char *p; - - p = config_get_string(cat, "machine", NULL); - if (p != NULL) - machine = machine_get_machine_from_internal_name(p); - else - machine = 0; - if (machine >= machine_count()) - machine = machine_count() - 1; - - /* This is for backwards compatibility. */ - p = config_get_string(cat, "model", NULL); - if (p != NULL) { - /* Detect the old model typos and fix them. */ - if (! strcmp(p, "p55r2p4")) { - machine = machine_get_machine_from_internal_name("p55t2p4"); - } else { - machine = machine_get_machine_from_internal_name(p); - } - config_delete_var(cat, "model"); - } - if (machine >= machine_count()) - machine = machine_count() - 1; - - romset = machine_getromset(); - cpu_manufacturer = config_get_int(cat, "cpu_manufacturer", 0); - cpu = config_get_int(cat, "cpu", 0); - cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0); - - mem_size = config_get_int(cat, "mem_size", 4096); - -#if 0 - if (mem_size < (((machines[machine].flags & MACHINE_AT) && - (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram)) - mem_size = (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram); -#endif - - if (mem_size > 1048576) - mem_size = 1048576; - - cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0); - - enable_external_fpu = !!config_get_int(cat, "cpu_enable_fpu", 0); - - p = config_get_string(cat, "time_sync", NULL); - if (p != NULL) { - if (!strcmp(p, "disabled")) - time_sync = TIME_SYNC_DISABLED; - else - if (!strcmp(p, "local")) - time_sync = TIME_SYNC_ENABLED; - else - if (!strcmp(p, "utc") || !strcmp(p, "gmt")) - time_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC; - else - time_sync = TIME_SYNC_ENABLED; - } else - time_sync = !!config_get_int(cat, "enable_sync", 1); - - /* Remove this after a while.. */ - config_delete_var(cat, "nvr_path"); - config_delete_var(cat, "enable_sync"); -} - - -/* Load "Video" section. */ -static void -load_video(void) -{ - char *cat = "Video"; - char *p; - - if (machines[machine].fixed_gfxcard) { - config_delete_var(cat, "gfxcard"); - gfxcard = GFX_INTERNAL; - } else { - p = config_get_string(cat, "gfxcard", NULL); - if (p == NULL) { - if (machines[machine].flags & MACHINE_VIDEO) { - p = (char *)malloc((strlen("internal")+1)*sizeof(char)); - strcpy(p, "internal"); - } else { - p = (char *)malloc((strlen("none")+1)*sizeof(char)); - strcpy(p, "none"); - } - } - gfxcard = video_get_video_from_internal_name(p); - } - - voodoo_enabled = !!config_get_int(cat, "voodoo", 0); -} - - -/* Load "Input Devices" section. */ -static void -load_input_devices(void) -{ - char *cat = "Input devices"; - char temp[512]; - int c, d; - char *p; - - p = config_get_string(cat, "mouse_type", NULL); - if (p != NULL) - mouse_type = mouse_get_from_internal_name(p); - else - mouse_type = 0; - - joystick_type = config_get_int(cat, "joystick_type", 7); - - for (c=0; c max_spt) - hdd[c].spt = max_spt; - if (hdd[c].hpc > max_hpc) - hdd[c].hpc = max_hpc; - if (hdd[c].tracks > max_tracks) - hdd[c].tracks = max_tracks; - - /* MFM/RLL */ - sprintf(temp, "hdd_%02i_mfm_channel", c+1); - if (hdd[c].bus == HDD_BUS_MFM) - hdd[c].mfm_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); - - /* XTA */ - sprintf(temp, "hdd_%02i_xta_channel", c+1); - if (hdd[c].bus == HDD_BUS_XTA) - hdd[c].xta_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); - - /* ESDI */ - sprintf(temp, "hdd_%02i_esdi_channel", c+1); - if (hdd[c].bus == HDD_BUS_ESDI) - hdd[c].esdi_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); - - /* IDE */ - // FIXME: Remove in a month. - sprintf(temp, "hdd_%02i_xtide_channel", c+1); - if (hdd[c].bus == HDD_BUS_IDE) - hdd[c].ide_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_ide_channel", c+1); - if (hdd[c].bus == HDD_BUS_IDE) { - sprintf(tmp2, "%01u:%01u", c>>1, c&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - hdd[c].ide_channel = (board<<1) + dev; - - if (hdd[c].ide_channel > 7) - hdd[c].ide_channel = 7; - } else { - config_delete_var(cat, temp); - } - - /* SCSI */ - sprintf(temp, "hdd_%02i_scsi_id", c+1); - if (hdd[c].bus == HDD_BUS_SCSI) { - hdd[c].scsi_id = config_get_int(cat, temp, c); - - if (hdd[c].scsi_id > 15) - hdd[c].scsi_id = 15; - } else - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "hdd_%02i_scsi_location", c+1); - if (hdd[c].bus == HDD_BUS_SCSI) { - p = config_get_string(cat, temp, NULL); - - if (p) { - sscanf(p, "%02i:%02i", - (int *)&hdd[c].scsi_id, (int *)&lun); - - if (hdd[c].scsi_id > 15) - hdd[c].scsi_id = 15; - } - } - config_delete_var(cat, temp); - - memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn)); - memset(hdd[c].prev_fn, 0x00, sizeof(hdd[c].prev_fn)); - sprintf(temp, "hdd_%02i_fn", c+1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the CFG path. Just strip - * that off for now... - */ - wcsncpy(hdd[c].fn, &wp[wcslen(usr_path)], sizeof_w(hdd[c].fn)); - } else -#endif - wcsncpy(hdd[c].fn, wp, sizeof_w(hdd[c].fn)); - - /* If disk is empty or invalid, mark it for deletion. */ - if (! hdd_is_valid(c)) { - sprintf(temp, "hdd_%02i_parameters", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_preide_channels", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_ide_channels", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_scsi_id", c+1); - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "hdd_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_fn", c+1); - config_delete_var(cat, temp); - } - - sprintf(temp, "hdd_%02i_mfm_channel", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - } -} - - -/* Load "Floppy Drives" section. */ -static void -load_floppy_drives(void) -{ - char *cat = "Floppy drives"; - char temp[512], *p; - wchar_t *wp; - int c; - - for (c=0; c 13) - fdd_set_type(c, 13); - - sprintf(temp, "fdd_%02i_fn", c + 1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(floppyfns[c], &wp[wcslen(usr_path)], sizeof_w(floppyfns[c])); - } else -#endif - wcsncpy(floppyfns[c], wp, sizeof_w(floppyfns[c])); - - /* if (*wp != L'\0') - config_log("Floppy%d: %ls\n", c, floppyfns[c]); */ - sprintf(temp, "fdd_%02i_writeprot", c+1); - ui_writeprot[c] = !!config_get_int(cat, temp, 0); - sprintf(temp, "fdd_%02i_turbo", c + 1); - fdd_set_turbo(c, !!config_get_int(cat, temp, 0)); - sprintf(temp, "fdd_%02i_check_bpb", c+1); - fdd_set_check_bpb(c, !!config_get_int(cat, temp, 1)); - - /* Check whether each value is default, if yes, delete it so that only non-default values will later be saved. */ - if (fdd_get_type(c) == ((c < 2) ? 2 : 0)) { - sprintf(temp, "fdd_%02i_type", c+1); - config_delete_var(cat, temp); - } - if (wcslen(floppyfns[c]) == 0) { - sprintf(temp, "fdd_%02i_fn", c+1); - config_delete_var(cat, temp); - } - if (ui_writeprot[c] == 0) { - sprintf(temp, "fdd_%02i_writeprot", c+1); - config_delete_var(cat, temp); - } - if (fdd_get_turbo(c) == 0) { - sprintf(temp, "fdd_%02i_turbo", c+1); - config_delete_var(cat, temp); - } - if (fdd_get_check_bpb(c) == 1) { - sprintf(temp, "fdd_%02i_check_bpb", c+1); - config_delete_var(cat, temp); - } - } -} - - -/* Load "Other Removable Devices" section. */ -static void -load_other_removable_devices(void) -{ - char *cat = "Other removable devices"; - char temp[512], tmp2[512], *p; - char s[512]; - unsigned int board = 0, dev = 0; - wchar_t *wp; - int c; - /* FIXME: Remove in a month. */ - int lun; - - memset(temp, 0x00, sizeof(temp)); - for (c=0; c>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - cdrom_drives[c].ide_channel = (board<<1)+dev; - - if (cdrom_drives[c].ide_channel > 7) - cdrom_drives[c].ide_channel = 7; - } else { - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { - cdrom_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); - - if (cdrom_drives[c].scsi_device_id > 15) - cdrom_drives[c].scsi_device_id = 15; - } else - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { - p = config_get_string(cat, temp, NULL); - if (p) { - sscanf(p, "%02u:%02u", - &cdrom_drives[c].scsi_device_id, &lun); - - if (cdrom_drives[c].scsi_device_id > 15) - cdrom_drives[c].scsi_device_id = 15; - } - } - config_delete_var(cat, temp); - } - - sprintf(temp, "cdrom_%02i_image_path", c+1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(cdrom_image[c].image_path, &wp[wcslen(usr_path)], sizeof_w(cdrom_image[c].image_path)); - } else -#endif - wcsncpy(cdrom_image[c].image_path, wp, sizeof_w(cdrom_image[c].image_path)); - - if (cdrom_drives[c].host_drive < 'A') - cdrom_drives[c].host_drive = 0; - - if ((cdrom_drives[c].host_drive == 0x200) && - (wcslen(cdrom_image[c].image_path) == 0)) - cdrom_drives[c].host_drive = 0; - - /* If the CD-ROM is disabled, delete all its variables. */ - if (cdrom_drives[c].bus_type == CDROM_BUS_DISABLED) { - sprintf(temp, "cdrom_%02i_host_drive", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_parameters", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_image_path", c+1); - config_delete_var(cat, temp); - } - - sprintf(temp, "cdrom_%02i_iso_path", c+1); - config_delete_var(cat, temp); - } - - memset(temp, 0x00, sizeof(temp)); - for (c=0; c>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - zip_drives[c].ide_channel = (board<<1)+dev; - - if (zip_drives[c].ide_channel > 7) - zip_drives[c].ide_channel = 7; - } else { - sprintf(temp, "zip_%02i_scsi_id", c+1); - if (zip_drives[c].bus_type == CDROM_BUS_SCSI) { - zip_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); - - if (zip_drives[c].scsi_device_id > 15) - zip_drives[c].scsi_device_id = 15; - } else - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "zip_%02i_scsi_location", c+1); - if (zip_drives[c].bus_type == CDROM_BUS_SCSI) { - p = config_get_string(cat, temp, NULL); - if (p) { - sscanf(p, "%02u:%02u", - &zip_drives[c].scsi_device_id, &lun); - - if (zip_drives[c].scsi_device_id > 15) - zip_drives[c].scsi_device_id = 15; - } - } - config_delete_var(cat, temp); - } - - sprintf(temp, "zip_%02i_image_path", c+1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(zip_drives[c].image_path, &wp[wcslen(usr_path)], sizeof_w(zip_drives[c].image_path)); - } else -#endif - wcsncpy(zip_drives[c].image_path, wp, sizeof_w(zip_drives[c].image_path)); - - /* If the CD-ROM is disabled, delete all its variables. */ - if (zip_drives[c].bus_type == ZIP_BUS_DISABLED) { - sprintf(temp, "zip_%02i_host_drive", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "zip_%02i_parameters", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "zip_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "zip_%02i_scsi_id", c+1); - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "zip_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "zip_%02i_image_path", c+1); - config_delete_var(cat, temp); - } - - sprintf(temp, "zip_%02i_iso_path", c+1); - config_delete_var(cat, temp); - } -} - - -/* Load the specified or a default configuration file. */ -void -config_load(void) -{ - int i; - - config_log("Loading config file '%ls'..\n", cfg_path); - - memset(hdd, 0, sizeof(hard_disk_t)); - memset(cdrom_drives, 0, sizeof(cdrom_drive_t) * CDROM_NUM); - memset(cdrom_image, 0, sizeof(cdrom_image_t) * CDROM_NUM); -#ifdef USE_IOCTL - memset(cdrom_ioctl, 0, sizeof(cdrom_ioctl_t) * CDROM_NUM); -#endif - memset(zip_drives, 0, sizeof(zip_drive_t)); - - if (! config_read(cfg_path)) { - cpu = 0; -#ifdef USE_LANGUAGE - plat_langid = 0x0409; -#endif - scale = 1; - machine = machine_get_machine_from_internal_name("ibmpc"); - gfxcard = GFX_CGA; - vid_api = plat_vidapi("default"); - time_sync = TIME_SYNC_ENABLED; - joystick_type = 7; - if (hdc_name) { - free(hdc_name); - hdc_name = NULL; - } - hdc_name = (char *) malloc((strlen("none")+1) * sizeof(char)); - strcpy(hdc_name, "none"); - serial_enabled[0] = 1; - serial_enabled[1] = 1; - lpt_enabled = 1; - for (i = 0; i < FDD_NUM; i++) { - if (i < 2) - fdd_set_type(i, 2); - else - fdd_set_type(i, 0); - - fdd_set_turbo(i, 0); - fdd_set_check_bpb(i, 1); - } - mem_size = 640; - opl_type = 0; - isartc_type = 0; - for (i = 0; i < ISAMEM_MAX; i++) - isamem_type[i] = 0; - - config_log("Config file not present or invalid!\n"); - return; - } - - load_general(); /* General */ - load_machine(); /* Machine */ - load_video(); /* Video */ - load_input_devices(); /* Input devices */ - load_sound(); /* Sound */ - load_network(); /* Network */ - load_ports(); /* Ports (COM & LPT) */ - load_other_peripherals(); /* Other peripherals */ - load_hard_disks(); /* Hard disks */ - load_floppy_drives(); /* Floppy drives */ - load_other_removable_devices(); /* Other removable devices */ - - /* Mark the configuration as changed. */ - config_changed = 1; - - config_log("Config loaded.\n\n"); -} - - -/* Save "General" section. */ -static void -save_general(void) -{ - char *cat = "General"; - char temp[512]; - - char *va_name; - - config_set_int(cat, "vid_resize", vid_resize); - if (vid_resize == 0) - config_delete_var(cat, "vid_resize"); - - va_name = plat_vidapi_name(vid_api); - if (!strcmp(va_name, "default")) { - config_delete_var(cat, "vid_renderer"); - } else { - config_set_string(cat, "vid_renderer", va_name); - } - - if (video_fullscreen_scale == 0) - config_delete_var(cat, "video_fullscreen_scale"); - else - config_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale); - - if (video_fullscreen_first == 0) - config_delete_var(cat, "video_fullscreen_first"); - else - config_set_int(cat, "video_fullscreen_first", video_fullscreen_first); - - if (force_43 == 0) - config_delete_var(cat, "force_43"); - else - config_set_int(cat, "force_43", force_43); - - if (scale == 1) - config_delete_var(cat, "scale"); - else - config_set_int(cat, "scale", scale); - - if (enable_overscan == 0) - config_delete_var(cat, "enable_overscan"); - else - config_set_int(cat, "enable_overscan", enable_overscan); - - if (vid_cga_contrast == 0) - config_delete_var(cat, "vid_cga_contrast"); - else - config_set_int(cat, "vid_cga_contrast", vid_cga_contrast); - - if (video_grayscale == 0) - config_delete_var(cat, "video_grayscale"); - else - config_set_int(cat, "video_grayscale", video_grayscale); - - if (video_graytype == 0) - config_delete_var(cat, "video_graytype"); - else - config_set_int(cat, "video_graytype", video_graytype); - - if (rctrl_is_lalt == 0) - config_delete_var(cat, "rctrl_is_lalt"); - else - config_set_int(cat, "rctrl_is_lalt", rctrl_is_lalt); - - if (update_icons == 1) - config_delete_var(cat, "update_icons"); - else - config_set_int(cat, "update_icons", update_icons); - - if (window_remember) { - config_set_int(cat, "window_remember", window_remember); - - sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y); - config_set_string(cat, "window_coordinates", temp); - } else { - config_delete_var(cat, "window_remember"); - config_delete_var(cat, "window_coordinates"); - } - - if (sound_gain != 0) - config_set_int(cat, "sound_gain", sound_gain); - else - config_delete_var(cat, "sound_gain"); - -#ifdef USE_LANGUAGE - if (plat_langid == 0x0409) - config_delete_var(cat, "language"); - else - config_set_hex16(cat, "language", plat_langid); -#endif - - delete_section_if_empty(cat); -} - - -/* Save "Machine" section. */ -static void -save_machine(void) -{ - char *cat = "Machine"; - - config_set_string(cat, "machine", machine_get_internal_name()); - - if (cpu_manufacturer == 0) - config_delete_var(cat, "cpu_manufacturer"); - else - config_set_int(cat, "cpu_manufacturer", cpu_manufacturer); - - if (cpu == 0) - config_delete_var(cat, "cpu"); - else - config_set_int(cat, "cpu", cpu); - - if (cpu_waitstates == 0) - config_delete_var(cat, "cpu_waitstates"); - else - config_set_int(cat, "cpu_waitstates", cpu_waitstates); - - if (mem_size == 4096) - config_delete_var(cat, "mem_size"); - else - config_set_int(cat, "mem_size", mem_size); - - config_set_int(cat, "cpu_use_dynarec", cpu_use_dynarec); - - if (enable_external_fpu == 0) - config_delete_var(cat, "cpu_enable_fpu"); - else - config_set_int(cat, "cpu_enable_fpu", enable_external_fpu); - - if (time_sync & TIME_SYNC_ENABLED) - if (time_sync & TIME_SYNC_UTC) - config_set_string(cat, "time_sync", "utc"); - else - config_set_string(cat, "time_sync", "local"); - else - config_set_string(cat, "time_sync", "disabled"); - - delete_section_if_empty(cat); -} - - -/* Save "Video" section. */ -static void -save_video(void) -{ - char *cat = "Video"; - - config_set_string(cat, "gfxcard", - video_get_internal_name(video_old_to_new(gfxcard))); - - if (voodoo_enabled == 0) - config_delete_var(cat, "voodoo"); - else - config_set_int(cat, "voodoo", voodoo_enabled); - - delete_section_if_empty(cat); -} - - -/* Save "Input Devices" section. */ -static void -save_input_devices(void) -{ - char *cat = "Input devices"; - char temp[512], tmp2[512]; - int c, d; - - config_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type)); - - if ((joystick_type == 0) || (joystick_type == 7)) { - if (joystick_type == 7) - config_delete_var(cat, "joystick_type"); - else - config_set_int(cat, "joystick_type", joystick_type); - - for (c=0; c<16; c++) { - sprintf(tmp2, "joystick_%i_nr", c); - config_delete_var(cat, tmp2); - - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_axis_%i", c, d); - config_delete_var(cat, tmp2); - } - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_button_%i", c, d); - config_delete_var(cat, tmp2); - } - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_pov_%i", c, d); - config_delete_var(cat, tmp2); - } - } - } else { - config_set_int(cat, "joystick_type", joystick_type); - - for (c=0; c> 1, hdd[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } - - sprintf(temp, "hdd_%02i_scsi_id", c+1); - if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_SCSI)) - config_set_int(cat, temp, hdd[c].scsi_id); - else - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_fn", c+1); - if (hdd_is_valid(c) && (wcslen(hdd[c].fn) != 0)) - config_set_wstring(cat, temp, hdd[c].fn); - else - config_delete_var(cat, temp); - } - - delete_section_if_empty(cat); -} - - -/* Save "Floppy Drives" section. */ -static void -save_floppy_drives(void) -{ - char *cat = "Floppy drives"; - char temp[512]; - int c; - - for (c=0; c 'Z') && (cdrom_drives[c].host_drive != 200))) { - config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, cdrom_drives[c].host_drive); - } - - sprintf(temp, "cdrom_%02i_speed", c+1); - if ((cdrom_drives[c].bus_type == 0) || (cdrom_drives[c].speed == 8)) { - config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, cdrom_drives[c].speed); - } - - sprintf(temp, "cdrom_%02i_parameters", c+1); - if (cdrom_drives[c].bus_type == 0) { - config_delete_var(cat, temp); - } else { - sprintf(tmp2, "%u, %s", cdrom_drives[c].sound_on, - hdd_bus_to_string(cdrom_drives[c].bus_type, 1)); - config_set_string(cat, temp, tmp2); - } - - sprintf(temp, "cdrom_%02i_ide_channel", c+1); - if (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI) - config_delete_var(cat, temp); - else { - sprintf(tmp2, "%01u:%01u", cdrom_drives[c].ide_channel>>1, - cdrom_drives[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } - - sprintf(temp, "cdrom_%02i_scsi_id", c + 1); - if (cdrom_drives[c].bus_type != CDROM_BUS_SCSI) { - config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, cdrom_drives[c].scsi_device_id); - } - - sprintf(temp, "cdrom_%02i_image_path", c + 1); - if ((cdrom_drives[c].bus_type == 0) || - (wcslen(cdrom_image[c].image_path) == 0)) { - config_delete_var(cat, temp); - } else { - config_set_wstring(cat, temp, cdrom_image[c].image_path); - } - } - - for (c=0; c>1, - zip_drives[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } - - sprintf(temp, "zip_%02i_scsi_id", c + 1); - if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { - config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, zip_drives[c].scsi_device_id); - } - - sprintf(temp, "zip_%02i_image_path", c + 1); - if ((zip_drives[c].bus_type == 0) || - (wcslen(zip_drives[c].image_path) == 0)) { - config_delete_var(cat, temp); - } else { - config_set_wstring(cat, temp, zip_drives[c].image_path); - } - } - - delete_section_if_empty(cat); -} - - -void -config_save(void) -{ - save_general(); /* General */ - save_machine(); /* Machine */ - save_video(); /* Video */ - save_input_devices(); /* Input devices */ - save_sound(); /* Sound */ - save_network(); /* Network */ - save_ports(); /* Ports (COM & LPT) */ - save_other_peripherals(); /* Other peripherals */ - save_hard_disks(); /* Hard disks */ - save_floppy_drives(); /* Floppy drives */ - save_other_removable_devices(); /* Other removable devices */ - - config_write(cfg_path); -} - - -void -config_dump(void) -{ - section_t *sec; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - entry_t *ent; - - if (sec->name && sec->name[0]) - config_log("[%s]\n", sec->name); - - ent = (entry_t *)sec->entry_head.next; - while (ent != NULL) { - config_log("%s = %ls\n", ent->name, ent->wdata); - - ent = (entry_t *)ent->list.next; - } - - sec = (section_t *)sec->list.next; - } -} - - -void -config_delete_var(char *head, char *name) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) return; - - entry = find_entry(section, name); - if (entry != NULL) { - list_delete(&entry->list, §ion->entry_head); - free(entry); - } -} - - -int -config_get_int(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%i", &value); - - return(value); -} - - -int -config_get_hex16(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%04X", &value); - - return(value); -} - - -int -config_get_hex20(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%05X", &value); - - return(value); -} - - -int -config_get_mac(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int val0 = 0, val1 = 0, val2 = 0; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2); - - return((val0 << 16) + (val1 << 8) + val2); -} - - -char * -config_get_string(char *head, char *name, char *def) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - return(entry->data); -} - - -wchar_t * -config_get_wstring(char *head, char *name, wchar_t *def) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - return(entry->wdata); -} - - -void -config_set_int(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%i", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_hex16(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%04X", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_hex20(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%05X", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_mac(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%02x:%02x:%02x", - (val>>16)&0xff, (val>>8)&0xff, val&0xff); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_string(char *head, char *name, char *val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - strncpy(ent->data, val, sizeof(ent->data)); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_wstring(char *head, char *name, wchar_t *val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - memcpy(ent->wdata, val, sizeof_w(ent->wdata)); - wcstombs(ent->data, ent->wdata, sizeof(ent->data)); -} diff --git a/src/config.c$ b/src/config.c$ deleted file mode 100644 index 7d323eafa..000000000 --- a/src/config.c$ +++ /dev/null @@ -1,2225 +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. - * - * Configuration file handler. - * - * Version: @(#)config.c 1.0.50 2018/08/27 - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * Overdoze, - * David Hrdlička, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2018 David Hrdlička. - * - * NOTE: Forcing config files to be in Unicode encoding breaks - * it on Windows XP, and possibly also Vista. Use the - * -DANSI_CFG for use on these systems. - */ -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "86box.h" -#include "cpu/cpu.h" -#include "device.h" -#include "nvr.h" -#include "config.h" -#include "lpt.h" -#include "disk/hdd.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" -#include "game/gameport.h" -#include "machine/machine.h" -#include "mouse.h" -#include "network/network.h" -#include "scsi/scsi.h" -#include "cdrom/cdrom.h" -#include "disk/zip.h" -#include "sound/sound.h" -#include "sound/midi.h" -#include "sound/snd_dbopl.h" -#include "sound/snd_mpu401.h" -#include "sound/snd_opl.h" -#include "sound/sound.h" -#include "video/video.h" -#include "plat.h" -#include "plat_midi.h" -#include "ui.h" - - -typedef struct _list_ { - struct _list_ *next; -} list_t; - -typedef struct { - list_t list; - - char name[128]; - - list_t entry_head; -} section_t; - -typedef struct { - list_t list; - - char name[128]; - char data[256]; - wchar_t wdata[512]; -} entry_t; - -#define list_add(new, head) { \ - list_t *next = head; \ - \ - while (next->next != NULL) \ - next = next->next; \ - \ - (next)->next = new; \ - (new)->next = NULL; \ -} - -#define list_delete(old, head) { \ - list_t *next = head; \ - \ - while ((next)->next != old) { \ - next = (next)->next; \ - } \ - \ - (next)->next = (old)->next; \ -} - - -static list_t config_head; - - -#ifdef ENABLE_CONFIG_LOG -int config_do_log = ENABLE_CONFIG_LOG; -#endif - - -static void -config_log(const char *format, ...) -{ -#ifdef ENABLE_CONFIG_LOG - va_list ap; - - if (config_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } -#endif -} - - -static section_t * -find_section(char *name) -{ - section_t *sec; - char blank[] = ""; - - sec = (section_t *)config_head.next; - if (name == NULL) - name = blank; - - while (sec != NULL) { - if (! strncmp(sec->name, name, sizeof(sec->name))) - return(sec); - - sec = (section_t *)sec->list.next; - } - - return(NULL); -} - - -static entry_t * -find_entry(section_t *section, char *name) -{ - entry_t *ent; - - ent = (entry_t *)section->entry_head.next; - - while (ent != NULL) { - if (! strncmp(ent->name, name, sizeof(ent->name))) - return(ent); - - ent = (entry_t *)ent->list.next; - } - - return(NULL); -} - - -static int -entries_num(section_t *section) -{ - entry_t *ent; - int i = 0; - - ent = (entry_t *)section->entry_head.next; - - while (ent != NULL) { - if (strlen(ent->name) > 0) i++; - - ent = (entry_t *)ent->list.next; - } - - return(i); -} - - -static void -delete_section_if_empty(char *head) -{ - section_t *section; - - section = find_section(head); - if (section == NULL) return; - - if (entries_num(section) == 0) { - list_delete(§ion->list, &config_head); - free(section); - } -} - - -static section_t * -create_section(char *name) -{ - section_t *ns = malloc(sizeof(section_t)); - - memset(ns, 0x00, sizeof(section_t)); - strncpy(ns->name, name, sizeof(ns->name)); - list_add(&ns->list, &config_head); - - return(ns); -} - - -static entry_t * -create_entry(section_t *section, char *name) -{ - entry_t *ne = malloc(sizeof(entry_t)); - - memset(ne, 0x00, sizeof(entry_t)); - strncpy(ne->name, name, sizeof(ne->name)); - list_add(&ne->list, §ion->entry_head); - - return(ne); -} - - -#if 0 -static void -config_free(void) -{ - section_t *sec, *ns; - entry_t *ent; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - ns = (section_t *)sec->list.next; - ent = (entry_t *)sec->entry_head.next; - - while (ent != NULL) { - entry_t *nent = (entry_t *)ent->list.next; - - free(ent); - ent = nent; - } - - free(sec); - sec = ns; - } -} -#endif - - -/* Read and parse the configuration file into memory. */ -static int -config_read(wchar_t *fn) -{ - char sname[128], ename[128]; - wchar_t buff[1024]; - section_t *sec, *ns; - entry_t *ne; - int c, d; - FILE *f; - -#if defined(ANSI_CFG) || !defined(_WIN32) - f = plat_fopen(fn, L"rt"); -#else - f = plat_fopen(fn, L"rt, ccs=UNICODE"); -#endif - if (f == NULL) return(0); - - sec = malloc(sizeof(section_t)); - memset(sec, 0x00, sizeof(section_t)); - memset(&config_head, 0x00, sizeof(list_t)); - list_add(&sec->list, &config_head); - - while (1) { - memset(buff, 0x00, sizeof(buff)); - fgetws(buff, sizeof_w(buff), f); - if (feof(f)) break; - - /* Make sure there are no stray newlines or hard-returns in there. */ - if (buff[wcslen(buff)-1] == L'\n') buff[wcslen(buff)-1] = L'\0'; - if (buff[wcslen(buff)-1] == L'\r') buff[wcslen(buff)-1] = L'\0'; - - /* Skip any leading whitespace. */ - c = 0; - while ((buff[c] == L' ') || (buff[c] == L'\t')) - c++; - - /* Skip empty lines. */ - if (buff[c] == L'\0') continue; - - /* Skip lines that (only) have a comment. */ - if ((buff[c] == L'#') || (buff[c] == L';')) continue; - - if (buff[c] == L'[') { /*Section*/ - c++; - d = 0; - while (buff[c] != L']' && buff[c]) - wctomb(&(sname[d++]), buff[c++]); - sname[d] = L'\0'; - - /* Is the section name properly terminated? */ - if (buff[c] != L']') continue; - - /* Create a new section and insert it. */ - ns = malloc(sizeof(section_t)); - memset(ns, 0x00, sizeof(section_t)); - strncpy(ns->name, sname, sizeof(ns->name)); - list_add(&ns->list, &config_head); - - /* New section is now the current one. */ - sec = ns; - continue; - } - - /* Get the variable name. */ - d = 0; - while ((buff[c] != L'=') && (buff[c] != L' ') && buff[c]) - wctomb(&(ename[d++]), buff[c++]); - ename[d] = L'\0'; - - /* Skip incomplete lines. */ - if (buff[c] == L'\0') continue; - - /* Look for =, skip whitespace. */ - while ((buff[c] == L'=' || buff[c] == L' ') && buff[c]) - c++; - - /* Skip incomplete lines. */ - if (buff[c] == L'\0') continue; - - /* This is where the value part starts. */ - d = c; - - /* Allocate a new variable entry.. */ - ne = malloc(sizeof(entry_t)); - memset(ne, 0x00, sizeof(entry_t)); - strncpy(ne->name, ename, sizeof(ne->name)); - wcsncpy(ne->wdata, &buff[d], sizeof_w(ne->wdata)-1); - ne->wdata[sizeof_w(ne->wdata)-1] = L'\0'; - wcstombs(ne->data, ne->wdata, sizeof(ne->data)); - ne->data[sizeof(ne->data)-1] = '\0'; - - /* .. and insert it. */ - list_add(&ne->list, &sec->entry_head); - } - - (void)fclose(f); - - if (do_dump_config) - config_dump(); - - return(1); -} - - -/* - * Write the in-memory configuration to disk. - * This is a public function, because the Settings UI - * want to directly write the configuration after it - * has changed it. - */ -void -config_write(wchar_t *fn) -{ - wchar_t wtemp[512]; - section_t *sec; - FILE *f; - int fl = 0; - -#if defined(ANSI_CFG) || !defined(_WIN32) - f = plat_fopen(fn, L"wt"); -#else - f = plat_fopen(fn, L"wt, ccs=UNICODE"); -#endif - if (f == NULL) return; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - entry_t *ent; - - if (sec->name[0]) { - mbstowcs(wtemp, sec->name, strlen(sec->name)+1); - if (fl) - fwprintf(f, L"\n[%ls]\n", wtemp); - else - fwprintf(f, L"[%ls]\n", wtemp); - fl++; - } - - ent = (entry_t *)sec->entry_head.next; - while (ent != NULL) { - if (ent->name[0] != '\0') { - mbstowcs(wtemp, ent->name, sizeof_w(wtemp)); - if (ent->wdata[0] == L'\0') - fwprintf(f, L"%ls = \n", wtemp); - else - fwprintf(f, L"%ls = %ls\n", wtemp, ent->wdata); - fl++; - } - - ent = (entry_t *)ent->list.next; - } - - sec = (section_t *)sec->list.next; - } - - (void)fclose(f); -} - - -#if NOT_USED -static void -config_new(void) -{ -#if defined(ANSI_CFG) || !defined(_WIN32) - FILE *f = _wfopen(config_file, L"wt"); -#else - FILE *f = _wfopen(config_file, L"wt, ccs=UNICODE"); -#endif - - if (file != NULL) - (void)fclose(f); -} -#endif - - -/* Load "General" section. */ -static void -load_general(void) -{ - char *cat = "General"; - char temp[512]; - char *p; - - vid_resize = !!config_get_int(cat, "vid_resize", 0); - - memset(temp, '\0', sizeof(temp)); - p = config_get_string(cat, "vid_renderer", "default"); - vid_api = plat_vidapi(p); - config_delete_var(cat, "vid_api"); - - video_fullscreen_scale = config_get_int(cat, "video_fullscreen_scale", 0); - - video_fullscreen_first = config_get_int(cat, "video_fullscreen_first", 0); - - force_43 = !!config_get_int(cat, "force_43", 0); - scale = config_get_int(cat, "scale", 1); - if (scale > 3) - scale = 3; - - enable_overscan = !!config_get_int(cat, "enable_overscan", 0); - vid_cga_contrast = !!config_get_int(cat, "vid_cga_contrast", 0); - video_grayscale = config_get_int(cat, "video_grayscale", 0); - video_graytype = config_get_int(cat, "video_graytype", 0); - - rctrl_is_lalt = config_get_int(cat, "rctrl_is_lalt", 0); - update_icons = config_get_int(cat, "update_icons", 1); - - window_remember = config_get_int(cat, "window_remember", 0); - if (window_remember) { - p = config_get_string(cat, "window_coordinates", NULL); - if (p == NULL) - p = "0, 0, 0, 0"; - sscanf(p, "%i, %i, %i, %i", &window_w, &window_h, &window_x, &window_y); - } else { - config_delete_var(cat, "window_remember"); - config_delete_var(cat, "window_coordinates"); - - window_w = window_h = window_x = window_y = 0; - } - - sound_gain = config_get_int(cat, "sound_gain", 0); - -#ifdef USE_LANGUAGE - /* - * Currently, 86Box is English (US) only, but in the future - * (version 3.0 at the earliest) other languages will be - * added, therefore it is better to future-proof the code. - */ - plat_langid = config_get_hex16(cat, "language", 0x0409); -#endif -} - - -/* Load "Machine" section. */ -static void -load_machine(void) -{ - char *cat = "Machine"; - char *p; - - p = config_get_string(cat, "machine", NULL); - if (p != NULL) - machine = machine_get_machine_from_internal_name(p); - else - machine = 0; - if (machine >= machine_count()) - machine = machine_count() - 1; - - /* This is for backwards compatibility. */ - p = config_get_string(cat, "model", NULL); - if (p != NULL) { - /* Detect the old model typos and fix them. */ - if (! strcmp(p, "p55r2p4")) { - machine = machine_get_machine_from_internal_name("p55t2p4"); - } else { - machine = machine_get_machine_from_internal_name(p); - } - config_delete_var(cat, "model"); - } - if (machine >= machine_count()) - machine = machine_count() - 1; - - romset = machine_getromset(); - cpu_manufacturer = config_get_int(cat, "cpu_manufacturer", 0); - cpu = config_get_int(cat, "cpu", 0); - cpu_waitstates = config_get_int(cat, "cpu_waitstates", 0); - - mem_size = config_get_int(cat, "mem_size", 4096); - if (mem_size < (((machines[machine].flags & MACHINE_AT) && - (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram)) - mem_size = (((machines[machine].flags & MACHINE_AT) && (machines[machine].ram_granularity < 128)) ? machines[machine].min_ram*1024 : machines[machine].min_ram); - if (mem_size > 1048576) - mem_size = 1048576; - - cpu_use_dynarec = !!config_get_int(cat, "cpu_use_dynarec", 0); - - enable_external_fpu = !!config_get_int(cat, "cpu_enable_fpu", 0); - - p = config_get_string(cat, "time_sync", NULL); - if (p != NULL) { - if (!strcmp(p, "disabled")) - time_sync = TIME_SYNC_DISABLED; - else - if (!strcmp(p, "local")) - time_sync = TIME_SYNC_ENABLED; - else - if (!strcmp(p, "utc") || !strcmp(p, "gmt")) - time_sync = TIME_SYNC_ENABLED | TIME_SYNC_UTC; - else - time_sync = TIME_SYNC_ENABLED; - } else - time_sync = !!config_get_int(cat, "enable_sync", 1); - - /* Remove this after a while.. */ - config_delete_var(cat, "nvr_path"); - config_delete_var(cat, "enable_sync"); -} - - -/* Load "Video" section. */ -static void -load_video(void) -{ - char *cat = "Video"; - char *p; - - if (machines[machine].fixed_gfxcard) { - config_delete_var(cat, "gfxcard"); - gfxcard = GFX_INTERNAL; - } else { - p = config_get_string(cat, "gfxcard", NULL); - if (p == NULL) { - if (machines[machine].flags & MACHINE_VIDEO) { - p = (char *)malloc((strlen("internal")+1)*sizeof(char)); - strcpy(p, "internal"); - } else { - p = (char *)malloc((strlen("none")+1)*sizeof(char)); - strcpy(p, "none"); - } - } - gfxcard = video_get_video_from_internal_name(p); - } - - voodoo_enabled = !!config_get_int(cat, "voodoo", 0); -} - - -/* Load "Input Devices" section. */ -static void -load_input_devices(void) -{ - char *cat = "Input devices"; - char temp[512]; - int c, d; - char *p; - - p = config_get_string(cat, "mouse_type", NULL); - if (p != NULL) - mouse_type = mouse_get_from_internal_name(p); - else - mouse_type = 0; - - joystick_type = config_get_int(cat, "joystick_type", 7); - - for (c=0; c max_spt) - hdd[c].spt = max_spt; - if (hdd[c].hpc > max_hpc) - hdd[c].hpc = max_hpc; - if (hdd[c].tracks > max_tracks) - hdd[c].tracks = max_tracks; - - /* MFM/RLL */ - sprintf(temp, "hdd_%02i_mfm_channel", c+1); - if (hdd[c].bus == HDD_BUS_MFM) - hdd[c].mfm_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); - - /* XTA */ - sprintf(temp, "hdd_%02i_xta_channel", c+1); - if (hdd[c].bus == HDD_BUS_XTA) - hdd[c].xta_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); - - /* ESDI */ - sprintf(temp, "hdd_%02i_esdi_channel", c+1); - if (hdd[c].bus == HDD_BUS_ESDI) - hdd[c].esdi_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); - - /* IDE */ - // FIXME: Remove in a month. - sprintf(temp, "hdd_%02i_xtide_channel", c+1); - if (hdd[c].bus == HDD_BUS_IDE) - hdd[c].ide_channel = !!config_get_int(cat, temp, c & 1); - else - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_ide_channel", c+1); - if (hdd[c].bus == HDD_BUS_IDE) { - sprintf(tmp2, "%01u:%01u", c>>1, c&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - hdd[c].ide_channel = (board<<1) + dev; - - if (hdd[c].ide_channel > 7) - hdd[c].ide_channel = 7; - } else { - config_delete_var(cat, temp); - } - - /* SCSI */ - sprintf(temp, "hdd_%02i_scsi_id", c+1); - if (hdd[c].bus == HDD_BUS_SCSI) { - hdd[c].scsi_id = config_get_int(cat, temp, c); - - if (hdd[c].scsi_id > 15) - hdd[c].scsi_id = 15; - } else - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "hdd_%02i_scsi_location", c+1); - if (hdd[c].bus == HDD_BUS_SCSI) { - p = config_get_string(cat, temp, NULL); - - if (p) { - sscanf(p, "%02i:%02i", - (int *)&hdd[c].scsi_id, (int *)&lun); - - if (hdd[c].scsi_id > 15) - hdd[c].scsi_id = 15; - } - } - config_delete_var(cat, temp); - - memset(hdd[c].fn, 0x00, sizeof(hdd[c].fn)); - memset(hdd[c].prev_fn, 0x00, sizeof(hdd[c].prev_fn)); - sprintf(temp, "hdd_%02i_fn", c+1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the CFG path. Just strip - * that off for now... - */ - wcsncpy(hdd[c].fn, &wp[wcslen(usr_path)], sizeof_w(hdd[c].fn)); - } else -#endif - wcsncpy(hdd[c].fn, wp, sizeof_w(hdd[c].fn)); - - /* If disk is empty or invalid, mark it for deletion. */ - if (! hdd_is_valid(c)) { - sprintf(temp, "hdd_%02i_parameters", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_preide_channels", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_ide_channels", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_scsi_id", c+1); - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "hdd_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_fn", c+1); - config_delete_var(cat, temp); - } - - sprintf(temp, "hdd_%02i_mfm_channel", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - } -} - - -/* Load "Floppy Drives" section. */ -static void -load_floppy_drives(void) -{ - char *cat = "Floppy drives"; - char temp[512], *p; - wchar_t *wp; - int c; - - for (c=0; c 13) - fdd_set_type(c, 13); - - sprintf(temp, "fdd_%02i_fn", c + 1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(floppyfns[c], &wp[wcslen(usr_path)], sizeof_w(floppyfns[c])); - } else -#endif - wcsncpy(floppyfns[c], wp, sizeof_w(floppyfns[c])); - - /* if (*wp != L'\0') - config_log("Floppy%d: %ls\n", c, floppyfns[c]); */ - sprintf(temp, "fdd_%02i_writeprot", c+1); - ui_writeprot[c] = !!config_get_int(cat, temp, 0); - sprintf(temp, "fdd_%02i_turbo", c + 1); - fdd_set_turbo(c, !!config_get_int(cat, temp, 0)); - sprintf(temp, "fdd_%02i_check_bpb", c+1); - fdd_set_check_bpb(c, !!config_get_int(cat, temp, 1)); - - /* Check whether each value is default, if yes, delete it so that only non-default values will later be saved. */ - if (fdd_get_type(c) == ((c < 2) ? 2 : 0)) { - sprintf(temp, "fdd_%02i_type", c+1); - config_delete_var(cat, temp); - } - if (wcslen(floppyfns[c]) == 0) { - sprintf(temp, "fdd_%02i_fn", c+1); - config_delete_var(cat, temp); - } - if (ui_writeprot[c] == 0) { - sprintf(temp, "fdd_%02i_writeprot", c+1); - config_delete_var(cat, temp); - } - if (fdd_get_turbo(c) == 0) { - sprintf(temp, "fdd_%02i_turbo", c+1); - config_delete_var(cat, temp); - } - if (fdd_get_check_bpb(c) == 1) { - sprintf(temp, "fdd_%02i_check_bpb", c+1); - config_delete_var(cat, temp); - } - } -} - - -/* Load "Other Removable Devices" section. */ -static void -load_other_removable_devices(void) -{ - char *cat = "Other removable devices"; - char temp[512], tmp2[512], *p; - char s[512]; - unsigned int board = 0, dev = 0; - wchar_t *wp; - int c; - /* FIXME: Remove in a month. */ - int lun; - - memset(temp, 0x00, sizeof(temp)); - for (c=0; c>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - cdrom_drives[c].ide_channel = (board<<1)+dev; - - if (cdrom_drives[c].ide_channel > 7) - cdrom_drives[c].ide_channel = 7; - } else { - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { - cdrom_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); - - if (cdrom_drives[c].scsi_device_id > 15) - cdrom_drives[c].scsi_device_id = 15; - } else - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - if (cdrom_drives[c].bus_type == CDROM_BUS_SCSI) { - p = config_get_string(cat, temp, NULL); - if (p) { - sscanf(p, "%02u:%02u", - &cdrom_drives[c].scsi_device_id, &lun); - - if (cdrom_drives[c].scsi_device_id > 15) - cdrom_drives[c].scsi_device_id = 15; - } - } - config_delete_var(cat, temp); - } - - sprintf(temp, "cdrom_%02i_image_path", c+1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(cdrom_image[c].image_path, &wp[wcslen(usr_path)], sizeof_w(cdrom_image[c].image_path)); - } else -#endif - wcsncpy(cdrom_image[c].image_path, wp, sizeof_w(cdrom_image[c].image_path)); - - if (cdrom_drives[c].host_drive < 'A') - cdrom_drives[c].host_drive = 0; - - if ((cdrom_drives[c].host_drive == 0x200) && - (wcslen(cdrom_image[c].image_path) == 0)) - cdrom_drives[c].host_drive = 0; - - /* If the CD-ROM is disabled, delete all its variables. */ - if (cdrom_drives[c].bus_type == CDROM_BUS_DISABLED) { - sprintf(temp, "cdrom_%02i_host_drive", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_parameters", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_scsi_id", c+1); - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "cdrom_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "cdrom_%02i_image_path", c+1); - config_delete_var(cat, temp); - } - - sprintf(temp, "cdrom_%02i_iso_path", c+1); - config_delete_var(cat, temp); - } - - memset(temp, 0x00, sizeof(temp)); - for (c=0; c>1, (c+2)&1); - p = config_get_string(cat, temp, tmp2); - sscanf(p, "%01u:%01u", &board, &dev); - board &= 3; - dev &= 1; - zip_drives[c].ide_channel = (board<<1)+dev; - - if (zip_drives[c].ide_channel > 7) - zip_drives[c].ide_channel = 7; - } else { - sprintf(temp, "zip_%02i_scsi_id", c+1); - if (zip_drives[c].bus_type == CDROM_BUS_SCSI) { - zip_drives[c].scsi_device_id = config_get_int(cat, temp, c+2); - - if (zip_drives[c].scsi_device_id > 15) - zip_drives[c].scsi_device_id = 15; - } else - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "zip_%02i_scsi_location", c+1); - if (zip_drives[c].bus_type == CDROM_BUS_SCSI) { - p = config_get_string(cat, temp, NULL); - if (p) { - sscanf(p, "%02u:%02u", - &zip_drives[c].scsi_device_id, &lun); - - if (zip_drives[c].scsi_device_id > 15) - zip_drives[c].scsi_device_id = 15; - } - } - config_delete_var(cat, temp); - } - - sprintf(temp, "zip_%02i_image_path", c+1); - wp = config_get_wstring(cat, temp, L""); - -#if 0 - /* - * NOTE: - * Temporary hack to remove the absolute - * path currently saved in most config - * files. We should remove this before - * finalizing this release! --FvK - */ - if (! wcsnicmp(wp, usr_path, wcslen(usr_path))) { - /* - * Yep, its absolute and prefixed - * with the EXE path. Just strip - * that off for now... - */ - wcsncpy(zip_drives[c].image_path, &wp[wcslen(usr_path)], sizeof_w(zip_drives[c].image_path)); - } else -#endif - wcsncpy(zip_drives[c].image_path, wp, sizeof_w(zip_drives[c].image_path)); - - /* If the CD-ROM is disabled, delete all its variables. */ - if (zip_drives[c].bus_type == ZIP_BUS_DISABLED) { - sprintf(temp, "zip_%02i_host_drive", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "zip_%02i_parameters", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "zip_%02i_ide_channel", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "zip_%02i_scsi_id", c+1); - config_delete_var(cat, temp); - - /* FIXME: Remove in a month. */ - sprintf(temp, "zip_%02i_scsi_location", c+1); - config_delete_var(cat, temp); - - sprintf(temp, "zip_%02i_image_path", c+1); - config_delete_var(cat, temp); - } - - sprintf(temp, "zip_%02i_iso_path", c+1); - config_delete_var(cat, temp); - } -} - - -/* Load the specified or a default configuration file. */ -void -config_load(void) -{ - int i; - - config_log("Loading config file '%ls'..\n", cfg_path); - - memset(hdd, 0, sizeof(hard_disk_t)); - memset(cdrom_drives, 0, sizeof(cdrom_drive_t) * CDROM_NUM); - memset(cdrom_image, 0, sizeof(cdrom_image_t) * CDROM_NUM); -#ifdef USE_IOCTL - memset(cdrom_ioctl, 0, sizeof(cdrom_ioctl_t) * CDROM_NUM); -#endif - memset(zip_drives, 0, sizeof(zip_drive_t)); - - if (! config_read(cfg_path)) { - cpu = 0; -#ifdef USE_LANGUAGE - plat_langid = 0x0409; -#endif - scale = 1; - machine = machine_get_machine_from_internal_name("ibmpc"); - gfxcard = GFX_CGA; - vid_api = plat_vidapi("default"); - time_sync = TIME_SYNC_ENABLED; - joystick_type = 7; - if (hdc_name) { - free(hdc_name); - hdc_name = NULL; - } - hdc_name = (char *) malloc((strlen("none")+1) * sizeof(char)); - strcpy(hdc_name, "none"); - serial_enabled[0] = 1; - serial_enabled[1] = 1; - lpt_enabled = 1; - for (i = 0; i < FDD_NUM; i++) { - if (i < 2) - fdd_set_type(i, 2); - else - fdd_set_type(i, 0); - - fdd_set_turbo(i, 0); - fdd_set_check_bpb(i, 1); - } - mem_size = 640; - opl_type = 0; - - config_log("Config file not present or invalid!\n"); - return; - } - - load_general(); /* General */ - load_machine(); /* Machine */ - load_video(); /* Video */ - load_input_devices(); /* Input devices */ - load_sound(); /* Sound */ - load_network(); /* Network */ - load_ports(); /* Ports (COM & LPT) */ - load_other_peripherals(); /* Other peripherals */ - load_hard_disks(); /* Hard disks */ - load_floppy_drives(); /* Floppy drives */ - load_other_removable_devices(); /* Other removable devices */ - - /* Mark the configuration as changed. */ - config_changed = 1; - - config_log("Config loaded.\n\n"); -} - - -/* Save "General" section. */ -static void -save_general(void) -{ - char *cat = "General"; - char temp[512]; - - char *va_name; - - config_set_int(cat, "vid_resize", vid_resize); - if (vid_resize == 0) - config_delete_var(cat, "vid_resize"); - - va_name = plat_vidapi_name(vid_api); - if (!strcmp(va_name, "default")) { - config_delete_var(cat, "vid_renderer"); - } else { - config_set_string(cat, "vid_renderer", va_name); - } - - if (video_fullscreen_scale == 0) - config_delete_var(cat, "video_fullscreen_scale"); - else - config_set_int(cat, "video_fullscreen_scale", video_fullscreen_scale); - - if (video_fullscreen_first == 0) - config_delete_var(cat, "video_fullscreen_first"); - else - config_set_int(cat, "video_fullscreen_first", video_fullscreen_first); - - if (force_43 == 0) - config_delete_var(cat, "force_43"); - else - config_set_int(cat, "force_43", force_43); - - if (scale == 1) - config_delete_var(cat, "scale"); - else - config_set_int(cat, "scale", scale); - - if (enable_overscan == 0) - config_delete_var(cat, "enable_overscan"); - else - config_set_int(cat, "enable_overscan", enable_overscan); - - if (vid_cga_contrast == 0) - config_delete_var(cat, "vid_cga_contrast"); - else - config_set_int(cat, "vid_cga_contrast", vid_cga_contrast); - - if (video_grayscale == 0) - config_delete_var(cat, "video_grayscale"); - else - config_set_int(cat, "video_grayscale", video_grayscale); - - if (video_graytype == 0) - config_delete_var(cat, "video_graytype"); - else - config_set_int(cat, "video_graytype", video_graytype); - - if (rctrl_is_lalt == 0) - config_delete_var(cat, "rctrl_is_lalt"); - else - config_set_int(cat, "rctrl_is_lalt", rctrl_is_lalt); - - if (update_icons == 1) - config_delete_var(cat, "update_icons"); - else - config_set_int(cat, "update_icons", update_icons); - - if (window_remember) { - config_set_int(cat, "window_remember", window_remember); - - sprintf(temp, "%i, %i, %i, %i", window_w, window_h, window_x, window_y); - config_set_string(cat, "window_coordinates", temp); - } else { - config_delete_var(cat, "window_remember"); - config_delete_var(cat, "window_coordinates"); - } - - if (sound_gain != 0) - config_set_int(cat, "sound_gain", sound_gain); - else - config_delete_var(cat, "sound_gain"); - -#ifdef USE_LANGUAGE - if (plat_langid == 0x0409) - config_delete_var(cat, "language"); - else - config_set_hex16(cat, "language", plat_langid); -#endif - - delete_section_if_empty(cat); -} - - -/* Save "Machine" section. */ -static void -save_machine(void) -{ - char *cat = "Machine"; - - config_set_string(cat, "machine", machine_get_internal_name()); - - if (cpu_manufacturer == 0) - config_delete_var(cat, "cpu_manufacturer"); - else - config_set_int(cat, "cpu_manufacturer", cpu_manufacturer); - - if (cpu == 0) - config_delete_var(cat, "cpu"); - else - config_set_int(cat, "cpu", cpu); - - if (cpu_waitstates == 0) - config_delete_var(cat, "cpu_waitstates"); - else - config_set_int(cat, "cpu_waitstates", cpu_waitstates); - - if (mem_size == 4096) - config_delete_var(cat, "mem_size"); - else - config_set_int(cat, "mem_size", mem_size); - - config_set_int(cat, "cpu_use_dynarec", cpu_use_dynarec); - - if (enable_external_fpu == 0) - config_delete_var(cat, "cpu_enable_fpu"); - else - config_set_int(cat, "cpu_enable_fpu", enable_external_fpu); - - if (time_sync & TIME_SYNC_ENABLED) - if (time_sync & TIME_SYNC_UTC) - config_set_string(cat, "time_sync", "utc"); - else - config_set_string(cat, "time_sync", "local"); - else - config_set_string(cat, "time_sync", "disabled"); - - delete_section_if_empty(cat); -} - - -/* Save "Video" section. */ -static void -save_video(void) -{ - char *cat = "Video"; - - config_set_string(cat, "gfxcard", - video_get_internal_name(video_old_to_new(gfxcard))); - - if (voodoo_enabled == 0) - config_delete_var(cat, "voodoo"); - else - config_set_int(cat, "voodoo", voodoo_enabled); - - delete_section_if_empty(cat); -} - - -/* Save "Input Devices" section. */ -static void -save_input_devices(void) -{ - char *cat = "Input devices"; - char temp[512], tmp2[512]; - int c, d; - - config_set_string(cat, "mouse_type", mouse_get_internal_name(mouse_type)); - - if ((joystick_type == 0) || (joystick_type == 7)) { - if (joystick_type == 7) - config_delete_var(cat, "joystick_type"); - else - config_set_int(cat, "joystick_type", joystick_type); - - for (c=0; c<16; c++) { - sprintf(tmp2, "joystick_%i_nr", c); - config_delete_var(cat, tmp2); - - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_axis_%i", c, d); - config_delete_var(cat, tmp2); - } - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_button_%i", c, d); - config_delete_var(cat, tmp2); - } - for (d=0; d<16; d++) { - sprintf(tmp2, "joystick_%i_pov_%i", c, d); - config_delete_var(cat, tmp2); - } - } - } else { - config_set_int(cat, "joystick_type", joystick_type); - - for (c=0; c> 1, hdd[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } - - sprintf(temp, "hdd_%02i_scsi_id", c+1); - if (hdd_is_valid(c) && (hdd[c].bus == HDD_BUS_SCSI)) - config_set_int(cat, temp, hdd[c].scsi_id); - else - config_delete_var(cat, temp); - - sprintf(temp, "hdd_%02i_fn", c+1); - if (hdd_is_valid(c) && (wcslen(hdd[c].fn) != 0)) - config_set_wstring(cat, temp, hdd[c].fn); - else - config_delete_var(cat, temp); - } - - delete_section_if_empty(cat); -} - - -/* Save "Floppy Drives" section. */ -static void -save_floppy_drives(void) -{ - char *cat = "Floppy drives"; - char temp[512]; - int c; - - for (c=0; c 'Z') && (cdrom_drives[c].host_drive != 200))) { - config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, cdrom_drives[c].host_drive); - } - - sprintf(temp, "cdrom_%02i_speed", c+1); - if ((cdrom_drives[c].bus_type == 0) || (cdrom_drives[c].speed == 8)) { - config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, cdrom_drives[c].speed); - } - - sprintf(temp, "cdrom_%02i_parameters", c+1); - if (cdrom_drives[c].bus_type == 0) { - config_delete_var(cat, temp); - } else { - sprintf(tmp2, "%u, %s", cdrom_drives[c].sound_on, - hdd_bus_to_string(cdrom_drives[c].bus_type, 1)); - config_set_string(cat, temp, tmp2); - } - - sprintf(temp, "cdrom_%02i_ide_channel", c+1); - if (cdrom_drives[c].bus_type != CDROM_BUS_ATAPI) - config_delete_var(cat, temp); - else { - sprintf(tmp2, "%01u:%01u", cdrom_drives[c].ide_channel>>1, - cdrom_drives[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } - - sprintf(temp, "cdrom_%02i_scsi_id", c + 1); - if (cdrom_drives[c].bus_type != CDROM_BUS_SCSI) { - config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, cdrom_drives[c].scsi_device_id); - } - - sprintf(temp, "cdrom_%02i_image_path", c + 1); - if ((cdrom_drives[c].bus_type == 0) || - (wcslen(cdrom_image[c].image_path) == 0)) { - config_delete_var(cat, temp); - } else { - config_set_wstring(cat, temp, cdrom_image[c].image_path); - } - } - - for (c=0; c>1, - zip_drives[c].ide_channel & 1); - config_set_string(cat, temp, tmp2); - } - - sprintf(temp, "zip_%02i_scsi_id", c + 1); - if (zip_drives[c].bus_type != ZIP_BUS_SCSI) { - config_delete_var(cat, temp); - } else { - config_set_int(cat, temp, zip_drives[c].scsi_device_id); - } - - sprintf(temp, "zip_%02i_image_path", c + 1); - if ((zip_drives[c].bus_type == 0) || - (wcslen(zip_drives[c].image_path) == 0)) { - config_delete_var(cat, temp); - } else { - config_set_wstring(cat, temp, zip_drives[c].image_path); - } - } - - delete_section_if_empty(cat); -} - - -void -config_save(void) -{ - save_general(); /* General */ - save_machine(); /* Machine */ - save_video(); /* Video */ - save_input_devices(); /* Input devices */ - save_sound(); /* Sound */ - save_network(); /* Network */ - save_ports(); /* Ports (COM & LPT) */ - save_other_peripherals(); /* Other peripherals */ - save_hard_disks(); /* Hard disks */ - save_floppy_drives(); /* Floppy drives */ - save_other_removable_devices(); /* Other removable devices */ - - config_write(cfg_path); -} - - -void -config_dump(void) -{ - section_t *sec; - - sec = (section_t *)config_head.next; - while (sec != NULL) { - entry_t *ent; - - if (sec->name && sec->name[0]) - config_log("[%s]\n", sec->name); - - ent = (entry_t *)sec->entry_head.next; - while (ent != NULL) { - config_log("%s = %ls\n", ent->name, ent->wdata); - - ent = (entry_t *)ent->list.next; - } - - sec = (section_t *)sec->list.next; - } -} - - -void -config_delete_var(char *head, char *name) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) return; - - entry = find_entry(section, name); - if (entry != NULL) { - list_delete(&entry->list, §ion->entry_head); - free(entry); - } -} - - -int -config_get_int(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%i", &value); - - return(value); -} - - -int -config_get_hex16(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%04X", &value); - - return(value); -} - - -int -config_get_hex20(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int value; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%05X", &value); - - return(value); -} - - -int -config_get_mac(char *head, char *name, int def) -{ - section_t *section; - entry_t *entry; - unsigned int val0 = 0, val1 = 0, val2 = 0; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - sscanf(entry->data, "%02x:%02x:%02x", &val0, &val1, &val2); - - return((val0 << 16) + (val1 << 8) + val2); -} - - -char * -config_get_string(char *head, char *name, char *def) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - return(entry->data); -} - - -wchar_t * -config_get_wstring(char *head, char *name, wchar_t *def) -{ - section_t *section; - entry_t *entry; - - section = find_section(head); - if (section == NULL) - return(def); - - entry = find_entry(section, name); - if (entry == NULL) - return(def); - - return(entry->wdata); -} - - -void -config_set_int(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%i", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_hex16(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%04X", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_hex20(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%05X", val); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_mac(char *head, char *name, int val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - sprintf(ent->data, "%02x:%02x:%02x", - (val>>16)&0xff, (val>>8)&0xff, val&0xff); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_string(char *head, char *name, char *val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - strncpy(ent->data, val, sizeof(ent->data)); - mbstowcs(ent->wdata, ent->data, sizeof_w(ent->wdata)); -} - - -void -config_set_wstring(char *head, char *name, wchar_t *val) -{ - section_t *section; - entry_t *ent; - - section = find_section(head); - if (section == NULL) - section = create_section(head); - - ent = find_entry(section, name); - if (ent == NULL) - ent = create_entry(section, name); - - memcpy(ent->wdata, val, sizeof_w(ent->wdata)); - wcstombs(ent->data, ent->wdata, sizeof(ent->data)); -} diff --git a/src/cpu/808x - Cópia.c b/src/cpu/808x - Cópia.c deleted file mode 100644 index 53e2403cc..000000000 --- a/src/cpu/808x - Cópia.c +++ /dev/null @@ -1,3324 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * 808x CPU emulation. - * - * SHR AX,1 - * - * 4 clocks - fetch opcode - * 4 clocks - fetch mod/rm - * 2 clocks - execute 2 clocks - fetch opcode 1 - * 2 clocks - fetch opcode 2 - * 4 clocks - fetch mod/rm - * 2 clocks - fetch opcode 1 2 clocks - execute - * 2 clocks - fetch opcode 2 etc - * - * Version: @(#)808x.c 1.0.5 2018/04/29 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "cpu.h" -#include "x86.h" -#include "../machine/machine.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../nmi.h" -#include "../pic.h" -#include "../timer.h" -#include "../plat.h" - - -int xt_cpu_multi; -int nmi = 0; -int nmi_auto_clear = 0; - -int nextcyc=0; -int cycdiff; -int is8086=0; - -int memcycs; -int nopageerrors=0; - -void FETCHCOMPLETE(); - -uint8_t readmembl(uint32_t addr); -void writemembl(uint32_t addr, uint8_t val); -uint16_t readmemwl(uint32_t seg, uint32_t addr); -void writememwl(uint32_t seg, uint32_t addr, uint16_t val); -uint32_t readmemll(uint32_t seg, uint32_t addr); -void writememll(uint32_t seg, uint32_t addr, uint32_t val); - - -#ifdef ENABLE_808X_LOG -int x808x_do_log = ENABLE_808X_LOG; -#endif - - -static void -x808x_log(const char *fmt, ...) -{ -#ifdef ENABLE_808X_LOG - va_list ap; - - if (x808x_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -#undef readmemb -#undef readmemw -uint8_t readmemb(uint32_t a) -{ - if (a!=(cs+cpu_state.pc)) memcycs+=4; - if (readlookup2 == NULL) return readmembl(a); - if (readlookup2[(a)>>12]==-1) return readmembl(a); - else return *(uint8_t *)(readlookup2[(a) >> 12] + (a)); -} - -uint8_t readmembf(uint32_t a) -{ - if (readlookup2 == NULL) return readmembl(a); - if (readlookup2[(a)>>12]==-1) return readmembl(a); - else return *(uint8_t *)(readlookup2[(a) >> 12] + (a)); -} - -uint16_t readmemw(uint32_t s, uint16_t a) -{ - if (a!=(cs+cpu_state.pc)) memcycs+=(8>>is8086); - if (readlookup2 == NULL) return readmemwl(s,a); - if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s,a); - else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a); -} - -void refreshread() { FETCHCOMPLETE(); memcycs+=4; } - -#undef fetchea -#define fetchea() { rmdat=FETCH(); \ - cpu_reg=(rmdat>>3)&7; \ - cpu_mod=(rmdat>>6)&3; \ - cpu_rm=rmdat&7; \ - if (cpu_mod!=3) fetcheal(); } - -void writemembl(uint32_t addr, uint8_t val); -void writememb(uint32_t a, uint8_t v) -{ - memcycs+=4; - if (writelookup2 == NULL) writemembl(a,v); - if (writelookup2[(a)>>12]==-1) writemembl(a,v); - else *(uint8_t *)(writelookup2[a >> 12] + a) = v; -} -void writememwl(uint32_t seg, uint32_t addr, uint16_t val); -void writememw(uint32_t s, uint32_t a, uint16_t v) -{ - memcycs+=(8>>is8086); - if (writelookup2 == NULL) writememwl(s,a,v); - if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s,a,v); - else *(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v; -} -void writememll(uint32_t seg, uint32_t addr, uint32_t val); -void writememl(uint32_t s, uint32_t a, uint32_t v) -{ - if (writelookup2 == NULL) writememll(s,a,v); - if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememll(s,a,v); - else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v; -} - - -void dumpregs(int); -uint16_t oldcs; -int oldcpl; - -int tempc; -uint8_t opcode; -uint16_t pc2,pc3; -int noint=0; - -int output=0; - -#if 0 -/* Also in mem.c */ -int shadowbios=0; -#endif - -int ins=0; - -int fetchcycles=0,memcycs,fetchclocks; - -uint8_t prefetchqueue[6]; -uint16_t prefetchpc; -int prefetchw=0; -static __inline uint8_t FETCH() -{ - uint8_t temp; -/* temp=prefetchqueue[0]; - prefetchqueue[0]=prefetchqueue[1]; - prefetchqueue[1]=prefetchqueue[2]; - prefetchqueue[2]=prefetchqueue[3]; - prefetchqueue[3]=prefetchqueue[4]; - prefetchqueue[4]=prefetchqueue[5]; - if (prefetchw<=((is8086)?4:3)) - { - prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++; - if (is8086 && (prefetchpc&1)) - { - prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++; - } - }*/ - - if (prefetchw==0) - { - cycles-=(4-(fetchcycles&3)); - fetchclocks+=(4-(fetchcycles&3)); - fetchcycles=4; - temp=readmembf(cs+cpu_state.pc); - prefetchpc = cpu_state.pc = cpu_state.pc + 1; - if (is8086 && (cpu_state.pc&1)) - { - prefetchqueue[0]=readmembf(cs+cpu_state.pc); - prefetchpc++; - prefetchw++; - } - } - else - { - temp=prefetchqueue[0]; - prefetchqueue[0]=prefetchqueue[1]; - prefetchqueue[1]=prefetchqueue[2]; - prefetchqueue[2]=prefetchqueue[3]; - prefetchqueue[3]=prefetchqueue[4]; - prefetchqueue[4]=prefetchqueue[5]; - prefetchw--; - fetchcycles-=4; - cpu_state.pc++; - } - return temp; -} - -static __inline void FETCHADD(int c) -{ - int d; - if (c<0) return; - if (prefetchw>((is8086)?4:3)) return; - d=c+(fetchcycles&3); - while (d>3 && prefetchw<((is8086)?6:4)) - { - d-=4; - if (is8086 && !(prefetchpc&1)) - { - prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); - prefetchpc++; - prefetchw++; - } - if (prefetchw<6) - { - prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); - prefetchpc++; - prefetchw++; - } - } - fetchcycles+=c; - if (fetchcycles>16) fetchcycles=16; -} - -void FETCHCOMPLETE() -{ - if (!(fetchcycles&3)) return; - if (prefetchw>((is8086)?4:3)) return; - if (!prefetchw) nextcyc=(4-(fetchcycles&3)); - cycles-=(4-(fetchcycles&3)); - fetchclocks+=(4-(fetchcycles&3)); - if (is8086 && !(prefetchpc&1)) - { - prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); - prefetchpc++; - prefetchw++; - } - if (prefetchw<6) - { - prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); - prefetchpc++; - prefetchw++; - } - fetchcycles+=(4-(fetchcycles&3)); -} - -static __inline void FETCHCLEAR() -{ - prefetchpc=cpu_state.pc; - prefetchw=0; - memcycs=cycdiff-cycles; - fetchclocks=0; -} - -static uint16_t getword() -{ - uint8_t temp=FETCH(); - return temp|(FETCH()<<8); -} - - -/*EA calculation*/ - -/*R/M - bits 0-2 - R/M bits 3-5 - Reg bits 6-7 - mod - From 386 programmers manual : -r8(/r) AL CL DL BL AH CH DH BH -r16(/r) AX CX DX BX SP BP SI DI -r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI -/digit (Opcode) 0 1 2 3 4 5 6 7 -REG = 000 001 010 011 100 101 110 111 - ����Address -disp8 denotes an 8-bit displacement following the ModR/M byte, to be -sign-extended and added to the index. disp16 denotes a 16-bit displacement -following the ModR/M byte, to be added to the index. Default segment -register is SS for the effective addresses containing a BP index, DS for -other effective addresses. - �Ŀ �Mod R/M� ���������ModR/M Values in Hexadecimal�������Ŀ - -[BX + SI] 000 00 08 10 18 20 28 30 38 -[BX + DI] 001 01 09 11 19 21 29 31 39 -[BP + SI] 010 02 0A 12 1A 22 2A 32 3A -[BP + DI] 011 03 0B 13 1B 23 2B 33 3B -[SI] 00 100 04 0C 14 1C 24 2C 34 3C -[DI] 101 05 0D 15 1D 25 2D 35 3D -disp16 110 06 0E 16 1E 26 2E 36 3E -[BX] 111 07 0F 17 1F 27 2F 37 3F - -[BX+SI]+disp8 000 40 48 50 58 60 68 70 78 -[BX+DI]+disp8 001 41 49 51 59 61 69 71 79 -[BP+SI]+disp8 010 42 4A 52 5A 62 6A 72 7A -[BP+DI]+disp8 011 43 4B 53 5B 63 6B 73 7B -[SI]+disp8 01 100 44 4C 54 5C 64 6C 74 7C -[DI]+disp8 101 45 4D 55 5D 65 6D 75 7D -[BP]+disp8 110 46 4E 56 5E 66 6E 76 7E -[BX]+disp8 111 47 4F 57 5F 67 6F 77 7F - -[BX+SI]+disp16 000 80 88 90 98 A0 A8 B0 B8 -[BX+DI]+disp16 001 81 89 91 99 A1 A9 B1 B9 -[BX+SI]+disp16 010 82 8A 92 9A A2 AA B2 BA -[BX+DI]+disp16 011 83 8B 93 9B A3 AB B3 BB -[SI]+disp16 10 100 84 8C 94 9C A4 AC B4 BC -[DI]+disp16 101 85 8D 95 9D A5 AD B5 BD -[BP]+disp16 110 86 8E 96 9E A6 AE B6 BE -[BX]+disp16 111 87 8F 97 9F A7 AF B7 BF - -EAX/AX/AL 000 C0 C8 D0 D8 E0 E8 F0 F8 -ECX/CX/CL 001 C1 C9 D1 D9 E1 E9 F1 F9 -EDX/DX/DL 010 C2 CA D2 DA E2 EA F2 FA -EBX/BX/BL 011 C3 CB D3 DB E3 EB F3 FB -ESP/SP/AH 11 100 C4 CC D4 DC E4 EC F4 FC -EBP/BP/CH 101 C5 CD D5 DD E5 ED F5 FD -ESI/SI/DH 110 C6 CE D6 DE E6 EE F6 FE -EDI/DI/BH 111 C7 CF D7 DF E7 EF F7 FF - -mod = 11 - register - 10 - address + 16 bit displacement - 01 - address + 8 bit displacement - 00 - address - -reg = If mod=11, (depending on data size, 16 bits/8 bits, 32 bits=extend 16 bit registers) - 0=AX/AL 1=CX/CL 2=DX/DL 3=BX/BL - 4=SP/AH 5=BP/CH 6=SI/DH 7=DI/BH - - Otherwise, LSB selects SI/DI (0=SI), NMSB selects BX/BP (0=BX), and MSB - selects whether BX/BP are used at all (0=used). - - mod=00 is an exception though - 6=16 bit displacement only - 7=[BX] - - Usage varies with instructions. - - MOV AL,BL has ModR/M as C3, for example. - mod=11, reg=0, r/m=3 - MOV uses reg as dest, and r/m as src. - reg 0 is AL, reg 3 is BL - - If BP or SP are in address calc, seg is SS, else DS -*/ - -uint32_t easeg; -int rmdat; - -uint16_t zero=0; -uint16_t *mod1add[2][8]; -uint32_t *mod1seg[8]; - -int slowrm[8]; - -void makemod1table() -{ - mod1add[0][0]=&BX; mod1add[0][1]=&BX; mod1add[0][2]=&BP; mod1add[0][3]=&BP; - mod1add[0][4]=&SI; mod1add[0][5]=&DI; mod1add[0][6]=&BP; mod1add[0][7]=&BX; - mod1add[1][0]=&SI; mod1add[1][1]=&DI; mod1add[1][2]=&SI; mod1add[1][3]=&DI; - mod1add[1][4]=&zero; mod1add[1][5]=&zero; mod1add[1][6]=&zero; mod1add[1][7]=&zero; - slowrm[0]=0; slowrm[1]=1; slowrm[2]=1; slowrm[3]=0; - mod1seg[0]=&ds; mod1seg[1]=&ds; mod1seg[2]=&ss; mod1seg[3]=&ss; - mod1seg[4]=&ds; mod1seg[5]=&ds; mod1seg[6]=&ss; mod1seg[7]=&ds; -} - -static void fetcheal() -{ - if (!cpu_mod && cpu_rm==6) { cpu_state.eaaddr=getword(); easeg=ds; FETCHADD(6); } - else - { - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr=0; - if (cpu_rm&4) FETCHADD(5); - else FETCHADD(7+slowrm[cpu_rm]); - break; - case 1: - cpu_state.eaaddr=(uint16_t)(int8_t)FETCH(); - if (cpu_rm&4) FETCHADD(9); - else FETCHADD(11+slowrm[cpu_rm]); - break; - case 2: - cpu_state.eaaddr=getword(); - if (cpu_rm&4) FETCHADD(9); - else FETCHADD(11+slowrm[cpu_rm]); - break; - } - cpu_state.eaaddr+=(*mod1add[0][cpu_rm])+(*mod1add[1][cpu_rm]); - easeg=*mod1seg[cpu_rm]; - cpu_state.eaaddr&=0xFFFF; - } - - cpu_state.last_ea = cpu_state.eaaddr; -} - -static __inline uint8_t geteab() -{ - if (cpu_mod == 3) - return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l; - return readmemb(easeg+cpu_state.eaaddr); -} - -static __inline uint16_t geteaw() -{ - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].w; - return readmemw(easeg,cpu_state.eaaddr); -} - -#if 0 -static __inline uint16_t geteaw2() -{ - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].w; - return readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); -} -#endif - -static __inline void seteab(uint8_t val) -{ - if (cpu_mod == 3) - { - if (cpu_rm & 4) - cpu_state.regs[cpu_rm & 3].b.h = val; - else - cpu_state.regs[cpu_rm & 3].b.l = val; - } - else - { - writememb(easeg+cpu_state.eaaddr,val); - } -} - -static __inline void seteaw(uint16_t val) -{ - if (cpu_mod == 3) - cpu_state.regs[cpu_rm].w = val; - else - { - writememw(easeg,cpu_state.eaaddr,val); - } -} - -#undef getr8 -#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l) - -#undef setr8 -#define setr8(r,v) if (r & 4) cpu_state.regs[r & 3].b.h = v; \ - else cpu_state.regs[r & 3].b.l = v; - - -/*Flags*/ -uint8_t znptable8[256]; -uint16_t znptable16[65536]; - -void makeznptable() -{ - int c,d; - for (c=0;c<256;c++) - { - d=0; - if (c&1) d++; - if (c&2) d++; - if (c&4) d++; - if (c&8) d++; - if (c&16) d++; - if (c&32) d++; - if (c&64) d++; - if (c&128) d++; - if (d&1) - { - znptable8[c]=0; - } - else - { - znptable8[c]=P_FLAG; - } - if (c == 0xb1) x808x_log("znp8 b1 = %i %02X\n", d, znptable8[c]); - if (!c) znptable8[c]|=Z_FLAG; - if (c&0x80) znptable8[c]|=N_FLAG; - } - for (c=0;c<65536;c++) - { - d=0; - if (c&1) d++; - if (c&2) d++; - if (c&4) d++; - if (c&8) d++; - if (c&16) d++; - if (c&32) d++; - if (c&64) d++; - if (c&128) d++; - if (d&1) - znptable16[c]=0; - else - znptable16[c]=P_FLAG; - if (c == 0xb1) x808x_log("znp16 b1 = %i %02X\n", d, znptable16[c]); - if (c == 0x65b1) x808x_log("znp16 65b1 = %i %02X\n", d, znptable16[c]); - if (!c) znptable16[c]|=Z_FLAG; - if (c&0x8000) znptable16[c]|=N_FLAG; - } -} -#if 1 -/* Also in mem.c */ -int timetolive=0; -#endif - -extern uint32_t oldcs2; -extern uint32_t oldpc2; - -int indump = 0; - -void dumpregs(int force) -{ - int c,d=0,e=0; -#ifndef RELEASE_BUILD - FILE *f; -#endif - - /* Only dump when needed, and only once.. */ - if (indump || (!force && !dump_on_exit)) return; - -#ifndef RELEASE_BUILD - indump = 1; - output=0; - (void)plat_chdir(usr_path); - nopageerrors=1; - f=fopen("ram.dmp","wb"); - fwrite(ram,mem_size*1024,1,f); - fclose(f); - x808x_log("Dumping rram.dmp\n"); - f=fopen("rram.dmp","wb"); - for (c=0;c<0x1000000;c++) putc(readmemb(c),f); - fclose(f); - x808x_log("Dumping rram4.dmp\n"); - f=fopen("rram4.dmp","wb"); - for (c=0;c<0x0050000;c++) - { - cpu_state.abrt = 0; - putc(readmemb386l(0,c+0x80000000),f); - } - fclose(f); - x808x_log("Dumping done\n"); -#endif - if (is386) - x808x_log("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP); - else - x808x_log("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); - x808x_log("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags); - x808x_log("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); - x808x_log("%i ins\n",ins); - if (is386) - x808x_log("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); - else - x808x_log("In %s mode\n",(msw&1)?"protected":"real"); - x808x_log("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high); - x808x_log("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high); - x808x_log("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); - if (is386) - { - x808x_log("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); - x808x_log("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); - } - x808x_log("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); - x808x_log("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit); - x808x_log("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit); - x808x_log("IDT : base=%06X limit=%04X\n",idt.base,idt.limit); - x808x_log("TR : base=%06X limit=%04X\n", tr.base, tr.limit); - if (is386) - { - x808x_log("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit"); - x808x_log("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4); - } - x808x_log("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum); - for (c=0;c<1024*1024;c++) - { - if (readlookup2[c]!=0xFFFFFFFF) d++; - if (writelookup2[c]!=0xFFFFFFFF) e++; - } - x808x_log("Entries in readlookup : %i writelookup : %i\n",d,e); - x87_dumpregs(); - indump = 0; -} - -int resets = 0; -int x86_was_reset = 0; -void resetx86() -{ - x808x_log("x86 reset\n"); - resets++; - ins = 0; - use32=0; - cpu_cur_status = 0; - stack32=0; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - msw=0; - if (is486) - cr0 = 1 << 30; - else - cr0 = 0; - cpu_cache_int_enabled = 0; - cpu_update_waitstates(); - cr4 = 0; - eflags=0; - cgate32=0; - if(AT) - { - loadcs(0xF000); - cpu_state.pc=0xFFF0; - rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; - } - else - { - loadcs(0xFFFF); - cpu_state.pc=0; - rammask = 0xfffff; - } - idt.base = 0; - idt.limit = is386 ? 0x03FF : 0xFFFF; - flags=2; - makeznptable(); - resetreadlookup(); - makemod1table(); - resetmcr(); - FETCHCLEAR(); - x87_reset(); - cpu_set_edx(); - EAX = 0; - ESP=0; - mmu_perm=4; - memset(inscounts, 0, sizeof(inscounts)); - x86seg_reset(); -#ifdef USE_DYNAREC - codegen_reset(); -#endif - x86_was_reset = 1; - port_92_clear_reset(); -} - -void softresetx86() -{ - use32=0; - stack32=0; - cpu_cur_status = 0; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - msw=0; - if (is486) - cr0 = 1 << 30; - else - cr0 = 0; - cpu_cache_int_enabled = 0; - cpu_update_waitstates(); - cr4 = 0; - eflags=0; - cgate32=0; - if(AT) - { - loadcs(0xF000); - cpu_state.pc=0xFFF0; - rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; - } - else - { - loadcs(0xFFFF); - cpu_state.pc=0; - rammask = 0xfffff; - } - flags=2; - idt.base = 0; - idt.limit = is386 ? 0x03FF : 0xFFFF; - x86seg_reset(); - x86_was_reset = 1; - port_92_clear_reset(); -} - -static void setznp8(uint8_t val) -{ - flags&=~0xC4; - flags|=znptable8[val]; -} - -static void setznp16(uint16_t val) -{ - flags&=~0xC4; - flags|=znptable16[val]; -} - -static void setadd8(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a+(uint16_t)b; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadd8nc(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a+(uint16_t)b; - flags&=~0x8D4; - flags|=znptable8[c&0xFF]; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadc8(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a+(uint16_t)b+tempc; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadd16(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadd16nc(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b; - flags&=~0x8D4; - flags|=znptable16[c&0xFFFF]; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadc16(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} - -static void setsub8(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a-(uint16_t)b; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsub8nc(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a-(uint16_t)b; - flags&=~0x8D4; - flags|=znptable8[c&0xFF]; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsbc8(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc); - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsub16(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a-(uint32_t)b; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsub16nc(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a-(uint32_t)b; - flags&=~0x8D4; - flags|=(znptable16[c&0xFFFF]&~4); - flags|=(znptable8[c&0xFF]&4); - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsbc16(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); - flags&=~0x8D5; - flags|=(znptable16[c&0xFFFF]&~4); - flags|=(znptable8[c&0xFF]&4); - if (c&0x10000) flags|=C_FLAG; - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} - -int current_diff = 0; -void clockhardware() -{ - int diff = cycdiff - cycles - current_diff; - - current_diff += diff; - - timer_end_period(cycles*xt_cpu_multi); -} - -static int takeint = 0; - - -int firstrepcycle=1; - -void rep(int fv) -{ - uint8_t temp = 0; - int c=CX; - uint8_t temp2; - uint16_t tempw,tempw2; - uint16_t ipc=cpu_state.oldpc; - int changeds=0; - uint32_t oldds = 0; - startrep: - temp=FETCH(); - - switch (temp) - { - case 0x08: - cpu_state.pc=ipc+1; - cycles-=2; - FETCHCLEAR(); - break; - case 0x26: /*ES:*/ - oldds=ds; - ds=es; - changeds=1; - cycles-=2; - goto startrep; - break; - case 0x2E: /*CS:*/ - oldds=ds; - ds=cs; - changeds=1; - cycles-=2; - goto startrep; - break; - case 0x36: /*SS:*/ - oldds=ds; - ds=ss; - changeds=1; - cycles-=2; - goto startrep; - break; - case 0x6E: /*REP OUTSB*/ - if (c>0) - { - temp2=readmemb(ds+SI); - outb(DX,temp2); - if (flags&D_FLAG) SI--; - else SI++; - c--; - cycles-=5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - case 0xA4: /*REP MOVSB*/ - while (c>0 && !IRQTEST) - { - temp2=readmemb(ds+SI); - writememb(es+DI,temp2); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - c--; - cycles-=17; - clockhardware(); - FETCHADD(17-memcycs); - } - if (IRQTEST && c>0) cpu_state.pc=ipc; - break; - case 0xA5: /*REP MOVSW*/ - while (c>0 && !IRQTEST) - { - memcycs=0; - tempw=readmemw(ds,SI); - writememw(es,DI,tempw); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - c--; - cycles-=17; - clockhardware(); - FETCHADD(17 - memcycs); - } - if (IRQTEST && c>0) cpu_state.pc=ipc; - break; - case 0xA6: /*REP CMPSB*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST) - { - memcycs=0; - temp=readmemb(ds+SI); - temp2=readmemb(es+DI); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - c--; - cycles -= 30; - setsub8(temp,temp2); - clockhardware(); - FETCHADD(30 - memcycs); - } - if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc; - break; - case 0xA7: /*REP CMPSW*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST) - { - memcycs=0; - tempw=readmemw(ds,SI); - tempw2=readmemw(es,DI); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - c--; - cycles -= 30; - setsub16(tempw,tempw2); - clockhardware(); - FETCHADD(30 - memcycs); - } - if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc; - break; - case 0xAA: /*REP STOSB*/ - while (c>0 && !IRQTEST) - { - memcycs=0; - writememb(es+DI,AL); - if (flags&D_FLAG) DI--; - else DI++; - c--; - cycles -= 10; - clockhardware(); - FETCHADD(10 - memcycs); - } - if (IRQTEST && c>0) cpu_state.pc=ipc; - break; - case 0xAB: /*REP STOSW*/ - while (c>0 && !IRQTEST) - { - memcycs=0; - writememw(es,DI,AX); - if (flags&D_FLAG) DI-=2; - else DI+=2; - c--; - cycles -= 10; - clockhardware(); - FETCHADD(10 - memcycs); - } - if (IRQTEST && c>0) cpu_state.pc=ipc; - break; - case 0xAC: /*REP LODSB*/ - if (c>0) - { - temp2=readmemb(ds+SI); - if (flags&D_FLAG) SI--; - else SI++; - c--; - cycles-=4; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - case 0xAD: /*REP LODSW*/ - if (c>0) - { - tempw2=readmemw(ds,SI); - if (flags&D_FLAG) SI-=2; - else SI+=2; - c--; - cycles-=4; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - case 0xAE: /*REP SCASB*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) - { - temp2=readmemb(es+DI); - setsub8(AL,temp2); - if (flags&D_FLAG) DI--; - else DI++; - c--; - cycles -= 15; - } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - case 0xAF: /*REP SCASW*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) - { - tempw=readmemw(es,DI); - setsub16(AX,tempw); - if (flags&D_FLAG) DI-=2; - else DI+=2; - c--; - cycles -= 15; - } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - default: - cpu_state.pc = ipc+1; - cycles-=20; - FETCHCLEAR(); - } - CX=c; - if (changeds) ds=oldds; - if (IRQTEST) - takeint = 1; -} - - -int inhlt=0; -uint16_t lastpc,lastcs; -int firstrepcycle; -int skipnextprint=0; - -int instime=0; -void execx86(int cycs) -{ - uint8_t temp = 0,temp2; - uint16_t addr,tempw,tempw2,tempw3,tempw4; - int8_t offset; - int tempws; - uint32_t templ; - unsigned int c; - int tempi; - int trap; - - cycles+=cycs; - while (cycles>0) - { - cycdiff=cycles; - timer_start_period(cycles*xt_cpu_multi); - current_diff = 0; - cycles-=nextcyc; - nextcyc=0; - fetchclocks=0; - oldcs=CS; - cpu_state.oldpc=cpu_state.pc; - opcodestart: - opcode=FETCH(); - tempc=flags&C_FLAG; - trap=flags&T_FLAG; - cpu_state.pc--; - if (output) - { - if (!skipnextprint) x808x_log("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]); - skipnextprint=0; - } - cpu_state.pc++; - inhlt=0; - switch (opcode) - { - case 0x00: /*ADD 8,reg*/ - fetchea(); - temp=geteab(); - setadd8(temp,getr8(cpu_reg)); - temp+=getr8(cpu_reg); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x01: /*ADD 16,reg*/ - fetchea(); - tempw=geteaw(); - setadd16(tempw, cpu_state.regs[cpu_reg].w); - tempw += cpu_state.regs[cpu_reg].w; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x02: /*ADD cpu_reg,8*/ - fetchea(); - temp=geteab(); - setadd8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)+temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x03: /*ADD cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setadd16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w+=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x04: /*ADD AL,#8*/ - temp=FETCH(); - setadd8(AL,temp); - AL+=temp; - cycles-=4; - break; - case 0x05: /*ADD AX,#16*/ - tempw=getword(); - setadd16(AX,tempw); - AX+=tempw; - cycles-=4; - break; - - case 0x06: /*PUSH ES*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),ES); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x07: /*POP ES*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_es); - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - - case 0x08: /*OR 8,reg*/ - fetchea(); - temp=geteab(); - temp|=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x09: /*OR 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw|=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x0A: /*OR cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp|=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x0B: /*OR reg,16*/ - fetchea(); - tempw=geteaw(); - tempw|=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x0C: /*OR AL,#8*/ - AL|=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x0D: /*OR AX,#16*/ - AX|=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - - case 0x0E: /*PUSH CS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),CS); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x0F: /*POP CS - 8088/8086 only*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_cs); - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - - case 0x10: /*ADC 8,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setadc8(temp,temp2); - temp+=temp2+tempc; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x11: /*ADC 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x12: /*ADC cpu_reg,8*/ - fetchea(); - temp=geteab(); - setadc8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)+temp+tempc); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x13: /*ADC cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setadc16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w+=tempw+tempc; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x14: /*ADC AL,#8*/ - tempw=FETCH(); - setadc8(AL,tempw & 0xff); - AL+=tempw+tempc; - cycles-=4; - break; - case 0x15: /*ADC AX,#16*/ - tempw=getword(); - setadc16(AX,tempw); - AX+=tempw+tempc; - cycles-=4; - break; - - case 0x16: /*PUSH SS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),SS); - SP-=2; - cycles-=14; - cpu_state.last_ea = SP; - break; - case 0x17: /*POP SS*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_ss); - SP+=2; - cpu_state.last_ea = SP; - noint=1; - cycles-=12; - break; - - case 0x18: /*SBB 8,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setsbc8(temp,temp2); - temp-=(temp2+tempc); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x19: /*SBB 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setsbc16(tempw,tempw2); - tempw-=(tempw2+tempc); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x1A: /*SBB cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsbc8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)-(temp+tempc)); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x1B: /*SBB cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setsbc16(tempw2,tempw); - tempw2-=(tempw+tempc); - cpu_state.regs[cpu_reg].w=tempw2; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x1C: /*SBB AL,#8*/ - temp=FETCH(); - setsbc8(AL,temp); - AL-=(temp+tempc); - cycles-=4; - break; - case 0x1D: /*SBB AX,#16*/ - tempw=getword(); - setsbc16(AX,tempw); - AX-=(tempw+tempc); - cycles-=4; - break; - - case 0x1E: /*PUSH DS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),DS); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x1F: /*POP DS*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - - case 0x20: /*AND 8,reg*/ - fetchea(); - temp=geteab(); - temp&=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x21: /*AND 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw&=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x22: /*AND cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp&=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x23: /*AND cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw&=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x24: /*AND AL,#8*/ - AL&=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x25: /*AND AX,#16*/ - AX&=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - - case 0x26: /*ES:*/ - oldss=ss; - oldds=ds; - ds=ss=es; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x27: /*DAA*/ - if ((flags&A_FLAG) || ((AL&0xF)>9)) - { - tempi=((uint16_t)AL)+6; - AL+=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; - } - if ((flags&C_FLAG) || (AL>0x9F)) - { - AL+=0x60; - flags|=C_FLAG; - } - setznp8(AL); - cycles-=4; - break; - - case 0x28: /*SUB 8,reg*/ - fetchea(); - temp=geteab(); - setsub8(temp,getr8(cpu_reg)); - temp-=getr8(cpu_reg); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x29: /*SUB 16,reg*/ - fetchea(); - tempw=geteaw(); - setsub16(tempw,cpu_state.regs[cpu_reg].w); - tempw-=cpu_state.regs[cpu_reg].w; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x2A: /*SUB cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsub8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)-temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x2B: /*SUB cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setsub16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w-=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x2C: /*SUB AL,#8*/ - temp=FETCH(); - setsub8(AL,temp); - AL-=temp; - cycles-=4; - break; - case 0x2D: /*SUB AX,#16*/ - tempw=getword(); - setsub16(AX,tempw); - AX-=tempw; - cycles-=4; - break; - case 0x2E: /*CS:*/ - oldss=ss; - oldds=ds; - ds=ss=cs; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - case 0x2F: /*DAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - tempi=((uint16_t)AL)-6; - AL-=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; - } - if ((flags&C_FLAG)||(AL>0x9F)) - { - AL-=0x60; - flags|=C_FLAG; - } - setznp8(AL); - cycles-=4; - break; - case 0x30: /*XOR 8,reg*/ - fetchea(); - temp=geteab(); - temp^=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x31: /*XOR 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw^=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x32: /*XOR cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp^=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x33: /*XOR cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw^=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x34: /*XOR AL,#8*/ - AL^=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x35: /*XOR AX,#16*/ - AX^=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - - case 0x36: /*SS:*/ - oldss=ss; - oldds=ds; - ds=ss=ss; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x37: /*AAA*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - AL+=6; - AH++; - flags|=(A_FLAG|C_FLAG); - } - else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=8; - break; - - case 0x38: /*CMP 8,reg*/ - fetchea(); - temp=geteab(); - setsub8(temp,getr8(cpu_reg)); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x39: /*CMP 16,reg*/ - fetchea(); - tempw=geteaw(); - setsub16(tempw,cpu_state.regs[cpu_reg].w); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3A: /*CMP cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsub8(getr8(cpu_reg),temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3B: /*CMP cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setsub16(cpu_state.regs[cpu_reg].w,tempw); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3C: /*CMP AL,#8*/ - temp=FETCH(); - setsub8(AL,temp); - cycles-=4; - break; - case 0x3D: /*CMP AX,#16*/ - tempw=getword(); - setsub16(AX,tempw); - cycles-=4; - break; - - case 0x3E: /*DS:*/ - oldss=ss; - oldds=ds; - ds=ss=ds; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x3F: /*AAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - AL-=6; - AH--; - flags|=(A_FLAG|C_FLAG); - } - else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=8; - break; - - case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/ - case 0x44: case 0x45: case 0x46: case 0x47: - setadd16nc(cpu_state.regs[opcode&7].w,1); - cpu_state.regs[opcode&7].w++; - cycles-=3; - break; - case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/ - case 0x4C: case 0x4D: case 0x4E: case 0x4F: - setsub16nc(cpu_state.regs[opcode&7].w,1); - cpu_state.regs[opcode&7].w--; - cycles-=3; - break; - - case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ - case 0x54: case 0x55: case 0x56: case 0x57: - if (cpu_state.ssegs) ss=oldss; - SP-=2; - cpu_state.last_ea = SP; - writememw(ss,SP,cpu_state.regs[opcode&7].w); - cycles-=15; - break; - case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ - case 0x5C: case 0x5D: case 0x5E: case 0x5F: - if (cpu_state.ssegs) ss=oldss; - SP+=2; - cpu_state.last_ea = SP; - cpu_state.regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF); - cycles-=12; - break; - - - case 0x60: /*JO alias*/ - case 0x70: /*JO*/ - offset=(int8_t)FETCH(); - if (flags&V_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x61: /*JNO alias*/ - case 0x71: /*JNO*/ - offset=(int8_t)FETCH(); - if (!(flags&V_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x62: /*JB alias*/ - case 0x72: /*JB*/ - offset=(int8_t)FETCH(); - if (flags&C_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x63: /*JNB alias*/ - case 0x73: /*JNB*/ - offset=(int8_t)FETCH(); - if (!(flags&C_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x64: /*JE alias*/ - case 0x74: /*JE*/ - offset=(int8_t)FETCH(); - if (flags&Z_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x65: /*JNE alias*/ - case 0x75: /*JNE*/ - offset=(int8_t)FETCH(); - cycles-=4; - if (!(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - break; - case 0x66: /*JBE alias*/ - case 0x76: /*JBE*/ - offset=(int8_t)FETCH(); - if (flags&(C_FLAG|Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x67: /*JNBE alias*/ - case 0x77: /*JNBE*/ - offset=(int8_t)FETCH(); - if (!(flags&(C_FLAG|Z_FLAG))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x68: /*JS alias*/ - case 0x78: /*JS*/ - offset=(int8_t)FETCH(); - if (flags&N_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x69: /*JNS alias*/ - case 0x79: /*JNS*/ - offset=(int8_t)FETCH(); - if (!(flags&N_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6A: /*JP alias*/ - case 0x7A: /*JP*/ - offset=(int8_t)FETCH(); - if (flags&P_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6B: /*JNP alias*/ - case 0x7B: /*JNP*/ - offset=(int8_t)FETCH(); - if (!(flags&P_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6C: /*JL alias*/ - case 0x7C: /*JL*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp!=temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6D: /*JNL alias*/ - case 0x7D: /*JNL*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp==temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6E: /*JLE alias*/ - case 0x7E: /*JLE*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if ((flags&Z_FLAG) || (temp!=temp2)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6F: /*JNLE alias*/ - case 0x7F: /*JNLE*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (!((flags&Z_FLAG) || (temp!=temp2))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - - case 0x80: case 0x82: - fetchea(); - temp=geteab(); - temp2=FETCH(); - switch (rmdat&0x38) - { - case 0x00: /*ADD b,#8*/ - setadd8(temp,temp2); - seteab(temp+temp2); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR b,#8*/ - temp|=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC b,#8*/ - setadc8(temp,temp2); - seteab(temp+temp2+tempc); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB b,#8*/ - setsbc8(temp,temp2); - seteab(temp-(temp2+tempc)); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND b,#8*/ - temp&=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x28: /*SUB b,#8*/ - setsub8(temp,temp2); - seteab(temp-temp2); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR b,#8*/ - temp^=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x38: /*CMP b,#8*/ - setsub8(temp,temp2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x81: - fetchea(); - tempw=geteaw(); - tempw2=getword(); - switch (rmdat&0x38) - { - case 0x00: /*ADD w,#16*/ - setadd16(tempw,tempw2); - tempw+=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR w,#16*/ - tempw|=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC w,#16*/ - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND w,#16*/ - tempw&=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB w,#16*/ - setsbc16(tempw,tempw2); - seteaw(tempw-(tempw2+tempc)); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x28: /*SUB w,#16*/ - setsub16(tempw,tempw2); - tempw-=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR w,#16*/ - tempw^=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x38: /*CMP w,#16*/ - setsub16(tempw,tempw2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x83: - fetchea(); - tempw=geteaw(); - tempw2=FETCH(); - if (tempw2&0x80) tempw2|=0xFF00; - switch (rmdat&0x38) - { - case 0x00: /*ADD w,#8*/ - setadd16(tempw,tempw2); - tempw+=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR w,#8*/ - tempw|=tempw2; - setznp16(tempw); - seteaw(tempw); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC w,#8*/ - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB w,#8*/ - setsbc16(tempw,tempw2); - tempw-=(tempw2+tempc); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND w,#8*/ - tempw&=tempw2; - setznp16(tempw); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - break; - case 0x28: /*SUB w,#8*/ - setsub16(tempw,tempw2); - tempw-=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR w,#8*/ - tempw^=tempw2; - setznp16(tempw); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - break; - case 0x38: /*CMP w,#8*/ - setsub16(tempw,tempw2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x84: /*TEST b,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setznp8(temp&temp2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x85: /*TEST w,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setznp16(tempw&tempw2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x86: /*XCHG b,reg*/ - fetchea(); - temp=geteab(); - seteab(getr8(cpu_reg)); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?4:25); - break; - case 0x87: /*XCHG w,reg*/ - fetchea(); - tempw=geteaw(); - seteaw(cpu_state.regs[cpu_reg].w); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?4:25); - break; - - case 0x88: /*MOV b,reg*/ - fetchea(); - seteab(getr8(cpu_reg)); - cycles-=((cpu_mod==3)?2:13); - break; - case 0x89: /*MOV w,reg*/ - fetchea(); - seteaw(cpu_state.regs[cpu_reg].w); - cycles-=((cpu_mod==3)?2:13); - break; - case 0x8A: /*MOV cpu_reg,b*/ - fetchea(); - temp=geteab(); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?2:12); - break; - case 0x8B: /*MOV cpu_reg,w*/ - fetchea(); - tempw=geteaw(); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?2:12); - break; - - case 0x8C: /*MOV w,sreg*/ - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - seteaw(ES); - break; - case 0x08: /*CS*/ - seteaw(CS); - break; - case 0x18: /*DS*/ - if (cpu_state.ssegs) ds=oldds; - seteaw(DS); - break; - case 0x10: /*SS*/ - if (cpu_state.ssegs) ss=oldss; - seteaw(SS); - break; - } - cycles-=((cpu_mod==3)?2:13); - break; - - case 0x8D: /*LEA*/ - fetchea(); - cpu_state.regs[cpu_reg].w=(cpu_mod == 3)?cpu_state.last_ea:cpu_state.eaaddr; - cycles-=2; - break; - - case 0x8E: /*MOV sreg,w*/ - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - tempw=geteaw(); - loadseg(tempw,&_es); - break; - case 0x08: /*CS - 8088/8086 only*/ - tempw=geteaw(); - loadseg(tempw,&_cs); - break; - case 0x18: /*DS*/ - tempw=geteaw(); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - break; - case 0x10: /*SS*/ - tempw=geteaw(); - loadseg(tempw,&_ss); - if (cpu_state.ssegs) oldss=ss; - break; - } - cycles-=((cpu_mod==3)?2:12); - skipnextprint=1; - noint=1; - break; - - case 0x8F: /*POPW*/ - fetchea(); - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - SP+=2; - cpu_state.last_ea = SP; - seteaw(tempw); - cycles-=25; - break; - - case 0x90: /*NOP*/ - cycles-=3; - break; - - case 0x91: case 0x92: case 0x93: /*XCHG AX*/ - case 0x94: case 0x95: case 0x96: case 0x97: - tempw=AX; - AX=cpu_state.regs[opcode&7].w; - cpu_state.regs[opcode&7].w=tempw; - cycles-=3; - break; - - case 0x98: /*CBW*/ - AH=(AL&0x80)?0xFF:0; - cycles-=2; - break; - case 0x99: /*CWD*/ - DX=(AX&0x8000)?0xFFFF:0; - cycles-=5; - break; - case 0x9A: /*CALL FAR*/ - tempw=getword(); - tempw2=getword(); - tempw3=CS; - tempw4=cpu_state.pc; - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=tempw; - loadcs(tempw2); - writememw(ss,(SP-2)&0xFFFF,tempw3); - writememw(ss,(SP-4)&0xFFFF,tempw4); - SP-=4; - cpu_state.last_ea = SP; - cycles-=36; - FETCHCLEAR(); - break; - case 0x9B: /*WAIT*/ - cycles-=4; - break; - case 0x9C: /*PUSHF*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x9D: /*POPF*/ - if (cpu_state.ssegs) ss=oldss; - flags=readmemw(ss,SP)&0xFFF; - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - case 0x9E: /*SAHF*/ - flags=(flags&0xFF00)|AH; - cycles-=4; - break; - case 0x9F: /*LAHF*/ - AH=flags&0xFF; - cycles-=4; - break; - - case 0xA0: /*MOV AL,(w)*/ - addr=getword(); - AL=readmemb(ds+addr); - cycles-=14; - break; - case 0xA1: /*MOV AX,(w)*/ - addr=getword(); - AX=readmemw(ds,addr); - cycles-=14; - break; - case 0xA2: /*MOV (w),AL*/ - addr=getword(); - writememb(ds+addr,AL); - cycles-=14; - break; - case 0xA3: /*MOV (w),AX*/ - addr=getword(); - writememw(ds,addr,AX); - cycles-=14; - break; - - case 0xA4: /*MOVSB*/ - temp=readmemb(ds+SI); - writememb(es+DI,temp); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - cycles-=18; - break; - case 0xA5: /*MOVSW*/ - tempw=readmemw(ds,SI); - writememw(es,DI,tempw); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - cycles-=18; - break; - case 0xA6: /*CMPSB*/ - temp =readmemb(ds+SI); - temp2=readmemb(es+DI); - setsub8(temp,temp2); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - cycles-=30; - break; - case 0xA7: /*CMPSW*/ - tempw =readmemw(ds,SI); - tempw2=readmemw(es,DI); - setsub16(tempw,tempw2); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - cycles-=30; - break; - case 0xA8: /*TEST AL,#8*/ - temp=FETCH(); - setznp8(AL&temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=5; - break; - case 0xA9: /*TEST AX,#16*/ - tempw=getword(); - setznp16(AX&tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=5; - break; - case 0xAA: /*STOSB*/ - writememb(es+DI,AL); - if (flags&D_FLAG) DI--; - else DI++; - cycles-=11; - break; - case 0xAB: /*STOSW*/ - writememw(es,DI,AX); - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=11; - break; - case 0xAC: /*LODSB*/ - AL=readmemb(ds+SI); - if (flags&D_FLAG) SI--; - else SI++; - cycles-=16; - break; - case 0xAD: /*LODSW*/ - AX=readmemw(ds,SI); - if (flags&D_FLAG) SI-=2; - else SI+=2; - cycles-=16; - break; - case 0xAE: /*SCASB*/ - temp=readmemb(es+DI); - setsub8(AL,temp); - if (flags&D_FLAG) DI--; - else DI++; - cycles-=19; - break; - case 0xAF: /*SCASW*/ - tempw=readmemw(es,DI); - setsub16(AX,tempw); - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=19; - break; - - case 0xB0: /*MOV AL,#8*/ - AL=FETCH(); - cycles-=4; - break; - case 0xB1: /*MOV CL,#8*/ - CL=FETCH(); - cycles-=4; - break; - case 0xB2: /*MOV DL,#8*/ - DL=FETCH(); - cycles-=4; - break; - case 0xB3: /*MOV BL,#8*/ - BL=FETCH(); - cycles-=4; - break; - case 0xB4: /*MOV AH,#8*/ - AH=FETCH(); - cycles-=4; - break; - case 0xB5: /*MOV CH,#8*/ - CH=FETCH(); - cycles-=4; - break; - case 0xB6: /*MOV DH,#8*/ - DH=FETCH(); - cycles-=4; - break; - case 0xB7: /*MOV BH,#8*/ - BH=FETCH(); - cycles-=4; - break; - case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ - case 0xBC: case 0xBD: case 0xBE: case 0xBF: - cpu_state.regs[opcode&7].w=getword(); - cycles-=4; - break; - - case 0xC0: /*RET alias*/ - case 0xC2: /*RET*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - SP+=2+tempw; - cycles-=24; - FETCHCLEAR(); - break; - case 0xC1: /*RET alias*/ - case 0xC3: /*RET*/ - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - SP+=2; - cycles-=20; - FETCHCLEAR(); - break; - case 0xC4: /*LES*/ - fetchea(); - cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); - tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - loadseg(tempw,&_es); - cycles-=24; - break; - case 0xC5: /*LDS*/ - fetchea(); - cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); - tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - cycles-=24; - break; - case 0xC6: /*MOV b,#8*/ - fetchea(); - temp=FETCH(); - seteab(temp); - cycles-=((cpu_mod==3)?4:14); - break; - case 0xC7: /*MOV w,#16*/ - fetchea(); - tempw=getword(); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:14); - break; - - case 0xC8: /*RETF alias*/ - case 0xCA: /*RETF*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,SP+2)); - SP+=4; - SP+=tempw; - cycles-=33; - FETCHCLEAR(); - break; - case 0xC9: /*RETF alias*/ - case 0xCB: /*RETF*/ - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,SP+2)); - SP+=4; - cycles-=34; - FETCHCLEAR(); - break; - case 0xCC: /*INT 3*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - SP-=6; - addr=3<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - cycles-=72; - break; - case 0xCD: /*INT*/ - lastpc=cpu_state.pc; - lastcs=CS; - temp=FETCH(); - - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - flags&=~T_FLAG; - SP-=6; - addr=temp<<2; - cpu_state.pc=readmemw(0,addr); - - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - - cycles-=71; - break; - case 0xCF: /*IRET*/ - if (cpu_state.ssegs) ss=oldss; - tempw=CS; - tempw2=cpu_state.pc; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,((SP+2)&0xFFFF))); - flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF; - SP+=6; - cycles-=44; - FETCHCLEAR(); - nmi_enable = 1; - break; - case 0xD0: - fetchea(); - temp=geteab(); - switch (rmdat&0x38) - { - case 0x00: /*ROL b,1*/ - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=1; - if (flags&C_FLAG) temp|=1; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x08: /*ROR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (flags&C_FLAG) temp|=0x80; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x10: /*RCL b,1*/ - temp2=flags&C_FLAG; - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=1; - if (temp2) temp|=1; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x18: /*RCR b,1*/ - temp2=flags&C_FLAG; - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (temp2) temp|=0x80; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x20: case 0x30: /*SHL b,1*/ - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - if ((temp^(temp<<1))&0x80) flags|=V_FLAG; - else flags&=~V_FLAG; - temp<<=1; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x28: /*SHR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - if (temp&0x80) flags|=V_FLAG; - else flags&=~V_FLAG; - temp>>=1; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x38: /*SAR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (temp&0x40) temp|=0x80; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - flags&=~V_FLAG; - break; - } - break; - - case 0xD1: - fetchea(); - tempw=geteaw(); - switch (rmdat&0x38) - { - case 0x00: /*ROL w,1*/ - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=1; - if (flags&C_FLAG) tempw|=1; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x08: /*ROR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (flags&C_FLAG) tempw|=0x8000; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x10: /*RCL w,1*/ - temp2=flags&C_FLAG; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=1; - if (temp2) tempw|=1; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x18: /*RCR w,1*/ - temp2=flags&C_FLAG; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (temp2) tempw|=0x8000; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x20: case 0x30: /*SHL w,1*/ - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG; - else flags&=~V_FLAG; - tempw<<=1; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x28: /*SHR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - if (tempw&0x8000) flags|=V_FLAG; - else flags&=~V_FLAG; - tempw>>=1; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - - case 0x38: /*SAR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (tempw&0x4000) tempw|=0x8000; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - flags&=~V_FLAG; - break; - } - break; - - case 0xD2: - fetchea(); - temp=geteab(); - c=CL; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL b,CL*/ - temp2=(temp&0x80)?1:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - temp2=(temp&0x80)?1:0; - temp=(temp<<1)|temp2; - c--; - cycles-=4; - } - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x08: /*ROR b,CL*/ - temp2=temp&1; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - temp2=temp&1; - temp>>=1; - if (temp2) temp|=0x80; - c--; - cycles-=4; - } - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x10: /*RCL b,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - temp2=temp&0x80; - temp<<=1; - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - if (templ) temp|=1; - c--; - cycles-=4; - } - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x18: /*RCR b,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - temp2=temp&1; - temp>>=1; - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - if (templ) temp|=0x80; - c--; - cycles-=4; - } - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x20: case 0x30: /*SHL b,CL*/ - if (c > 8) - { - temp = 0; - flags &= ~C_FLAG; - } - else - { - if ((temp<<(c-1))&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=c; - } - seteab(temp); - setznp8(temp); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - case 0x28: /*SHR b,CL*/ - if (c > 8) - { - temp = 0; - flags &= ~C_FLAG; - } - else - { - if ((temp>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=c; - } - seteab(temp); - setznp8(temp); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - case 0x38: /*SAR b,CL*/ - if ((temp>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - while (c>0) - { - temp>>=1; - if (temp&0x40) temp|=0x80; - c--; - cycles-=4; - } - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - } - break; - - case 0xD3: - fetchea(); - tempw=geteaw(); - c=CL; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL w,CL*/ - while (c>0) - { - temp=(tempw&0x8000)?1:0; - tempw=(tempw<<1)|temp; - c--; - cycles-=4; - } - if (temp) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x08: /*ROR w,CL*/ - tempw2=(tempw&1)?0x8000:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - tempw2=(tempw&1)?0x8000:0; - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - if (tempw2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x10: /*RCL w,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw=(tempw<<1)|templ; - c--; - cycles-=4; - } - if (temp) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x18: /*RCR w,CL*/ - templ=flags&C_FLAG; - tempw2=(templ&1)?0x8000:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - templ=flags&C_FLAG; - tempw2=(templ&1)?0x8000:0; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - if (tempw2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - - case 0x20: case 0x30: /*SHL w,CL*/ - if (c>16) - { - tempw=0; - flags&=~C_FLAG; - } - else - { - if ((tempw<<(c-1))&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=c; - } - seteaw(tempw); - setznp16(tempw); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - - case 0x28: /*SHR w,CL*/ - if (c > 16) - { - tempw = 0; - flags &= ~C_FLAG; - } - else - { - if ((tempw>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=c; - } - seteaw(tempw); - setznp16(tempw); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - - case 0x38: /*SAR w,CL*/ - tempw2=tempw&0x8000; - if ((tempw>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - while (c>0) - { - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - } - break; - - case 0xD4: /*AAM*/ - tempws=FETCH(); - AH=AL/tempws; - AL%=tempws; - setznp16(AX); - cycles-=83; - break; - case 0xD5: /*AAD*/ - tempws=FETCH(); - AL=(AH*tempws)+AL; - AH=0; - setznp16(AX); - cycles-=60; - break; - case 0xD6: /*SETALC*/ - AL = (flags & C_FLAG) ? 0xff : 0; - cycles -= 4; - break; - case 0xD7: /*XLAT*/ - addr=BX+AL; - cpu_state.last_ea = addr; - AL=readmemb(ds+addr); - cycles-=11; - break; - case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/ - case 0xDC: case 0xDE: case 0xDF: case 0xD8: - fetchea(); - geteab(); - break; - - case 0xE0: /*LOOPNE*/ - offset=(int8_t)FETCH(); - CX--; - if (CX && !(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; - case 0xE1: /*LOOPE*/ - offset=(int8_t)FETCH(); - CX--; - if (CX && (flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; - case 0xE2: /*LOOP*/ - offset=(int8_t)FETCH(); - CX--; - if (CX) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=5; - break; - case 0xE3: /*JCXZ*/ - offset=(int8_t)FETCH(); - if (!CX) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; - - case 0xE4: /*IN AL*/ - temp=FETCH(); - AL=inb(temp); - cycles-=14; - break; - case 0xE5: /*IN AX*/ - temp=FETCH(); - AL=inb(temp); - AH=inb(temp+1); - cycles-=14; - break; - case 0xE6: /*OUT AL*/ - temp=FETCH(); - outb(temp,AL); - cycles-=14; - break; - case 0xE7: /*OUT AX*/ - temp=FETCH(); - outb(temp,AL); - outb(temp+1,AH); - cycles-=14; - break; - - case 0xE8: /*CALL rel 16*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),cpu_state.pc); - SP-=2; - cpu_state.last_ea = SP; - cpu_state.pc+=tempw; - cycles-=23; - FETCHCLEAR(); - break; - case 0xE9: /*JMP rel 16*/ - tempw = getword(); - cpu_state.pc += tempw; - cycles-=15; - FETCHCLEAR(); - break; - case 0xEA: /*JMP far*/ - addr=getword(); - tempw=getword(); - cpu_state.pc=addr; - loadcs(tempw); - cycles-=15; - FETCHCLEAR(); - break; - case 0xEB: /*JMP rel*/ - offset=(int8_t)FETCH(); - cpu_state.pc+=offset; - cycles-=15; - FETCHCLEAR(); - break; - case 0xEC: /*IN AL,DX*/ - AL=inb(DX); - cycles-=12; - break; - case 0xED: /*IN AX,DX*/ - AL=inb(DX); - AH=inb(DX+1); - cycles-=12; - break; - case 0xEE: /*OUT DX,AL*/ - outb(DX,AL); - cycles-=12; - break; - case 0xEF: /*OUT DX,AX*/ - outb(DX,AL); - outb(DX+1,AH); - cycles-=12; - break; - - case 0xF0: /*LOCK*/ - case 0xF1: /*LOCK alias*/ - cycles-=4; - break; - - case 0xF2: /*REPNE*/ - rep(0); - break; - case 0xF3: /*REPE*/ - rep(1); - break; - - case 0xF4: /*HLT*/ - inhlt=1; - cpu_state.pc--; - FETCHCLEAR(); - cycles-=2; - break; - case 0xF5: /*CMC*/ - flags^=C_FLAG; - cycles-=2; - break; - - case 0xF6: - fetchea(); - temp=geteab(); - switch (rmdat&0x38) - { - case 0x00: /*TEST b,#8*/ - case 0x08: - temp2=FETCH(); - temp&=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?5:11); - break; - case 0x10: /*NOT b*/ - temp=~temp; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x18: /*NEG b*/ - setsub8(0,temp); - temp=0-temp; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x20: /*MUL AL,b*/ - setznp8(AL); - AX=AL*temp; - if (AX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=70; - break; - case 0x28: /*IMUL AL,b*/ - setznp8(AL); - tempws=(int)((int8_t)AL)*(int)((int8_t)temp); - AX=tempws&0xFFFF; - if (AX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=80; - break; - case 0x30: /*DIV AL,b*/ - tempw=AX; - if (temp) - { - tempw2=tempw%temp; - AH=tempw2 & 0xff; - tempw/=temp; - AL=tempw&0xFF; - } - else - { - x808x_log("DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=80; - break; - case 0x38: /*IDIV AL,b*/ - tempws=(int)AX; - if (temp) - { - tempw2=tempws%(int)((int8_t)temp); - AH=tempw2&0xFF; - tempws/=(int)((int8_t)temp); - AL=tempws&0xFF; - } - else - { - x808x_log("IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=101; - break; - } - break; - - case 0xF7: - fetchea(); - tempw=geteaw(); - switch (rmdat&0x38) - { - case 0x00: /*TEST w*/ - case 0x08: - tempw2=getword(); - setznp16(tempw&tempw2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?5:11); - break; - case 0x10: /*NOT w*/ - seteaw(~tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x18: /*NEG w*/ - setsub16(0,tempw); - tempw=0-tempw; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x20: /*MUL AX,w*/ - setznp16(AX); - templ=AX*tempw; - AX=templ&0xFFFF; - DX=templ>>16; - if (AX|DX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (DX) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=118; - break; - case 0x28: /*IMUL AX,w*/ - setznp16(AX); - tempws=(int)((int16_t)AX)*(int)((int16_t)tempw); - if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - AX=tempws&0xFFFF; - tempws=(uint16_t)(tempws>>16); - DX=tempws&0xFFFF; - if (AX|DX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - cycles-=128; - break; - case 0x30: /*DIV AX,w*/ - templ=(DX<<16)|AX; - if (tempw) - { - tempw2=templ%tempw; - DX=tempw2; - templ/=tempw; - AX=templ&0xFFFF; - } - else - { - x808x_log("DIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=144; - break; - case 0x38: /*IDIV AX,w*/ - tempws=(int)((DX<<16)|AX); - if (tempw) - { - tempw2=tempws%(int)((int16_t)tempw); - DX=tempw2; - tempws/=(int)((int16_t)tempw); - AX=tempws&0xFFFF; - } - else - { - x808x_log("IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=165; - break; - } - break; - - case 0xF8: /*CLC*/ - flags&=~C_FLAG; - cycles-=2; - break; - case 0xF9: /*STC*/ - flags|=C_FLAG; - cycles-=2; - break; - case 0xFA: /*CLI*/ - flags&=~I_FLAG; - cycles-=3; - break; - case 0xFB: /*STI*/ - flags|=I_FLAG; - cycles-=2; - break; - case 0xFC: /*CLD*/ - flags&=~D_FLAG; - cycles-=2; - break; - case 0xFD: /*STD*/ - flags|=D_FLAG; - cycles-=2; - break; - - case 0xFE: /*INC/DEC b*/ - fetchea(); - temp=geteab(); - flags&=~V_FLAG; - if (rmdat&0x38) - { - setsub8nc(temp,1); - temp2=temp-1; - if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG; - } - else - { - setadd8nc(temp,1); - temp2=temp+1; - if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG; - } - seteab(temp2); - cycles-=((cpu_mod==3)?3:23); - break; - - case 0xFF: - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*INC w*/ - tempw=geteaw(); - setadd16nc(tempw,1); - seteaw(tempw+1); - cycles-=((cpu_mod==3)?3:23); - break; - case 0x08: /*DEC w*/ - tempw=geteaw(); - setsub16nc(tempw,1); - seteaw(tempw-1); - cycles-=((cpu_mod==3)?3:23); - break; - case 0x10: /*CALL*/ - tempw=geteaw(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,(SP-2)&0xFFFF,cpu_state.pc); - SP-=2; - cpu_state.last_ea = SP; - cpu_state.pc=tempw; - cycles-=((cpu_mod==3)?20:29); - FETCHCLEAR(); - break; - case 0x18: /*CALL far*/ - tempw=readmemw(easeg,cpu_state.eaaddr); - tempw2=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - tempw3=CS; - tempw4=cpu_state.pc; - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=tempw; - loadcs(tempw2); - writememw(ss,(SP-2)&0xFFFF,tempw3); - writememw(ss,((SP-4)&0xFFFF),tempw4); - SP-=4; - cpu_state.last_ea = SP; - cycles-=53; - FETCHCLEAR(); - break; - case 0x20: /*JMP*/ - cpu_state.pc=geteaw(); - cycles-=((cpu_mod==3)?11:18); - FETCHCLEAR(); - break; - case 0x28: /*JMP far*/ - cpu_state.pc=readmemw(easeg,cpu_state.eaaddr); - loadcs(readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF)); - cycles-=24; - FETCHCLEAR(); - break; - case 0x30: /*PUSH w*/ - case 0x38: /*PUSH w alias, reported by reenigne*/ - tempw=geteaw(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),tempw); - SP-=2; - cpu_state.last_ea = SP; - cycles-=((cpu_mod==3)?15:24); - break; - } - break; - - default: - FETCH(); - cycles-=8; - break; - } - cpu_state.pc&=0xFFFF; - - if (cpu_state.ssegs) - { - ds=oldds; - ss=oldss; - cpu_state.ssegs=0; - } - - FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks); - if ((cycdiff-cycles) - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "cpu.h" -#include "x86.h" -#include "../machine/machine.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../nmi.h" -#include "../pic.h" -#include "../timer.h" -#include "../plat.h" - - -int xt_cpu_multi; -int nmi = 0; -int nmi_auto_clear = 0; - -int nextcyc=0; -int cycdiff; -int is8086=0; - -int memcycs; -int nopageerrors=0; - -void FETCHCOMPLETE(); - -uint8_t readmembl(uint32_t addr); -void writemembl(uint32_t addr, uint8_t val); -uint16_t readmemwl(uint32_t seg, uint32_t addr); -void writememwl(uint32_t seg, uint32_t addr, uint16_t val); -uint32_t readmemll(uint32_t seg, uint32_t addr); -void writememll(uint32_t seg, uint32_t addr, uint32_t val); - - -#ifdef ENABLE_808X_LOG -int x808x_do_log = ENABLE_808X_LOG; -#endif - - -static void -x808x_log(const char *fmt, ...) -{ -#ifdef ENABLE_808X_LOG - va_list ap; - - if (x808x_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -#undef readmemb -#undef readmemw -uint8_t readmemb(uint32_t a) -{ - if (a!=(cs+cpu_state.pc)) memcycs+=4; - if (readlookup2 == NULL) return readmembl(a); - if (readlookup2[(a)>>12]==-1) return readmembl(a); - else return *(uint8_t *)(readlookup2[(a) >> 12] + (a)); -} - -uint8_t readmembf(uint32_t a) -{ - if (readlookup2 == NULL) return readmembl(a); - if (readlookup2[(a)>>12]==-1) return readmembl(a); - else return *(uint8_t *)(readlookup2[(a) >> 12] + (a)); -} - -uint16_t readmemw(uint32_t s, uint16_t a) -{ - if (a!=(cs+cpu_state.pc)) memcycs+=(8>>is8086); - if (readlookup2 == NULL) return readmemwl(s,a); - if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s,a); - else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a); -} - -void refreshread() { FETCHCOMPLETE(); memcycs+=4; } - -#undef fetchea -#define fetchea() { rmdat=FETCH(); \ - cpu_reg=(rmdat>>3)&7; \ - cpu_mod=(rmdat>>6)&3; \ - cpu_rm=rmdat&7; \ - if (cpu_mod!=3) fetcheal(); } - -void writemembl(uint32_t addr, uint8_t val); -void writememb(uint32_t a, uint8_t v) -{ - memcycs+=4; - if (writelookup2 == NULL) writemembl(a,v); - if (writelookup2[(a)>>12]==-1) writemembl(a,v); - else *(uint8_t *)(writelookup2[a >> 12] + a) = v; -} -void writememwl(uint32_t seg, uint32_t addr, uint16_t val); -void writememw(uint32_t s, uint32_t a, uint16_t v) -{ - memcycs+=(8>>is8086); - if (writelookup2 == NULL) writememwl(s,a,v); - if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s,a,v); - else *(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v; -} -void writememll(uint32_t seg, uint32_t addr, uint32_t val); -void writememl(uint32_t s, uint32_t a, uint32_t v) -{ - if (writelookup2 == NULL) writememll(s,a,v); - if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememll(s,a,v); - else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v; -} - - -void dumpregs(int); -uint16_t oldcs; -int oldcpl; - -int tempc; -uint8_t opcode; -uint16_t pc2,pc3; -int noint=0; - -int output=0; - -#if 0 -/* Also in mem.c */ -int shadowbios=0; -#endif - -int ins=0; - -int fetchcycles=0,memcycs,fetchclocks; - -uint8_t prefetchqueue[6]; -uint16_t prefetchpc; -int prefetchw=0; -static __inline uint8_t FETCH() -{ - uint8_t temp; -/* temp=prefetchqueue[0]; - prefetchqueue[0]=prefetchqueue[1]; - prefetchqueue[1]=prefetchqueue[2]; - prefetchqueue[2]=prefetchqueue[3]; - prefetchqueue[3]=prefetchqueue[4]; - prefetchqueue[4]=prefetchqueue[5]; - if (prefetchw<=((is8086)?4:3)) - { - prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++; - if (is8086 && (prefetchpc&1)) - { - prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++; - } - }*/ - - if (prefetchw==0) - { - cycles-=(4-(fetchcycles&3)); - fetchclocks+=(4-(fetchcycles&3)); - fetchcycles=4; - temp=readmembf(cs+cpu_state.pc); - prefetchpc = cpu_state.pc = cpu_state.pc + 1; - if (is8086 && (cpu_state.pc&1)) - { - prefetchqueue[0]=readmembf(cs+cpu_state.pc); - prefetchpc++; - prefetchw++; - } - } - else - { - temp=prefetchqueue[0]; - prefetchqueue[0]=prefetchqueue[1]; - prefetchqueue[1]=prefetchqueue[2]; - prefetchqueue[2]=prefetchqueue[3]; - prefetchqueue[3]=prefetchqueue[4]; - prefetchqueue[4]=prefetchqueue[5]; - prefetchw--; - fetchcycles-=4; - cpu_state.pc++; - } - return temp; -} - -static __inline void FETCHADD(int c) -{ - int d; - if (c<0) return; - if (prefetchw>((is8086)?4:3)) return; - d=c+(fetchcycles&3); - while (d>3 && prefetchw<((is8086)?6:4)) - { - d-=4; - if (is8086 && !(prefetchpc&1)) - { - prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); - prefetchpc++; - prefetchw++; - } - if (prefetchw<6) - { - prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); - prefetchpc++; - prefetchw++; - } - } - fetchcycles+=c; - if (fetchcycles>16) fetchcycles=16; -} - -void FETCHCOMPLETE() -{ - if (!(fetchcycles&3)) return; - if (prefetchw>((is8086)?4:3)) return; - if (!prefetchw) nextcyc=(4-(fetchcycles&3)); - cycles-=(4-(fetchcycles&3)); - fetchclocks+=(4-(fetchcycles&3)); - if (is8086 && !(prefetchpc&1)) - { - prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); - prefetchpc++; - prefetchw++; - } - if (prefetchw<6) - { - prefetchqueue[prefetchw]=readmembf(cs+prefetchpc); - prefetchpc++; - prefetchw++; - } - fetchcycles+=(4-(fetchcycles&3)); -} - -static __inline void FETCHCLEAR() -{ - prefetchpc=cpu_state.pc; - prefetchw=0; - memcycs=cycdiff-cycles; - fetchclocks=0; -} - -static uint16_t getword() -{ - uint8_t temp=FETCH(); - return temp|(FETCH()<<8); -} - - -/*EA calculation*/ - -/*R/M - bits 0-2 - R/M bits 3-5 - Reg bits 6-7 - mod - From 386 programmers manual : -r8(/r) AL CL DL BL AH CH DH BH -r16(/r) AX CX DX BX SP BP SI DI -r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI -/digit (Opcode) 0 1 2 3 4 5 6 7 -REG = 000 001 010 011 100 101 110 111 - ����Address -disp8 denotes an 8-bit displacement following the ModR/M byte, to be -sign-extended and added to the index. disp16 denotes a 16-bit displacement -following the ModR/M byte, to be added to the index. Default segment -register is SS for the effective addresses containing a BP index, DS for -other effective addresses. - �Ŀ �Mod R/M� ���������ModR/M Values in Hexadecimal�������Ŀ - -[BX + SI] 000 00 08 10 18 20 28 30 38 -[BX + DI] 001 01 09 11 19 21 29 31 39 -[BP + SI] 010 02 0A 12 1A 22 2A 32 3A -[BP + DI] 011 03 0B 13 1B 23 2B 33 3B -[SI] 00 100 04 0C 14 1C 24 2C 34 3C -[DI] 101 05 0D 15 1D 25 2D 35 3D -disp16 110 06 0E 16 1E 26 2E 36 3E -[BX] 111 07 0F 17 1F 27 2F 37 3F - -[BX+SI]+disp8 000 40 48 50 58 60 68 70 78 -[BX+DI]+disp8 001 41 49 51 59 61 69 71 79 -[BP+SI]+disp8 010 42 4A 52 5A 62 6A 72 7A -[BP+DI]+disp8 011 43 4B 53 5B 63 6B 73 7B -[SI]+disp8 01 100 44 4C 54 5C 64 6C 74 7C -[DI]+disp8 101 45 4D 55 5D 65 6D 75 7D -[BP]+disp8 110 46 4E 56 5E 66 6E 76 7E -[BX]+disp8 111 47 4F 57 5F 67 6F 77 7F - -[BX+SI]+disp16 000 80 88 90 98 A0 A8 B0 B8 -[BX+DI]+disp16 001 81 89 91 99 A1 A9 B1 B9 -[BX+SI]+disp16 010 82 8A 92 9A A2 AA B2 BA -[BX+DI]+disp16 011 83 8B 93 9B A3 AB B3 BB -[SI]+disp16 10 100 84 8C 94 9C A4 AC B4 BC -[DI]+disp16 101 85 8D 95 9D A5 AD B5 BD -[BP]+disp16 110 86 8E 96 9E A6 AE B6 BE -[BX]+disp16 111 87 8F 97 9F A7 AF B7 BF - -EAX/AX/AL 000 C0 C8 D0 D8 E0 E8 F0 F8 -ECX/CX/CL 001 C1 C9 D1 D9 E1 E9 F1 F9 -EDX/DX/DL 010 C2 CA D2 DA E2 EA F2 FA -EBX/BX/BL 011 C3 CB D3 DB E3 EB F3 FB -ESP/SP/AH 11 100 C4 CC D4 DC E4 EC F4 FC -EBP/BP/CH 101 C5 CD D5 DD E5 ED F5 FD -ESI/SI/DH 110 C6 CE D6 DE E6 EE F6 FE -EDI/DI/BH 111 C7 CF D7 DF E7 EF F7 FF - -mod = 11 - register - 10 - address + 16 bit displacement - 01 - address + 8 bit displacement - 00 - address - -reg = If mod=11, (depending on data size, 16 bits/8 bits, 32 bits=extend 16 bit registers) - 0=AX/AL 1=CX/CL 2=DX/DL 3=BX/BL - 4=SP/AH 5=BP/CH 6=SI/DH 7=DI/BH - - Otherwise, LSB selects SI/DI (0=SI), NMSB selects BX/BP (0=BX), and MSB - selects whether BX/BP are used at all (0=used). - - mod=00 is an exception though - 6=16 bit displacement only - 7=[BX] - - Usage varies with instructions. - - MOV AL,BL has ModR/M as C3, for example. - mod=11, reg=0, r/m=3 - MOV uses reg as dest, and r/m as src. - reg 0 is AL, reg 3 is BL - - If BP or SP are in address calc, seg is SS, else DS -*/ - -uint32_t easeg; -int rmdat; - -uint16_t zero=0; -uint16_t *mod1add[2][8]; -uint32_t *mod1seg[8]; - -int slowrm[8]; - -void makemod1table() -{ - mod1add[0][0]=&BX; mod1add[0][1]=&BX; mod1add[0][2]=&BP; mod1add[0][3]=&BP; - mod1add[0][4]=&SI; mod1add[0][5]=&DI; mod1add[0][6]=&BP; mod1add[0][7]=&BX; - mod1add[1][0]=&SI; mod1add[1][1]=&DI; mod1add[1][2]=&SI; mod1add[1][3]=&DI; - mod1add[1][4]=&zero; mod1add[1][5]=&zero; mod1add[1][6]=&zero; mod1add[1][7]=&zero; - slowrm[0]=0; slowrm[1]=1; slowrm[2]=1; slowrm[3]=0; - mod1seg[0]=&ds; mod1seg[1]=&ds; mod1seg[2]=&ss; mod1seg[3]=&ss; - mod1seg[4]=&ds; mod1seg[5]=&ds; mod1seg[6]=&ss; mod1seg[7]=&ds; -} - -static void fetcheal() -{ - if (!cpu_mod && cpu_rm==6) { cpu_state.eaaddr=getword(); easeg=ds; FETCHADD(6); } - else - { - switch (cpu_mod) - { - case 0: - cpu_state.eaaddr=0; - if (cpu_rm&4) FETCHADD(5); - else FETCHADD(7+slowrm[cpu_rm]); - break; - case 1: - cpu_state.eaaddr=(uint16_t)(int8_t)FETCH(); - if (cpu_rm&4) FETCHADD(9); - else FETCHADD(11+slowrm[cpu_rm]); - break; - case 2: - cpu_state.eaaddr=getword(); - if (cpu_rm&4) FETCHADD(9); - else FETCHADD(11+slowrm[cpu_rm]); - break; - } - cpu_state.eaaddr+=(*mod1add[0][cpu_rm])+(*mod1add[1][cpu_rm]); - easeg=*mod1seg[cpu_rm]; - cpu_state.eaaddr&=0xFFFF; - } - - cpu_state.last_ea = cpu_state.eaaddr; -} - -static __inline uint8_t geteab() -{ - if (cpu_mod == 3) - return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm & 3].b.l; - return readmemb(easeg+cpu_state.eaaddr); -} - -static __inline uint16_t geteaw() -{ - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].w; - return readmemw(easeg,cpu_state.eaaddr); -} - -#if 0 -static __inline uint16_t geteaw2() -{ - if (cpu_mod == 3) - return cpu_state.regs[cpu_rm].w; - return readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); -} -#endif - -static __inline void seteab(uint8_t val) -{ - if (cpu_mod == 3) - { - if (cpu_rm & 4) - cpu_state.regs[cpu_rm & 3].b.h = val; - else - cpu_state.regs[cpu_rm & 3].b.l = val; - } - else - { - writememb(easeg+cpu_state.eaaddr,val); - } -} - -static __inline void seteaw(uint16_t val) -{ - if (cpu_mod == 3) - cpu_state.regs[cpu_rm].w = val; - else - { - writememw(easeg,cpu_state.eaaddr,val); - } -} - -#undef getr8 -#define getr8(r) ((r & 4) ? cpu_state.regs[r & 3].b.h : cpu_state.regs[r & 3].b.l) - -#undef setr8 -#define setr8(r,v) if (r & 4) cpu_state.regs[r & 3].b.h = v; \ - else cpu_state.regs[r & 3].b.l = v; - - -/*Flags*/ -uint8_t znptable8[256]; -uint16_t znptable16[65536]; - -void makeznptable() -{ - int c,d; - for (c=0;c<256;c++) - { - d=0; - if (c&1) d++; - if (c&2) d++; - if (c&4) d++; - if (c&8) d++; - if (c&16) d++; - if (c&32) d++; - if (c&64) d++; - if (c&128) d++; - if (d&1) - { - znptable8[c]=0; - } - else - { - znptable8[c]=P_FLAG; - } - if (c == 0xb1) x808x_log("znp8 b1 = %i %02X\n", d, znptable8[c]); - if (!c) znptable8[c]|=Z_FLAG; - if (c&0x80) znptable8[c]|=N_FLAG; - } - for (c=0;c<65536;c++) - { - d=0; - if (c&1) d++; - if (c&2) d++; - if (c&4) d++; - if (c&8) d++; - if (c&16) d++; - if (c&32) d++; - if (c&64) d++; - if (c&128) d++; - if (d&1) - znptable16[c]=0; - else - znptable16[c]=P_FLAG; - if (c == 0xb1) x808x_log("znp16 b1 = %i %02X\n", d, znptable16[c]); - if (c == 0x65b1) x808x_log("znp16 65b1 = %i %02X\n", d, znptable16[c]); - if (!c) znptable16[c]|=Z_FLAG; - if (c&0x8000) znptable16[c]|=N_FLAG; - } -} -#if 1 -/* Also in mem.c */ -int timetolive=0; -#endif - -extern uint32_t oldcs2; -extern uint32_t oldpc2; - -int indump = 0; - -void dumpregs(int force) -{ - int c,d=0,e=0; -#ifndef RELEASE_BUILD - FILE *f; -#endif - - /* Only dump when needed, and only once.. */ - if (indump || (!force && !dump_on_exit)) return; - -#ifndef RELEASE_BUILD - indump = 1; - output=0; - (void)plat_chdir(usr_path); - nopageerrors=1; - f=fopen("ram.dmp","wb"); - fwrite(ram,mem_size*1024,1,f); - fclose(f); - x808x_log("Dumping rram.dmp\n"); - f=fopen("rram.dmp","wb"); - for (c=0;c<0x1000000;c++) putc(readmemb(c),f); - fclose(f); - x808x_log("Dumping rram4.dmp\n"); - f=fopen("rram4.dmp","wb"); - for (c=0;c<0x0050000;c++) - { - cpu_state.abrt = 0; - putc(readmemb386l(0,c+0x80000000),f); - } - fclose(f); - x808x_log("Dumping done\n"); -#endif - if (is386) - x808x_log("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP); - else - x808x_log("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP); - x808x_log("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags); - x808x_log("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2); - x808x_log("%i ins\n",ins); - if (is386) - x808x_log("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); - else - x808x_log("In %s mode\n",(msw&1)?"protected":"real"); - x808x_log("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high); - x808x_log("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high); - x808x_log("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high); - if (is386) - { - x808x_log("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high); - x808x_log("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high); - } - x808x_log("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high); - x808x_log("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit); - x808x_log("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit); - x808x_log("IDT : base=%06X limit=%04X\n",idt.base,idt.limit); - x808x_log("TR : base=%06X limit=%04X\n", tr.base, tr.limit); - if (is386) - { - x808x_log("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit"); - x808x_log("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4); - } - x808x_log("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum); - for (c=0;c<1024*1024;c++) - { - if (readlookup2[c]!=0xFFFFFFFF) d++; - if (writelookup2[c]!=0xFFFFFFFF) e++; - } - x808x_log("Entries in readlookup : %i writelookup : %i\n",d,e); - x87_dumpregs(); - indump = 0; -} - -int resets = 0; -int x86_was_reset = 0; -void resetx86() -{ - x808x_log("x86 reset\n"); - resets++; - ins = 0; - use32=0; - cpu_cur_status = 0; - stack32=0; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - msw=0; - if (is486) - cr0 = 1 << 30; - else - cr0 = 0; - cpu_cache_int_enabled = 0; - cpu_update_waitstates(); - cr4 = 0; - eflags=0; - cgate32=0; - if(AT) - { - loadcs(0xF000); - cpu_state.pc=0xFFF0; - rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; - } - else - { - loadcs(0xFFFF); - cpu_state.pc=0; - rammask = 0xfffff; - } - idt.base = 0; - idt.limit = is386 ? 0x03FF : 0xFFFF; - flags=2; - makeznptable(); - resetreadlookup(); - makemod1table(); - resetmcr(); - FETCHCLEAR(); - x87_reset(); - cpu_set_edx(); - EAX = 0; - ESP=0; - mmu_perm=4; - memset(inscounts, 0, sizeof(inscounts)); - x86seg_reset(); -#ifdef USE_DYNAREC - codegen_reset(); -#endif - x86_was_reset = 1; - port_92_clear_reset(); -} - -void softresetx86() -{ - use32=0; - stack32=0; - cpu_cur_status = 0; - msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); - msw=0; - if (is486) - cr0 = 1 << 30; - else - cr0 = 0; - cpu_cache_int_enabled = 0; - cpu_update_waitstates(); - cr4 = 0; - eflags=0; - cgate32=0; - if(AT) - { - loadcs(0xF000); - cpu_state.pc=0xFFF0; - rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF; - } - else - { - loadcs(0xFFFF); - cpu_state.pc=0; - rammask = 0xfffff; - } - flags=2; - idt.base = 0; - idt.limit = is386 ? 0x03FF : 0xFFFF; - x86seg_reset(); - x86_was_reset = 1; - port_92_clear_reset(); -} - -static void setznp8(uint8_t val) -{ - flags&=~0xC4; - flags|=znptable8[val]; -} - -static void setznp16(uint16_t val) -{ - flags&=~0xC4; - flags|=znptable16[val]; -} - -static void setadd8(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a+(uint16_t)b; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadd8nc(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a+(uint16_t)b; - flags&=~0x8D4; - flags|=znptable8[c&0xFF]; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadc8(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a+(uint16_t)b+tempc; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadd16(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadd16nc(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b; - flags&=~0x8D4; - flags|=znptable16[c&0xFFFF]; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} -static void setadc16(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a+(uint32_t)b+tempc; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG; - if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG; -} - -static void setsub8(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a-(uint16_t)b; - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsub8nc(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a-(uint16_t)b; - flags&=~0x8D4; - flags|=znptable8[c&0xFF]; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsbc8(uint8_t a, uint8_t b) -{ - uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc); - flags&=~0x8D5; - flags|=znptable8[c&0xFF]; - if (c&0x100) flags|=C_FLAG; - if ((a^b)&(a^c)&0x80) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsub16(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a-(uint32_t)b; - flags&=~0x8D5; - flags|=znptable16[c&0xFFFF]; - if (c&0x10000) flags|=C_FLAG; - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsub16nc(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a-(uint32_t)b; - flags&=~0x8D4; - flags|=(znptable16[c&0xFFFF]&~4); - flags|=(znptable8[c&0xFF]&4); - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} -static void setsbc16(uint16_t a, uint16_t b) -{ - uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc); - flags&=~0x8D5; - flags|=(znptable16[c&0xFFFF]&~4); - flags|=(znptable8[c&0xFF]&4); - if (c&0x10000) flags|=C_FLAG; - if ((a^b)&(a^c)&0x8000) flags|=V_FLAG; - if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; -} - -int current_diff = 0; -void clockhardware() -{ - int diff = cycdiff - cycles - current_diff; - - current_diff += diff; - - timer_end_period(cycles*xt_cpu_multi); -} - -static int takeint = 0; - - -int firstrepcycle=1; - -void rep(int fv) -{ - uint8_t temp = 0; - int c=CX; - uint8_t temp2; - uint16_t tempw,tempw2; - uint16_t ipc=cpu_state.oldpc; - int changeds=0; - uint32_t oldds = 0; - startrep: - temp=FETCH(); - - switch (temp) - { - case 0x08: - cpu_state.pc=ipc+1; - cycles-=2; - FETCHCLEAR(); - break; - case 0x26: /*ES:*/ - oldds=ds; - ds=es; - changeds=1; - cycles-=2; - goto startrep; - break; - case 0x2E: /*CS:*/ - oldds=ds; - ds=cs; - changeds=1; - cycles-=2; - goto startrep; - break; - case 0x36: /*SS:*/ - oldds=ds; - ds=ss; - changeds=1; - cycles-=2; - goto startrep; - break; - case 0x6E: /*REP OUTSB*/ - if (c>0) - { - temp2=readmemb(ds+SI); - outb(DX,temp2); - if (flags&D_FLAG) SI--; - else SI++; - c--; - cycles-=5; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - case 0xA4: /*REP MOVSB*/ - while (c>0 && !IRQTEST) - { - temp2=readmemb(ds+SI); - writememb(es+DI,temp2); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - c--; - cycles-=17; - clockhardware(); - FETCHADD(17-memcycs); - } - if (IRQTEST && c>0) cpu_state.pc=ipc; - break; - case 0xA5: /*REP MOVSW*/ - while (c>0 && !IRQTEST) - { - memcycs=0; - tempw=readmemw(ds,SI); - writememw(es,DI,tempw); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - c--; - cycles-=17; - clockhardware(); - FETCHADD(17 - memcycs); - } - if (IRQTEST && c>0) cpu_state.pc=ipc; - break; - case 0xA6: /*REP CMPSB*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST) - { - memcycs=0; - temp=readmemb(ds+SI); - temp2=readmemb(es+DI); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - c--; - cycles -= 30; - setsub8(temp,temp2); - clockhardware(); - FETCHADD(30 - memcycs); - } - if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc; - break; - case 0xA7: /*REP CMPSW*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST) - { - memcycs=0; - tempw=readmemw(ds,SI); - tempw2=readmemw(es,DI); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - c--; - cycles -= 30; - setsub16(tempw,tempw2); - clockhardware(); - FETCHADD(30 - memcycs); - } - if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc; - break; - case 0xAA: /*REP STOSB*/ - while (c>0 && !IRQTEST) - { - memcycs=0; - writememb(es+DI,AL); - if (flags&D_FLAG) DI--; - else DI++; - c--; - cycles -= 10; - clockhardware(); - FETCHADD(10 - memcycs); - } - if (IRQTEST && c>0) cpu_state.pc=ipc; - break; - case 0xAB: /*REP STOSW*/ - while (c>0 && !IRQTEST) - { - memcycs=0; - writememw(es,DI,AX); - if (flags&D_FLAG) DI-=2; - else DI+=2; - c--; - cycles -= 10; - clockhardware(); - FETCHADD(10 - memcycs); - } - if (IRQTEST && c>0) cpu_state.pc=ipc; - break; - case 0xAC: /*REP LODSB*/ - if (c>0) - { - temp2=readmemb(ds+SI); - if (flags&D_FLAG) SI--; - else SI++; - c--; - cycles-=4; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - case 0xAD: /*REP LODSW*/ - if (c>0) - { - tempw2=readmemw(ds,SI); - if (flags&D_FLAG) SI-=2; - else SI+=2; - c--; - cycles-=4; - } - if (c>0) { firstrepcycle=0; cpu_state.pc=ipc; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - case 0xAE: /*REP SCASB*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) - { - temp2=readmemb(es+DI); - setsub8(AL,temp2); - if (flags&D_FLAG) DI--; - else DI++; - c--; - cycles -= 15; - } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - case 0xAF: /*REP SCASW*/ - if (fv) flags|=Z_FLAG; - else flags&=~Z_FLAG; - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) - { - tempw=readmemw(es,DI); - setsub16(AX,tempw); - if (flags&D_FLAG) DI-=2; - else DI+=2; - c--; - cycles -= 15; - } - if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); } - else firstrepcycle=1; - break; - default: - cpu_state.pc = ipc+1; - cycles-=20; - FETCHCLEAR(); - } - CX=c; - if (changeds) ds=oldds; - if (IRQTEST) - takeint = 1; -} - - -int inhlt=0; -uint16_t lastpc,lastcs; -int firstrepcycle; -int skipnextprint=0; - -int instime=0; -void execx86(int cycs) -{ - uint8_t temp = 0,temp2; - uint16_t addr,tempw,tempw2,tempw3,tempw4; - int8_t offset; - int tempws; - uint32_t templ; - unsigned int c; - int tempi; - int trap; - - cycles+=cycs; - while (cycles>0) - { - cycdiff=cycles; - timer_start_period(cycles*xt_cpu_multi); - current_diff = 0; - cycles-=nextcyc; - nextcyc=0; - fetchclocks=0; - oldcs=CS; - cpu_state.oldpc=cpu_state.pc; - opcodestart: - opcode=FETCH(); - tempc=flags&C_FLAG; - trap=flags&T_FLAG; - cpu_state.pc--; - if (output) - { - if (!skipnextprint) x808x_log("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]); - skipnextprint=0; - } - cpu_state.pc++; - inhlt=0; - switch (opcode) - { - case 0x00: /*ADD 8,reg*/ - fetchea(); - temp=geteab(); - setadd8(temp,getr8(cpu_reg)); - temp+=getr8(cpu_reg); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x01: /*ADD 16,reg*/ - fetchea(); - tempw=geteaw(); - setadd16(tempw, cpu_state.regs[cpu_reg].w); - tempw += cpu_state.regs[cpu_reg].w; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x02: /*ADD cpu_reg,8*/ - fetchea(); - temp=geteab(); - setadd8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)+temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x03: /*ADD cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setadd16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w+=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x04: /*ADD AL,#8*/ - temp=FETCH(); - setadd8(AL,temp); - AL+=temp; - cycles-=4; - break; - case 0x05: /*ADD AX,#16*/ - tempw=getword(); - setadd16(AX,tempw); - AX+=tempw; - cycles-=4; - break; - - case 0x06: /*PUSH ES*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),ES); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x07: /*POP ES*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_es); - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - - case 0x08: /*OR 8,reg*/ - fetchea(); - temp=geteab(); - temp|=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x09: /*OR 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw|=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x0A: /*OR cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp|=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x0B: /*OR reg,16*/ - fetchea(); - tempw=geteaw(); - tempw|=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x0C: /*OR AL,#8*/ - AL|=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x0D: /*OR AX,#16*/ - AX|=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - - case 0x0E: /*PUSH CS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),CS); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x0F: /*POP CS - 8088/8086 only*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_cs); - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - - case 0x10: /*ADC 8,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setadc8(temp,temp2); - temp+=temp2+tempc; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x11: /*ADC 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x12: /*ADC cpu_reg,8*/ - fetchea(); - temp=geteab(); - setadc8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)+temp+tempc); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x13: /*ADC cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setadc16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w+=tempw+tempc; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x14: /*ADC AL,#8*/ - tempw=FETCH(); - setadc8(AL,tempw & 0xff); - AL+=tempw+tempc; - cycles-=4; - break; - case 0x15: /*ADC AX,#16*/ - tempw=getword(); - setadc16(AX,tempw); - AX+=tempw+tempc; - cycles-=4; - break; - - case 0x16: /*PUSH SS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),SS); - SP-=2; - cycles-=14; - cpu_state.last_ea = SP; - break; - case 0x17: /*POP SS*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_ss); - SP+=2; - cpu_state.last_ea = SP; - noint=1; - cycles-=12; - break; - - case 0x18: /*SBB 8,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setsbc8(temp,temp2); - temp-=(temp2+tempc); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x19: /*SBB 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setsbc16(tempw,tempw2); - tempw-=(tempw2+tempc); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x1A: /*SBB cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsbc8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)-(temp+tempc)); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x1B: /*SBB cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setsbc16(tempw2,tempw); - tempw2-=(tempw+tempc); - cpu_state.regs[cpu_reg].w=tempw2; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x1C: /*SBB AL,#8*/ - temp=FETCH(); - setsbc8(AL,temp); - AL-=(temp+tempc); - cycles-=4; - break; - case 0x1D: /*SBB AX,#16*/ - tempw=getword(); - setsbc16(AX,tempw); - AX-=(tempw+tempc); - cycles-=4; - break; - - case 0x1E: /*PUSH DS*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),DS); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x1F: /*POP DS*/ - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - - case 0x20: /*AND 8,reg*/ - fetchea(); - temp=geteab(); - temp&=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x21: /*AND 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw&=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x22: /*AND cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp&=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x23: /*AND cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw&=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x24: /*AND AL,#8*/ - AL&=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x25: /*AND AX,#16*/ - AX&=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - - case 0x26: /*ES:*/ - oldss=ss; - oldds=ds; - ds=ss=es; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x27: /*DAA*/ - if ((flags&A_FLAG) || ((AL&0xF)>9)) - { - tempi=((uint16_t)AL)+6; - AL+=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; - } - if ((flags&C_FLAG) || (AL>0x9F)) - { - AL+=0x60; - flags|=C_FLAG; - } - setznp8(AL); - cycles-=4; - break; - - case 0x28: /*SUB 8,reg*/ - fetchea(); - temp=geteab(); - setsub8(temp,getr8(cpu_reg)); - temp-=getr8(cpu_reg); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x29: /*SUB 16,reg*/ - fetchea(); - tempw=geteaw(); - setsub16(tempw,cpu_state.regs[cpu_reg].w); - tempw-=cpu_state.regs[cpu_reg].w; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x2A: /*SUB cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsub8(getr8(cpu_reg),temp); - setr8(cpu_reg,getr8(cpu_reg)-temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x2B: /*SUB cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setsub16(cpu_state.regs[cpu_reg].w,tempw); - cpu_state.regs[cpu_reg].w-=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x2C: /*SUB AL,#8*/ - temp=FETCH(); - setsub8(AL,temp); - AL-=temp; - cycles-=4; - break; - case 0x2D: /*SUB AX,#16*/ - tempw=getword(); - setsub16(AX,tempw); - AX-=tempw; - cycles-=4; - break; - case 0x2E: /*CS:*/ - oldss=ss; - oldds=ds; - ds=ss=cs; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - case 0x2F: /*DAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - tempi=((uint16_t)AL)-6; - AL-=6; - flags|=A_FLAG; - if (tempi&0x100) flags|=C_FLAG; - } - if ((flags&C_FLAG)||(AL>0x9F)) - { - AL-=0x60; - flags|=C_FLAG; - } - setznp8(AL); - cycles-=4; - break; - case 0x30: /*XOR 8,reg*/ - fetchea(); - temp=geteab(); - temp^=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x31: /*XOR 16,reg*/ - fetchea(); - tempw=geteaw(); - tempw^=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x32: /*XOR cpu_reg,8*/ - fetchea(); - temp=geteab(); - temp^=getr8(cpu_reg); - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x33: /*XOR cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - tempw^=cpu_state.regs[cpu_reg].w; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?3:13); - break; - case 0x34: /*XOR AL,#8*/ - AL^=FETCH(); - setznp8(AL); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - case 0x35: /*XOR AX,#16*/ - AX^=getword(); - setznp16(AX); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=4; - break; - - case 0x36: /*SS:*/ - oldss=ss; - oldds=ds; - ds=ss=ss; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x37: /*AAA*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - AL+=6; - AH++; - flags|=(A_FLAG|C_FLAG); - } - else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=8; - break; - - case 0x38: /*CMP 8,reg*/ - fetchea(); - temp=geteab(); - setsub8(temp,getr8(cpu_reg)); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x39: /*CMP 16,reg*/ - fetchea(); - tempw=geteaw(); - setsub16(tempw,cpu_state.regs[cpu_reg].w); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3A: /*CMP cpu_reg,8*/ - fetchea(); - temp=geteab(); - setsub8(getr8(cpu_reg),temp); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3B: /*CMP cpu_reg,16*/ - fetchea(); - tempw=geteaw(); - setsub16(cpu_state.regs[cpu_reg].w,tempw); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x3C: /*CMP AL,#8*/ - temp=FETCH(); - setsub8(AL,temp); - cycles-=4; - break; - case 0x3D: /*CMP AX,#16*/ - tempw=getword(); - setsub16(AX,tempw); - cycles-=4; - break; - - case 0x3E: /*DS:*/ - oldss=ss; - oldds=ds; - ds=ss=ds; - cpu_state.ssegs=2; - cycles-=4; - goto opcodestart; - - case 0x3F: /*AAS*/ - if ((flags&A_FLAG)||((AL&0xF)>9)) - { - AL-=6; - AH--; - flags|=(A_FLAG|C_FLAG); - } - else - flags&=~(A_FLAG|C_FLAG); - AL&=0xF; - cycles-=8; - break; - - case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/ - case 0x44: case 0x45: case 0x46: case 0x47: - setadd16nc(cpu_state.regs[opcode&7].w,1); - cpu_state.regs[opcode&7].w++; - cycles-=3; - break; - case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/ - case 0x4C: case 0x4D: case 0x4E: case 0x4F: - setsub16nc(cpu_state.regs[opcode&7].w,1); - cpu_state.regs[opcode&7].w--; - cycles-=3; - break; - - case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/ - case 0x54: case 0x55: case 0x56: case 0x57: - if (cpu_state.ssegs) ss=oldss; - SP-=2; - cpu_state.last_ea = SP; - writememw(ss,SP,cpu_state.regs[opcode&7].w); - cycles-=15; - break; - case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/ - case 0x5C: case 0x5D: case 0x5E: case 0x5F: - if (cpu_state.ssegs) ss=oldss; - SP+=2; - cpu_state.last_ea = SP; - cpu_state.regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF); - cycles-=12; - break; - - - case 0x60: /*JO alias*/ - case 0x70: /*JO*/ - offset=(int8_t)FETCH(); - if (flags&V_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x61: /*JNO alias*/ - case 0x71: /*JNO*/ - offset=(int8_t)FETCH(); - if (!(flags&V_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x62: /*JB alias*/ - case 0x72: /*JB*/ - offset=(int8_t)FETCH(); - if (flags&C_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x63: /*JNB alias*/ - case 0x73: /*JNB*/ - offset=(int8_t)FETCH(); - if (!(flags&C_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x64: /*JE alias*/ - case 0x74: /*JE*/ - offset=(int8_t)FETCH(); - if (flags&Z_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x65: /*JNE alias*/ - case 0x75: /*JNE*/ - offset=(int8_t)FETCH(); - cycles-=4; - if (!(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - break; - case 0x66: /*JBE alias*/ - case 0x76: /*JBE*/ - offset=(int8_t)FETCH(); - if (flags&(C_FLAG|Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x67: /*JNBE alias*/ - case 0x77: /*JNBE*/ - offset=(int8_t)FETCH(); - if (!(flags&(C_FLAG|Z_FLAG))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x68: /*JS alias*/ - case 0x78: /*JS*/ - offset=(int8_t)FETCH(); - if (flags&N_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x69: /*JNS alias*/ - case 0x79: /*JNS*/ - offset=(int8_t)FETCH(); - if (!(flags&N_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6A: /*JP alias*/ - case 0x7A: /*JP*/ - offset=(int8_t)FETCH(); - if (flags&P_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6B: /*JNP alias*/ - case 0x7B: /*JNP*/ - offset=(int8_t)FETCH(); - if (!(flags&P_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6C: /*JL alias*/ - case 0x7C: /*JL*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp!=temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6D: /*JNL alias*/ - case 0x7D: /*JNL*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (temp==temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6E: /*JLE alias*/ - case 0x7E: /*JLE*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if ((flags&Z_FLAG) || (temp!=temp2)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - case 0x6F: /*JNLE alias*/ - case 0x7F: /*JNLE*/ - offset=(int8_t)FETCH(); - temp=(flags&N_FLAG)?1:0; - temp2=(flags&V_FLAG)?1:0; - if (!((flags&Z_FLAG) || (temp!=temp2))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=4; - break; - - case 0x80: case 0x82: - fetchea(); - temp=geteab(); - temp2=FETCH(); - switch (rmdat&0x38) - { - case 0x00: /*ADD b,#8*/ - setadd8(temp,temp2); - seteab(temp+temp2); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR b,#8*/ - temp|=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC b,#8*/ - setadc8(temp,temp2); - seteab(temp+temp2+tempc); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB b,#8*/ - setsbc8(temp,temp2); - seteab(temp-(temp2+tempc)); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND b,#8*/ - temp&=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x28: /*SUB b,#8*/ - setsub8(temp,temp2); - seteab(temp-temp2); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR b,#8*/ - temp^=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteab(temp); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x38: /*CMP b,#8*/ - setsub8(temp,temp2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x81: - fetchea(); - tempw=geteaw(); - tempw2=getword(); - switch (rmdat&0x38) - { - case 0x00: /*ADD w,#16*/ - setadd16(tempw,tempw2); - tempw+=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR w,#16*/ - tempw|=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC w,#16*/ - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND w,#16*/ - tempw&=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB w,#16*/ - setsbc16(tempw,tempw2); - seteaw(tempw-(tempw2+tempc)); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x28: /*SUB w,#16*/ - setsub16(tempw,tempw2); - tempw-=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR w,#16*/ - tempw^=tempw2; - setznp16(tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x38: /*CMP w,#16*/ - setsub16(tempw,tempw2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x83: - fetchea(); - tempw=geteaw(); - tempw2=FETCH(); - if (tempw2&0x80) tempw2|=0xFF00; - switch (rmdat&0x38) - { - case 0x00: /*ADD w,#8*/ - setadd16(tempw,tempw2); - tempw+=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x08: /*OR w,#8*/ - tempw|=tempw2; - setznp16(tempw); - seteaw(tempw); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x10: /*ADC w,#8*/ - setadc16(tempw,tempw2); - tempw+=tempw2+tempc; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x18: /*SBB w,#8*/ - setsbc16(tempw,tempw2); - tempw-=(tempw2+tempc); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x20: /*AND w,#8*/ - tempw&=tempw2; - setznp16(tempw); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - break; - case 0x28: /*SUB w,#8*/ - setsub16(tempw,tempw2); - tempw-=tempw2; - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - break; - case 0x30: /*XOR w,#8*/ - tempw^=tempw2; - setznp16(tempw); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:23); - flags&=~(C_FLAG|A_FLAG|V_FLAG); - break; - case 0x38: /*CMP w,#8*/ - setsub16(tempw,tempw2); - cycles-=((cpu_mod==3)?4:14); - break; - } - break; - - case 0x84: /*TEST b,reg*/ - fetchea(); - temp=geteab(); - temp2=getr8(cpu_reg); - setznp8(temp&temp2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x85: /*TEST w,reg*/ - fetchea(); - tempw=geteaw(); - tempw2=cpu_state.regs[cpu_reg].w; - setznp16(tempw&tempw2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?3:13); - break; - case 0x86: /*XCHG b,reg*/ - fetchea(); - temp=geteab(); - seteab(getr8(cpu_reg)); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?4:25); - break; - case 0x87: /*XCHG w,reg*/ - fetchea(); - tempw=geteaw(); - seteaw(cpu_state.regs[cpu_reg].w); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?4:25); - break; - - case 0x88: /*MOV b,reg*/ - fetchea(); - seteab(getr8(cpu_reg)); - cycles-=((cpu_mod==3)?2:13); - break; - case 0x89: /*MOV w,reg*/ - fetchea(); - seteaw(cpu_state.regs[cpu_reg].w); - cycles-=((cpu_mod==3)?2:13); - break; - case 0x8A: /*MOV cpu_reg,b*/ - fetchea(); - temp=geteab(); - setr8(cpu_reg,temp); - cycles-=((cpu_mod==3)?2:12); - break; - case 0x8B: /*MOV cpu_reg,w*/ - fetchea(); - tempw=geteaw(); - cpu_state.regs[cpu_reg].w=tempw; - cycles-=((cpu_mod==3)?2:12); - break; - - case 0x8C: /*MOV w,sreg*/ - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - seteaw(ES); - break; - case 0x08: /*CS*/ - seteaw(CS); - break; - case 0x18: /*DS*/ - if (cpu_state.ssegs) ds=oldds; - seteaw(DS); - break; - case 0x10: /*SS*/ - if (cpu_state.ssegs) ss=oldss; - seteaw(SS); - break; - } - cycles-=((cpu_mod==3)?2:13); - break; - - case 0x8D: /*LEA*/ - fetchea(); - cpu_state.regs[cpu_reg].w=(cpu_mod == 3)?cpu_state.last_ea:cpu_state.eaaddr; - cycles-=2; - break; - - case 0x8E: /*MOV sreg,w*/ - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*ES*/ - tempw=geteaw(); - loadseg(tempw,&_es); - break; - case 0x08: /*CS - 8088/8086 only*/ - tempw=geteaw(); - loadseg(tempw,&_cs); - break; - case 0x18: /*DS*/ - tempw=geteaw(); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - break; - case 0x10: /*SS*/ - tempw=geteaw(); - loadseg(tempw,&_ss); - if (cpu_state.ssegs) oldss=ss; - break; - } - cycles-=((cpu_mod==3)?2:12); - skipnextprint=1; - noint=1; - break; - - case 0x8F: /*POPW*/ - fetchea(); - if (cpu_state.ssegs) ss=oldss; - tempw=readmemw(ss,SP); - SP+=2; - cpu_state.last_ea = SP; - seteaw(tempw); - cycles-=25; - break; - - case 0x90: /*NOP*/ - cycles-=3; - break; - - case 0x91: case 0x92: case 0x93: /*XCHG AX*/ - case 0x94: case 0x95: case 0x96: case 0x97: - tempw=AX; - AX=cpu_state.regs[opcode&7].w; - cpu_state.regs[opcode&7].w=tempw; - cycles-=3; - break; - - case 0x98: /*CBW*/ - AH=(AL&0x80)?0xFF:0; - cycles-=2; - break; - case 0x99: /*CWD*/ - DX=(AX&0x8000)?0xFFFF:0; - cycles-=5; - break; - case 0x9A: /*CALL FAR*/ - tempw=getword(); - tempw2=getword(); - tempw3=CS; - tempw4=cpu_state.pc; - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=tempw; - loadcs(tempw2); - writememw(ss,(SP-2)&0xFFFF,tempw3); - writememw(ss,(SP-4)&0xFFFF,tempw4); - SP-=4; - cpu_state.last_ea = SP; - cycles-=36; - FETCHCLEAR(); - break; - case 0x9B: /*WAIT*/ - cycles-=4; - break; - case 0x9C: /*PUSHF*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - SP-=2; - cpu_state.last_ea = SP; - cycles-=14; - break; - case 0x9D: /*POPF*/ - if (cpu_state.ssegs) ss=oldss; - flags=readmemw(ss,SP)&0xFFF; - SP+=2; - cpu_state.last_ea = SP; - cycles-=12; - break; - case 0x9E: /*SAHF*/ - flags=(flags&0xFF00)|AH; - cycles-=4; - break; - case 0x9F: /*LAHF*/ - AH=flags&0xFF; - cycles-=4; - break; - - case 0xA0: /*MOV AL,(w)*/ - addr=getword(); - AL=readmemb(ds+addr); - cycles-=14; - break; - case 0xA1: /*MOV AX,(w)*/ - addr=getword(); - AX=readmemw(ds,addr); - cycles-=14; - break; - case 0xA2: /*MOV (w),AL*/ - addr=getword(); - writememb(ds+addr,AL); - cycles-=14; - break; - case 0xA3: /*MOV (w),AX*/ - addr=getword(); - writememw(ds,addr,AX); - cycles-=14; - break; - - case 0xA4: /*MOVSB*/ - temp=readmemb(ds+SI); - writememb(es+DI,temp); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - cycles-=18; - break; - case 0xA5: /*MOVSW*/ - tempw=readmemw(ds,SI); - writememw(es,DI,tempw); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - cycles-=18; - break; - case 0xA6: /*CMPSB*/ - temp =readmemb(ds+SI); - temp2=readmemb(es+DI); - setsub8(temp,temp2); - if (flags&D_FLAG) { DI--; SI--; } - else { DI++; SI++; } - cycles-=30; - break; - case 0xA7: /*CMPSW*/ - tempw =readmemw(ds,SI); - tempw2=readmemw(es,DI); - setsub16(tempw,tempw2); - if (flags&D_FLAG) { DI-=2; SI-=2; } - else { DI+=2; SI+=2; } - cycles-=30; - break; - case 0xA8: /*TEST AL,#8*/ - temp=FETCH(); - setznp8(AL&temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=5; - break; - case 0xA9: /*TEST AX,#16*/ - tempw=getword(); - setznp16(AX&tempw); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=5; - break; - case 0xAA: /*STOSB*/ - writememb(es+DI,AL); - if (flags&D_FLAG) DI--; - else DI++; - cycles-=11; - break; - case 0xAB: /*STOSW*/ - writememw(es,DI,AX); - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=11; - break; - case 0xAC: /*LODSB*/ - AL=readmemb(ds+SI); - if (flags&D_FLAG) SI--; - else SI++; - cycles-=16; - break; - case 0xAD: /*LODSW*/ - AX=readmemw(ds,SI); - if (flags&D_FLAG) SI-=2; - else SI+=2; - cycles-=16; - break; - case 0xAE: /*SCASB*/ - temp=readmemb(es+DI); - setsub8(AL,temp); - if (flags&D_FLAG) DI--; - else DI++; - cycles-=19; - break; - case 0xAF: /*SCASW*/ - tempw=readmemw(es,DI); - setsub16(AX,tempw); - if (flags&D_FLAG) DI-=2; - else DI+=2; - cycles-=19; - break; - - case 0xB0: /*MOV AL,#8*/ - AL=FETCH(); - cycles-=4; - break; - case 0xB1: /*MOV CL,#8*/ - CL=FETCH(); - cycles-=4; - break; - case 0xB2: /*MOV DL,#8*/ - DL=FETCH(); - cycles-=4; - break; - case 0xB3: /*MOV BL,#8*/ - BL=FETCH(); - cycles-=4; - break; - case 0xB4: /*MOV AH,#8*/ - AH=FETCH(); - cycles-=4; - break; - case 0xB5: /*MOV CH,#8*/ - CH=FETCH(); - cycles-=4; - break; - case 0xB6: /*MOV DH,#8*/ - DH=FETCH(); - cycles-=4; - break; - case 0xB7: /*MOV BH,#8*/ - BH=FETCH(); - cycles-=4; - break; - case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV cpu_reg,#16*/ - case 0xBC: case 0xBD: case 0xBE: case 0xBF: - cpu_state.regs[opcode&7].w=getword(); - cycles-=4; - break; - - case 0xC0: /*RET alias*/ - case 0xC2: /*RET*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - SP+=2+tempw; - cycles-=24; - FETCHCLEAR(); - break; - case 0xC1: /*RET alias*/ - case 0xC3: /*RET*/ - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - SP+=2; - cycles-=20; - FETCHCLEAR(); - break; - case 0xC4: /*LES*/ - fetchea(); - cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); - tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - loadseg(tempw,&_es); - cycles-=24; - break; - case 0xC5: /*LDS*/ - fetchea(); - cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); - tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - loadseg(tempw,&_ds); - if (cpu_state.ssegs) oldds=ds; - cycles-=24; - break; - case 0xC6: /*MOV b,#8*/ - fetchea(); - temp=FETCH(); - seteab(temp); - cycles-=((cpu_mod==3)?4:14); - break; - case 0xC7: /*MOV w,#16*/ - fetchea(); - tempw=getword(); - seteaw(tempw); - cycles-=((cpu_mod==3)?4:14); - break; - - case 0xC8: /*RETF alias*/ - case 0xCA: /*RETF*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,SP+2)); - SP+=4; - SP+=tempw; - cycles-=33; - FETCHCLEAR(); - break; - case 0xC9: /*RETF alias*/ - case 0xCB: /*RETF*/ - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,SP+2)); - SP+=4; - cycles-=34; - FETCHCLEAR(); - break; - case 0xCC: /*INT 3*/ - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - SP-=6; - addr=3<<2; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - cycles-=72; - break; - case 0xCD: /*INT*/ - lastpc=cpu_state.pc; - lastcs=CS; - temp=FETCH(); - - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),flags|0xF000); - writememw(ss,((SP-4)&0xFFFF),CS); - writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); - flags&=~T_FLAG; - SP-=6; - addr=temp<<2; - cpu_state.pc=readmemw(0,addr); - - loadcs(readmemw(0,addr+2)); - FETCHCLEAR(); - - cycles-=71; - break; - case 0xCF: /*IRET*/ - if (cpu_state.ssegs) ss=oldss; - tempw=CS; - tempw2=cpu_state.pc; - cpu_state.pc=readmemw(ss,SP); - loadcs(readmemw(ss,((SP+2)&0xFFFF))); - flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF; - SP+=6; - cycles-=44; - FETCHCLEAR(); - nmi_enable = 1; - break; - case 0xD0: - fetchea(); - temp=geteab(); - switch (rmdat&0x38) - { - case 0x00: /*ROL b,1*/ - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=1; - if (flags&C_FLAG) temp|=1; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x08: /*ROR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (flags&C_FLAG) temp|=0x80; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x10: /*RCL b,1*/ - temp2=flags&C_FLAG; - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=1; - if (temp2) temp|=1; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x18: /*RCR b,1*/ - temp2=flags&C_FLAG; - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (temp2) temp|=0x80; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x20: case 0x30: /*SHL b,1*/ - if (temp&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - if ((temp^(temp<<1))&0x80) flags|=V_FLAG; - else flags&=~V_FLAG; - temp<<=1; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x28: /*SHR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - if (temp&0x80) flags|=V_FLAG; - else flags&=~V_FLAG; - temp>>=1; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x38: /*SAR b,1*/ - if (temp&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=1; - if (temp&0x40) temp|=0x80; - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - flags&=~V_FLAG; - break; - } - break; - - case 0xD1: - fetchea(); - tempw=geteaw(); - switch (rmdat&0x38) - { - case 0x00: /*ROL w,1*/ - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=1; - if (flags&C_FLAG) tempw|=1; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x08: /*ROR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (flags&C_FLAG) tempw|=0x8000; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x10: /*RCL w,1*/ - temp2=flags&C_FLAG; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=1; - if (temp2) tempw|=1; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x18: /*RCR w,1*/ - temp2=flags&C_FLAG; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (temp2) tempw|=0x8000; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?2:23); - break; - case 0x20: case 0x30: /*SHL w,1*/ - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG; - else flags&=~V_FLAG; - tempw<<=1; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - case 0x28: /*SHR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - if (tempw&0x8000) flags|=V_FLAG; - else flags&=~V_FLAG; - tempw>>=1; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - break; - - case 0x38: /*SAR w,1*/ - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=1; - if (tempw&0x4000) tempw|=0x8000; - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?2:23); - flags|=A_FLAG; - flags&=~V_FLAG; - break; - } - break; - - case 0xD2: - fetchea(); - temp=geteab(); - c=CL; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL b,CL*/ - temp2=(temp&0x80)?1:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - temp2=(temp&0x80)?1:0; - temp=(temp<<1)|temp2; - c--; - cycles-=4; - } - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x08: /*ROR b,CL*/ - temp2=temp&1; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - temp2=temp&1; - temp>>=1; - if (temp2) temp|=0x80; - c--; - cycles-=4; - } - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x10: /*RCL b,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - temp2=temp&0x80; - temp<<=1; - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - if (templ) temp|=1; - c--; - cycles-=4; - } - seteab(temp); - if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x18: /*RCR b,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - temp2=temp&1; - temp>>=1; - if (temp2) flags|=C_FLAG; - else flags&=~C_FLAG; - if (templ) temp|=0x80; - c--; - cycles-=4; - } - seteab(temp); - if ((temp^(temp>>1))&0x40) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x20: case 0x30: /*SHL b,CL*/ - if (c > 8) - { - temp = 0; - flags &= ~C_FLAG; - } - else - { - if ((temp<<(c-1))&0x80) flags|=C_FLAG; - else flags&=~C_FLAG; - temp<<=c; - } - seteab(temp); - setznp8(temp); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - case 0x28: /*SHR b,CL*/ - if (c > 8) - { - temp = 0; - flags &= ~C_FLAG; - } - else - { - if ((temp>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - temp>>=c; - } - seteab(temp); - setznp8(temp); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - case 0x38: /*SAR b,CL*/ - if ((temp>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - while (c>0) - { - temp>>=1; - if (temp&0x40) temp|=0x80; - c--; - cycles-=4; - } - seteab(temp); - setznp8(temp); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - } - break; - - case 0xD3: - fetchea(); - tempw=geteaw(); - c=CL; - if (!c) break; - switch (rmdat&0x38) - { - case 0x00: /*ROL w,CL*/ - while (c>0) - { - temp=(tempw&0x8000)?1:0; - tempw=(tempw<<1)|temp; - c--; - cycles-=4; - } - if (temp) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x08: /*ROR w,CL*/ - tempw2=(tempw&1)?0x8000:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - tempw2=(tempw&1)?0x8000:0; - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - if (tempw2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x10: /*RCL w,CL*/ - while (c>0) - { - templ=flags&C_FLAG; - if (tempw&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw=(tempw<<1)|templ; - c--; - cycles-=4; - } - if (temp) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - case 0x18: /*RCR w,CL*/ - templ=flags&C_FLAG; - tempw2=(templ&1)?0x8000:0; - if (!c) - { - cycles-=((cpu_mod==3)?8:28); - break; - } - while (c>0) - { - templ=flags&C_FLAG; - tempw2=(templ&1)?0x8000:0; - if (tempw&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - if (tempw2) flags|=C_FLAG; - else flags&=~C_FLAG; - seteaw(tempw); - if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG; - else flags&=~V_FLAG; - cycles-=((cpu_mod==3)?8:28); - break; - - case 0x20: case 0x30: /*SHL w,CL*/ - if (c>16) - { - tempw=0; - flags&=~C_FLAG; - } - else - { - if ((tempw<<(c-1))&0x8000) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw<<=c; - } - seteaw(tempw); - setznp16(tempw); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - - case 0x28: /*SHR w,CL*/ - if (c > 16) - { - tempw = 0; - flags &= ~C_FLAG; - } - else - { - if ((tempw>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - tempw>>=c; - } - seteaw(tempw); - setznp16(tempw); - cycles-=(c*4); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - - case 0x38: /*SAR w,CL*/ - tempw2=tempw&0x8000; - if ((tempw>>(c-1))&1) flags|=C_FLAG; - else flags&=~C_FLAG; - while (c>0) - { - tempw=(tempw>>1)|tempw2; - c--; - cycles-=4; - } - seteaw(tempw); - setznp16(tempw); - cycles-=((cpu_mod==3)?8:28); - flags|=A_FLAG; - break; - } - break; - - case 0xD4: /*AAM*/ - tempws=FETCH(); - AH=AL/tempws; - AL%=tempws; - setznp16(AX); - cycles-=83; - break; - case 0xD5: /*AAD*/ - tempws=FETCH(); - AL=(AH*tempws)+AL; - AH=0; - setznp16(AX); - cycles-=60; - break; - case 0xD6: /*SETALC*/ - AL = (flags & C_FLAG) ? 0xff : 0; - cycles -= 4; - break; - case 0xD7: /*XLAT*/ - addr=BX+AL; - cpu_state.last_ea = addr; - AL=readmemb(ds+addr); - cycles-=11; - break; - case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/ - case 0xDC: case 0xDE: case 0xDF: case 0xD8: - fetchea(); - geteab(); - break; - - case 0xE0: /*LOOPNE*/ - offset=(int8_t)FETCH(); - CX--; - if (CX && !(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; - case 0xE1: /*LOOPE*/ - offset=(int8_t)FETCH(); - CX--; - if (CX && (flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; - case 0xE2: /*LOOP*/ - offset=(int8_t)FETCH(); - CX--; - if (CX) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=5; - break; - case 0xE3: /*JCXZ*/ - offset=(int8_t)FETCH(); - if (!CX) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); } - cycles-=6; - break; - - case 0xE4: /*IN AL*/ - temp=FETCH(); - AL=inb(temp); - cycles-=14; - break; - case 0xE5: /*IN AX*/ - temp=FETCH(); - AL=inb(temp); - AH=inb(temp+1); - cycles-=14; - break; - case 0xE6: /*OUT AL*/ - temp=FETCH(); - outb(temp,AL); - cycles-=14; - break; - case 0xE7: /*OUT AX*/ - temp=FETCH(); - outb(temp,AL); - outb(temp+1,AH); - cycles-=14; - break; - - case 0xE8: /*CALL rel 16*/ - tempw=getword(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),cpu_state.pc); - SP-=2; - cpu_state.last_ea = SP; - cpu_state.pc+=tempw; - cycles-=23; - FETCHCLEAR(); - break; - case 0xE9: /*JMP rel 16*/ - tempw = getword(); - cpu_state.pc += tempw; - cycles-=15; - FETCHCLEAR(); - break; - case 0xEA: /*JMP far*/ - addr=getword(); - tempw=getword(); - cpu_state.pc=addr; - loadcs(tempw); - cycles-=15; - FETCHCLEAR(); - break; - case 0xEB: /*JMP rel*/ - offset=(int8_t)FETCH(); - cpu_state.pc+=offset; - cycles-=15; - FETCHCLEAR(); - break; - case 0xEC: /*IN AL,DX*/ - AL=inb(DX); - cycles-=12; - break; - case 0xED: /*IN AX,DX*/ - AL=inb(DX); - AH=inb(DX+1); - cycles-=12; - break; - case 0xEE: /*OUT DX,AL*/ - outb(DX,AL); - cycles-=12; - break; - case 0xEF: /*OUT DX,AX*/ - outb(DX,AL); - outb(DX+1,AH); - cycles-=12; - break; - - case 0xF0: /*LOCK*/ - case 0xF1: /*LOCK alias*/ - cycles-=4; - break; - - case 0xF2: /*REPNE*/ - rep(0); - break; - case 0xF3: /*REPE*/ - rep(1); - break; - - case 0xF4: /*HLT*/ - inhlt=1; - cpu_state.pc--; - FETCHCLEAR(); - cycles-=2; - break; - case 0xF5: /*CMC*/ - flags^=C_FLAG; - cycles-=2; - break; - - case 0xF6: - fetchea(); - temp=geteab(); - switch (rmdat&0x38) - { - case 0x00: /*TEST b,#8*/ - case 0x08: - temp2=FETCH(); - temp&=temp2; - setznp8(temp); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?5:11); - break; - case 0x10: /*NOT b*/ - temp=~temp; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x18: /*NEG b*/ - setsub8(0,temp); - temp=0-temp; - seteab(temp); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x20: /*MUL AL,b*/ - setznp8(AL); - AX=AL*temp; - if (AX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=70; - break; - case 0x28: /*IMUL AL,b*/ - setznp8(AL); - tempws=(int)((int8_t)AL)*(int)((int8_t)temp); - AX=tempws&0xFFFF; - if (AX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (AH) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=80; - break; - case 0x30: /*DIV AL,b*/ - tempw=AX; - if (temp) - { - tempw2=tempw%temp; - AH=tempw2 & 0xff; - tempw/=temp; - AL=tempw&0xFF; - } - else - { - x808x_log("DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=80; - break; - case 0x38: /*IDIV AL,b*/ - tempws=(int)AX; - if (temp) - { - tempw2=tempws%(int)((int8_t)temp); - AH=tempw2&0xFF; - tempws/=(int)((int8_t)temp); - AL=tempws&0xFF; - } - else - { - x808x_log("IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=101; - break; - } - break; - - case 0xF7: - fetchea(); - tempw=geteaw(); - switch (rmdat&0x38) - { - case 0x00: /*TEST w*/ - case 0x08: - tempw2=getword(); - setznp16(tempw&tempw2); - flags&=~(C_FLAG|V_FLAG|A_FLAG); - cycles-=((cpu_mod==3)?5:11); - break; - case 0x10: /*NOT w*/ - seteaw(~tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x18: /*NEG w*/ - setsub16(0,tempw); - tempw=0-tempw; - seteaw(tempw); - cycles-=((cpu_mod==3)?3:24); - break; - case 0x20: /*MUL AX,w*/ - setznp16(AX); - templ=AX*tempw; - AX=templ&0xFFFF; - DX=templ>>16; - if (AX|DX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - if (DX) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - cycles-=118; - break; - case 0x28: /*IMUL AX,w*/ - setznp16(AX); - tempws=(int)((int16_t)AX)*(int)((int16_t)tempw); - if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG); - else flags&=~(C_FLAG|V_FLAG); - AX=tempws&0xFFFF; - tempws=(uint16_t)(tempws>>16); - DX=tempws&0xFFFF; - if (AX|DX) flags&=~Z_FLAG; - else flags|=Z_FLAG; - cycles-=128; - break; - case 0x30: /*DIV AX,w*/ - templ=(DX<<16)|AX; - if (tempw) - { - tempw2=templ%tempw; - DX=tempw2; - templ/=tempw; - AX=templ&0xFFFF; - } - else - { - x808x_log("DIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=144; - break; - case 0x38: /*IDIV AX,w*/ - tempws=(int)((DX<<16)|AX); - if (tempw) - { - tempw2=tempws%(int)((int16_t)tempw); - DX=tempw2; - tempws/=(int)((int16_t)tempw); - AX=tempws&0xFFFF; - } - else - { - x808x_log("IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc); - writememw(ss,(SP-2)&0xFFFF,flags|0xF000); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - flags&=~I_FLAG; - flags&=~T_FLAG; - cpu_state.pc=readmemw(0,0); - loadcs(readmemw(0,2)); - FETCHCLEAR(); - } - cycles-=165; - break; - } - break; - - case 0xF8: /*CLC*/ - flags&=~C_FLAG; - cycles-=2; - break; - case 0xF9: /*STC*/ - flags|=C_FLAG; - cycles-=2; - break; - case 0xFA: /*CLI*/ - flags&=~I_FLAG; - cycles-=3; - break; - case 0xFB: /*STI*/ - flags|=I_FLAG; - cycles-=2; - break; - case 0xFC: /*CLD*/ - flags&=~D_FLAG; - cycles-=2; - break; - case 0xFD: /*STD*/ - flags|=D_FLAG; - cycles-=2; - break; - - case 0xFE: /*INC/DEC b*/ - fetchea(); - temp=geteab(); - flags&=~V_FLAG; - if (rmdat&0x38) - { - setsub8nc(temp,1); - temp2=temp-1; - if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG; - } - else - { - setadd8nc(temp,1); - temp2=temp+1; - if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG; - } - seteab(temp2); - cycles-=((cpu_mod==3)?3:23); - break; - - case 0xFF: - fetchea(); - switch (rmdat&0x38) - { - case 0x00: /*INC w*/ - tempw=geteaw(); - setadd16nc(tempw,1); - seteaw(tempw+1); - cycles-=((cpu_mod==3)?3:23); - break; - case 0x08: /*DEC w*/ - tempw=geteaw(); - setsub16nc(tempw,1); - seteaw(tempw-1); - cycles-=((cpu_mod==3)?3:23); - break; - case 0x10: /*CALL*/ - tempw=geteaw(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,(SP-2)&0xFFFF,cpu_state.pc); - SP-=2; - cpu_state.last_ea = SP; - cpu_state.pc=tempw; - cycles-=((cpu_mod==3)?20:29); - FETCHCLEAR(); - break; - case 0x18: /*CALL far*/ - tempw=readmemw(easeg,cpu_state.eaaddr); - tempw2=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); - tempw3=CS; - tempw4=cpu_state.pc; - if (cpu_state.ssegs) ss=oldss; - cpu_state.pc=tempw; - loadcs(tempw2); - writememw(ss,(SP-2)&0xFFFF,tempw3); - writememw(ss,((SP-4)&0xFFFF),tempw4); - SP-=4; - cpu_state.last_ea = SP; - cycles-=53; - FETCHCLEAR(); - break; - case 0x20: /*JMP*/ - cpu_state.pc=geteaw(); - cycles-=((cpu_mod==3)?11:18); - FETCHCLEAR(); - break; - case 0x28: /*JMP far*/ - cpu_state.pc=readmemw(easeg,cpu_state.eaaddr); - loadcs(readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF)); - cycles-=24; - FETCHCLEAR(); - break; - case 0x30: /*PUSH w*/ - case 0x38: /*PUSH w alias, reported by reenigne*/ - tempw=geteaw(); - if (cpu_state.ssegs) ss=oldss; - writememw(ss,((SP-2)&0xFFFF),tempw); - SP-=2; - cpu_state.last_ea = SP; - cycles-=((cpu_mod==3)?15:24); - break; - } - break; - - default: - FETCH(); - cycles-=8; - break; - } - cpu_state.pc&=0xFFFF; - - if (cpu_state.ssegs) - { - ds=oldds; - ss=oldss; - cpu_state.ssegs=0; - } - - FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks); - if ((cycdiff-cycles) - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "86box.h" -#include "cpu/cpu.h" -#include "config.h" -#include "device.h" -#include "machine/machine.h" -#include "sound/sound.h" - - -#define DEVICE_MAX 256 /* max # of devices */ - - -typedef struct clonedev { - const device_t *master; - int count; - struct clonedev *next; -} clonedev_t; - - -static device_t *devices[DEVICE_MAX]; -static void *device_priv[DEVICE_MAX]; -static device_t *device_current; -static clonedev_t *clones = NULL; - - -#ifdef ENABLE_DEVICE_LOG -int device_do_log = ENABLE_DEVICE_LOG; -#endif - - -static void -device_log(const char *format, ...) -{ -#ifdef ENABLE_DEVICE_LOG - va_list ap; - - if (device_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } -#endif -} - -/* Initialize the module for use. */ -void -device_init(void) -{ - clonedev_t *ptr; - - memset(devices, 0x00, sizeof(devices)); - - ptr = NULL; - while (clones != NULL) - { - ptr = clones->next; - free(clones); - clones = ptr; - } - - clones = NULL; -} - - -/* Clone a master device for multi-instance devices. */ -const device_t * -device_clone(const device_t *master) -{ - char temp[1024], *sp; - clonedev_t *cl, *ptr; - device_t *dev; - - /* Look up the master. */ - for (ptr = clones; ptr != NULL; ptr = ptr->next) - if (ptr->master == master) break; - - /* If not found, add this master to the list. */ - if (ptr == NULL) { - ptr = (clonedev_t *)malloc(sizeof(clonedev_t)); - memset(ptr, 0x00, sizeof(clonedev_t)); - if (clones != NULL) { - for (cl = clones; cl->next != NULL; cl = cl->next) - ; - cl->next = ptr; - } else - clones = ptr; - ptr->master = master; - } - - /* Create a new device. */ - dev = (device_t *)malloc(sizeof(device_t)); - - /* Copy the master info. */ - memcpy(dev, ptr->master, sizeof(device_t)); - - /* Set up a clone. */ - if (++ptr->count > 1) - sprintf(temp, "%s #%i", ptr->master->name, ptr->count); - else - strcpy(temp, ptr->master->name); - sp = (char *)malloc(strlen(temp) + 1); - strcpy(sp, temp); - dev->name = (const char *)sp; - - return((const device_t *)dev); -} - - -void * -device_add(const device_t *d) -{ - void *priv = NULL; - int c; - - for (c=0; c<256; c++) { - if (devices[c] == (device_t *)d) { - device_log("DEVICE: device already exists!\n"); - return(NULL); - } - if (devices[c] == NULL) break; - } - if (c >= DEVICE_MAX) - fatal("DEVICE: too many devices\n"); - - device_current = (device_t *)d; - - devices[c] = (device_t *)d; - - if (d->init != NULL) { - priv = d->init(d); - if (priv == NULL) { - if (d->name) - device_log("DEVICE: device '%s' init failed\n", d->name); - else - device_log("DEVICE: device init failed\n"); - - device_priv[c] = NULL; - - return(NULL); - } - } - - device_priv[c] = priv; - - return(priv); -} - - -/* For devices that do not have an init function (internal video etc.) */ -void -device_add_ex(const device_t *d, void *priv) -{ - int c; - - for (c=0; c<256; c++) { - if (devices[c] == (device_t *)d) { - fatal("device_add: device already exists!\n"); - break; - } - if (devices[c] == NULL) break; - } - if (c >= DEVICE_MAX) - fatal("device_add: too many devices\n"); - - device_current = (device_t *)d; - - devices[c] = (device_t *)d; - device_priv[c] = priv; -} - - -void -device_close_all(void) -{ - int c; - - for (c=0; cclose != NULL) - devices[c]->close(device_priv[c]); - devices[c] = device_priv[c] = NULL; - } - } -} - - -void -device_reset_all(void) -{ - int c; - - for (c=0; creset != NULL) - devices[c]->reset(device_priv[c]); - } - } -} - - -/* Reset all attached PCI devices - needed for PCI turbo reset control. */ -void -device_reset_all_pci(void) -{ - int c; - - for (c=0; creset != NULL) && (devices[c]->flags & DEVICE_PCI)) - devices[c]->reset(device_priv[c]); - } - } -} - - -void * -device_get_priv(const device_t *d) -{ - int c; - - for (c=0; cflags & DEVICE_NOT_WORKING) return(0); -#endif - if (d->available != NULL) - return(d->available()); - - return(1); -} - - -void -device_speed_changed(void) -{ - int c; - - for (c=0; cspeed_changed != NULL) - devices[c]->speed_changed(device_priv[c]); - } - } - - sound_speed_changed(); -} - - -void -device_force_redraw(void) -{ - int c; - - for (c=0; cforce_redraw != NULL) - devices[c]->force_redraw(device_priv[c]); - } - } -} - - -char * -device_get_config_string(char *s) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_string((char *)device_current->name, s, (char *)c->default_string)); - - c++; - } - - return(NULL); -} - - -int -device_get_config_int(char *s) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_int((char *)device_current->name, s, c->default_int)); - - c++; - } - - return(0); -} - - -int -device_get_config_int_ex(char *s, int default_int) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_int((char *)device_current->name, s, default_int)); - - c++; - } - - return(default_int); -} - - -int -device_get_config_hex16(char *s) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_hex16((char *)device_current->name, s, c->default_int)); - - c++; - } - - return(0); -} - - -int -device_get_config_hex20(char *s) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_hex20((char *)device_current->name, s, c->default_int)); - - c++; - } - - return(0); -} - - -int -device_get_config_mac(char *s, int default_int) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_mac((char *)device_current->name, s, default_int)); - - c++; - } - - return(default_int); -} - - -void -device_set_config_int(char *s, int val) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) { - config_set_int((char *)device_current->name, s, val); - break; - } - - c++; - } -} - - -void -device_set_config_hex16(char *s, int val) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) { - config_set_hex16((char *)device_current->name, s, val); - break; - } - - c++; - } -} - - -void -device_set_config_hex20(char *s, int val) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) { - config_set_hex20((char *)device_current->name, s, val); - break; - } - - c++; - } -} - - -void -device_set_config_mac(char *s, int val) -{ - const device_config_t *c = device_current->config; - - while (c && c->type != -1) { - if (! strcmp(s, c->name)) { - config_set_mac((char *)device_current->name, s, val); - break; - } - - c++; - } -} - - -int -device_is_valid(const device_t *device, int mflags) -{ - if (device == NULL) return(1); - - if ((device->flags & DEVICE_AT) && !(mflags & MACHINE_AT)) return(0); - - if ((device->flags & DEVICE_CBUS) && !(mflags & MACHINE_CBUS)) return(0); - - if ((device->flags & DEVICE_ISA) && !(mflags & MACHINE_ISA)) return(0); - - if ((device->flags & DEVICE_MCA) && !(mflags & MACHINE_MCA)) return(0); - - if ((device->flags & DEVICE_EISA) && !(mflags & MACHINE_EISA)) return(0); - - if ((device->flags & DEVICE_VLB) && !(mflags & MACHINE_VLB)) return(0); - - if ((device->flags & DEVICE_PCI) && !(mflags & MACHINE_PCI)) return(0); - - if ((device->flags & DEVICE_PS2) && !(mflags & MACHINE_HDC_PS2)) return(0); - if ((device->flags & DEVICE_AGP) && !(mflags & MACHINE_AGP)) return(0); - - return(1); -} - - -int -machine_get_config_int(char *s) -{ - const device_t *d = machine_getdevice(machine); - const device_config_t *c; - - if (d == NULL) return(0); - - c = d->config; - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_int((char *)d->name, s, c->default_int)); - - c++; - } - - return(0); -} - - -char * -machine_get_config_string(char *s) -{ - const device_t *d = machine_getdevice(machine); - const device_config_t *c; - - if (d == NULL) return(0); - - c = d->config; - while (c && c->type != -1) { - if (! strcmp(s, c->name)) - return(config_get_string((char *)d->name, s, (char *)c->default_string)); - - c++; - } - - return(NULL); -} diff --git a/src/device - Cópia.h b/src/device - Cópia.h deleted file mode 100644 index 9e6508172..000000000 --- a/src/device - Cópia.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Definitions for the device handler. - * - * Version: @(#)device.h 1.0.6 2018/09/02 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2017,2018 Fred N. van Kempen. - * Copyright 2016-2018 Miran Grca. - * Copyright 2008-2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#ifndef EMU_DEVICE_H -# define EMU_DEVICE_H - - -#define CONFIG_STRING 0 -#define CONFIG_INT 1 -#define CONFIG_BINARY 2 -#define CONFIG_SELECTION 3 -#define CONFIG_MIDI 4 -#define CONFIG_FNAME 5 -#define CONFIG_SPINNER 6 -#define CONFIG_HEX16 7 -#define CONFIG_HEX20 8 -#define CONFIG_MAC 9 - - -enum { - DEVICE_NOT_WORKING = 1, /* does not currently work correctly and will be disabled in a release build*/ - DEVICE_AT = 2, /* requires an AT-compatible system */ - DEVICE_PS2 = 4, /* requires a PS/1 or PS/2 system */ - DEVICE_ISA = 8, /* requires the ISA bus */ - DEVICE_CBUS = 0x10, /* requires the C-BUS bus */ - DEVICE_MCA = 0x20, /* requires the MCA bus */ - DEVICE_EISA = 0x40, /* requires the EISA bus */ - DEVICE_VLB = 0x80, /* requires the PCI bus */ - DEVICE_PCI = 0x100, /* requires the VLB bus */ - DEVICE_AGP = 0x200 /* requires the AGP bus */ -}; - - -typedef struct { - const char *description; - int value; -} device_config_selection_t; - -typedef struct { - const char *description; - const char *extensions[5]; -} device_config_file_filter_t; - -typedef struct { - int min; - int max; - int step; -} device_config_spinner_t; - -typedef struct { - const char *name; - const char *description; - int type; - const char *default_string; - int default_int; - device_config_selection_t selection[16]; - device_config_file_filter_t file_filter[16]; - device_config_spinner_t spinner; -} device_config_t; - -typedef struct _device_ { - const char *name; - uint32_t flags; /* system flags */ - uint32_t local; /* flags local to device */ - - void *(*init)(const struct _device_ *); - void (*close)(void *p); - void (*reset)(void *p); - int (*available)(/*void*/); - void (*speed_changed)(void *p); - void (*force_redraw)(void *p); - - const device_config_t *config; -} device_t; - - -#ifdef __cplusplus -extern "C" { -#endif - -extern void device_init(void); -extern const device_t * device_clone(const device_t *master); -extern void *device_add(const device_t *d); -extern void device_add_ex(const device_t *d, void *priv); -extern void device_close_all(void); -extern void device_reset_all(void); -extern void device_reset_all_pci(void); -extern void *device_get_priv(const device_t *d); -extern int device_available(const device_t *d); -extern void device_speed_changed(void); -extern void device_force_redraw(void); - -extern int device_get_config_int(char *name); -extern int device_get_config_int_ex(char *s, int default_int); -extern int device_get_config_hex16(char *name); -extern int device_get_config_hex20(char *name); -extern int device_get_config_mac(char *name, int default_int); -extern void device_set_config_int(char *s, int val); -extern void device_set_config_hex16(char *s, int val); -extern void device_set_config_hex20(char *s, int val); -extern void device_set_config_mac(char *s, int val); -extern char *device_get_config_string(char *name); -extern int device_is_valid(const device_t *device, int machine_flags); - -extern int machine_get_config_int(char *s); -extern char *machine_get_config_string(char *s); - -#ifdef __cplusplus -} -#endif - - -#endif /*EMU_DEVICE_H*/ diff --git a/src/isamem - Cópia.c b/src/isamem - Cópia.c deleted file mode 100644 index fab98eb3a..000000000 --- a/src/isamem - Cópia.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of a memory expansion board for the ISA Bus. - * - * Although modern systems use direct-connect local buses to - * connect the CPU with its memory, originally the main system - * bus(es) were used for that. Memory expension cards could add - * memory to the system through the ISA bus, using a variety of - * techniques. - * - * The majority of these boards could provide some (additional) - * conventional (low) memory, extended (high) memory on 80286 - * and higher systems, as well as EMS bank-switched memory. - * - * This implementation uses the LIM 3.2 specifications for EMS. - * - * With the EMS method, the system's standard memory is expanded - * by means of bank-switching. One or more 'frames' in the upper - * memory area (640K-1024K) are used as viewports into an array - * of RAM pages numbered 0 to N. Each page is defined to be 16KB - * in size, so, for a 1024KB board, 64 such pages are available. - * I/O control registers are used to set up the mappings. More - * modern boards even have multiple 'copies' of those registers, - * which can be switched very fast, to allow for multitasking. - * - * TODO: The EV159 is supposed to support 16b EMS transfers, but the - * EMM.sys driver for it doesn't seem to want to do that.. - * - * Version: @(#)isamem.c 1.0.3 2018/09/04 - * - * Author: Fred N. van Kempen, - * - * Copyright 2018 Fred N. van Kempen. - * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include -#include -#include -#include -#include "86box.h" -#include "cpu/cpu.h" -#include "machine/machine.h" -#include "io.h" -#include "mem.h" -#include "device.h" -#include "ui.h" -#include "plat.h" -#include "isamem.h" - -#define RAM_TOPMEM (640 << 10) /* end of low memory */ -#define RAM_UMAMEM (384 << 10) /* upper memory block */ -#define RAM_EXTMEM (1024 << 10) /* start of high memory */ - -#define EMS_MAXSIZE (2048 << 10) /* max EMS memory size */ -#define EMS_PGSIZE (16 << 10) /* one page is this big */ -#define EMS_MAXPAGE 4 /* number of viewport pages */ - - -typedef struct { - int8_t enabled; /* 1=ENABLED */ - uint8_t page; /* page# in EMS RAM */ - uint8_t frame; /* (varies with board) */ - char pad; - uint8_t *addr; /* start addr in EMS RAM */ - mem_mapping_t mapping; /* mapping entry for page */ -} emsreg_t; - -typedef struct { - const char *name; - uint8_t board : 6, /* board type */ - instance : 2; /* device instance */ - - uint8_t flags; -#define FLAG_CONFIG 0x01 /* card is configured */ -#define FLAG_WIDE 0x10 /* card uses 16b mode */ -#define FLAG_FAST 0x20 /* fast (<= 120ns) chips */ -#define FLAG_EMS 0x40 /* card has EMS mode enabled */ - - uint16_t total_size; /* configured size in KB */ - uint32_t base_addr, /* configured I/O address */ - start_addr, /* configured memory start */ - frame_addr; /* configured frame address */ - - uint16_t ems_size, /* EMS size in KB */ - ems_pages; /* EMS size in pages */ - uint32_t ems_start; /* start of EMS in RAM */ - - uint8_t *ram; /* allocated RAM buffer */ - - mem_mapping_t low_mapping; /* mapping for low mem */ - mem_mapping_t high_mapping; /* mapping for high mem */ - - emsreg_t ems[EMS_MAXPAGE]; /* EMS controller registers */ -} memdev_t; - -#ifdef ENABLE_ISAMEM_LOG -int isamem_do_log = ENABLE_ISAMEM_LOG; -#endif - - -static void -isamem_log(const char *fmt, ...) -{ -#ifdef ENABLE_ISAMEM_LOG - va_list ap; - - if (isamem_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -/* Read one byte from onboard RAM. */ -static uint8_t -ram_readb(uint32_t addr, void *priv) -{ - mem_mapping_t *map = (mem_mapping_t *)priv; - memdev_t *dev = (memdev_t *)map->dev; - uint8_t ret = 0xff; - - /* Grab the data. */ - ret = *(uint8_t *)(dev->ram + (addr - map->base)); - - return(ret); -} - - -/* Read one word from onboard RAM. */ -static uint16_t -ram_readw(uint32_t addr, void *priv) -{ - mem_mapping_t *map = (mem_mapping_t *)priv; - memdev_t *dev = (memdev_t *)map->dev; - uint16_t ret = 0xffff; - - /* Grab the data. */ - ret = *(uint16_t *)(dev->ram + (addr - map->base)); - - return(ret); -} - - -/* Write one byte to onboard RAM. */ -static void -ram_writeb(uint32_t addr, uint8_t val, void *priv) -{ - mem_mapping_t *map = (mem_mapping_t *)priv; - memdev_t *dev = (memdev_t *)map->dev; - - /* Write the data. */ - *(uint8_t *)(dev->ram + (addr - map->base)) = val; -} - - -/* Write one word to onboard RAM. */ -static void -ram_writew(uint32_t addr, uint16_t val, void *priv) -{ - mem_mapping_t *map = (mem_mapping_t *)priv; - memdev_t *dev = (memdev_t *)map->dev; - - /* Write the data. */ - *(uint16_t *)(dev->ram + (addr - map->base)) = val; -} - - -/* Read one byte from onboard paged RAM. */ -static uint8_t -ems_readb(uint32_t addr, void *priv) -{ - mem_mapping_t *map = (mem_mapping_t *)priv; - memdev_t *dev = (memdev_t *)map->dev; - uint8_t ret = 0xff; - int vpage; - - /* Get the viewport page number. */ - vpage = ((addr & 0xffff) / EMS_PGSIZE); - - /* Grab the data. */ - ret = *(uint8_t *)(dev->ems[vpage].addr + (addr - map->base)); - - return(ret); -} - - -/* Read one word from onboard paged RAM. */ -static uint16_t -ems_readw(uint32_t addr, void *priv) -{ - mem_mapping_t *map = (mem_mapping_t *)priv; - memdev_t *dev = (memdev_t *)map->dev; - uint16_t ret = 0xffff; - int vpage; - - /* Get the viewport page number. */ - vpage = ((addr & 0xffff) / EMS_PGSIZE); - - /* Grab the data. */ - ret = *(uint16_t *)(dev->ems[vpage].addr + (addr - map->base)); - - return(ret); -} - - -/* Write one byte to onboard paged RAM. */ -static void -ems_writeb(uint32_t addr, uint8_t val, void *priv) -{ - mem_mapping_t *map = (mem_mapping_t *)priv; - memdev_t *dev = (memdev_t *)map->dev; - int vpage; - - /* Get the viewport page number. */ - vpage = ((addr & 0xffff) / EMS_PGSIZE); - - /* Write the data. */ - *(uint8_t *)(dev->ems[vpage].addr + (addr - map->base)) = val; -} - - -/* Write one word to onboard paged RAM. */ -static void -ems_writew(uint32_t addr, uint16_t val, void *priv) -{ - mem_mapping_t *map = (mem_mapping_t *)priv; - memdev_t *dev = (memdev_t *)map->dev; - int vpage; - - /* Get the viewport page number. */ - vpage = ((addr & 0xffff) / EMS_PGSIZE); - - /* Write the data. */ - *(uint16_t *)(dev->ems[vpage].addr + (addr - map->base)) = val; -} - - -/* Handle a READ operation from one of our registers. */ -static uint8_t -ems_read(uint16_t port, void *priv) -{ - memdev_t *dev = (memdev_t *)priv; - uint8_t ret = 0xff; - int vpage; - - /* Get the viewport page number. */ - vpage = (port / EMS_PGSIZE); - port &= (EMS_PGSIZE - 1); - - switch(port - dev->base_addr) { - case 0x0000: /* page number register */ - ret = dev->ems[vpage].page; - if (dev->ems[vpage].enabled) - ret |= 0x80; - break; - - case 0x0001: /* W/O */ - break; - } - - isamem_log("ISAMEM: read(%04x) = %02x)\n", port, ret); - - return(ret); -} - - -/* Handle a WRITE operation to one of our registers. */ -static void -ems_write(uint16_t port, uint8_t val, void *priv) -{ - memdev_t *dev = (memdev_t *)priv; - int vpage; - - /* Get the viewport page number. */ - vpage = (port / EMS_PGSIZE); - port &= (EMS_PGSIZE - 1); - - isamem_log("ISAMEM: write(%04x, %02x) page=%d\n", port, val, vpage); - - switch(port - dev->base_addr) { - case 0x0000: /* page mapping registers */ - /* Set the page number. */ - dev->ems[vpage].enabled = (val & 0x80); - dev->ems[vpage].page = (val & 0x7f); - - /* Make sure we can do that.. */ - if (dev->flags & FLAG_CONFIG) { - if (dev->ems[vpage].page < dev->ems_pages) { - /* Pre-calculate the page address in EMS RAM. */ - dev->ems[vpage].addr = dev->ram + dev->ems_start + ((val & 0x7f) * EMS_PGSIZE); - } else { - /* That page does not exist. */ - dev->ems[vpage].enabled = 0; - } - - if (dev->ems[vpage].enabled) { - /* Update the EMS RAM address for this page. */ - mem_mapping_set_exec(&dev->ems[vpage].mapping, - dev->ems[vpage].addr); - - /* Enable this page. */ - mem_mapping_enable(&dev->ems[vpage].mapping); - } else { - /* Disable this page. */ - mem_mapping_disable(&dev->ems[vpage].mapping); - } - } - break; - - case 0x0001: /* page frame registers */ - /* - * The EV-159 EMM driver configures the frame address - * by setting bits in these registers. The information - * in their manual is unclear, but here is what was - * found out by repeatedly changing EMM's config: - * - * 00 04 08 Address - * ----------------- - * 80 c0 e0 E0000 - */ - - isamem_log("EMS: write(%02x) to register 1 !\n"); - - dev->ems[vpage].frame = val; - if (val) - dev->flags |= FLAG_CONFIG; - break; - } -} - - -/* Initialize the device for use. */ -static void * -isamem_init(const device_t *info) -{ - memdev_t *dev; - uint32_t k, t; - uint32_t addr; - uint32_t tot; - uint8_t *ptr; - int i; - - /* Find our device and create an instance. */ - dev = (memdev_t *)malloc(sizeof(memdev_t)); - memset(dev, 0x00, sizeof(memdev_t)); - dev->name = info->name; - dev->board = info->local; - - /* Do per-board initialization. */ - tot = 0; - switch(dev->board) { - case 0: /* IBM PC/XT Memory Expansion Card */ - case 2: /* Paradise Systems 5-PAK */ - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - tot = dev->total_size; - break; - - case 1: /* IBM PC/AT Memory Expansion Card */ - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - tot = dev->total_size; - dev->flags |= FLAG_WIDE; - break; - - case 3: /* Micro Mainframe EMS-5150(T) */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->frame_addr = 0xD0000; - dev->flags |= (FLAG_EMS | FLAG_CONFIG); - break; - - case 10: /* Everex EV-159 RAM 3000 */ - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - tot = device_get_config_int("length"); - if (!!device_get_config_int("width")) - dev->flags |= FLAG_WIDE; - if (!!device_get_config_int("speed")) - dev->flags |= FLAG_FAST; - if (!!device_get_config_int("ems")) - dev->flags |= FLAG_EMS; -dev->frame_addr = 0xE0000; - break; - - case 11: - dev->base_addr = device_get_config_hex16("base"); - dev->total_size = device_get_config_int("size"); - dev->start_addr = device_get_config_int("start"); - dev->frame_addr = device_get_config_hex20("frame"); - if (!!device_get_config_int("width")) - dev->flags |= FLAG_WIDE; - if (!!device_get_config_int("speed")) - dev->flags |= FLAG_FAST; - break; - } - - /* Fix up the memory start address. */ - dev->start_addr <<= 10; - - /* Say hello! */ - isamem_log("ISAMEM: %s (%iKB", info->name, dev->total_size); - if (dev->total_size != tot) isamem_log(", %iKB for RAM", tot); - if (dev->flags & FLAG_FAST) isamem_log(", FAST"); - if (dev->flags & FLAG_WIDE) isamem_log(", 16BIT"); - isamem_log(")\n"); - - /* Force (back to) 8-bit bus if needed. */ - if (AT) { - if (! cpu_16bitbus) - isamem_log("ISAMEM: *WARNING* this board will slow down your PC!\n"); - } else { - isamem_log("ISAMEM: not AT+ system, forcing 8-bit mode!\n"); - dev->flags &= ~FLAG_WIDE; - } - - /* Allocate and initialize our RAM. */ - k = dev->total_size << 10; - dev->ram = (uint8_t *)malloc(k); - memset(dev->ram, 0x00, k); - ptr = dev->ram; - - /* - * The 'Memory Start Address' switch indicates at which address - * we should start adding memory. No memory is added if it is - * set to 0. - */ - tot <<= 10; - addr = dev->start_addr; - if (addr > 0 && tot > 0) { - /* Adjust K for the RAM we will use. */ - k -= tot; - - /* - * First, see if we have to expand the conventional - * (low) memory area. This can extend up to 640KB, - * so check this first. - */ - t = (addr < RAM_TOPMEM) ? RAM_TOPMEM - addr : 0; - if (t > 0) { - /* - * We need T bytes to extend that area. - * - * If the board doesn't have that much, grab - * as much as we can. - */ - if (t > tot) - t = tot; - isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); - - /* Create, initialize and enable the low-memory mapping. */ - mem_mapping_add(&dev->low_mapping, addr, t, - ram_readb, - (dev->flags&FLAG_WIDE) ? ram_readw : NULL, - NULL, - ram_writeb, - (dev->flags&FLAG_WIDE) ? ram_writew : NULL, - NULL, - ptr, MEM_MAPPING_EXTERNAL, &dev->low_mapping); - mem_mapping_set_dev(&dev->low_mapping, dev); - - /* Tell the memory system this is external RAM. */ - mem_set_mem_state(addr, t, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - - /* Update pointers. */ - ptr += t; - tot -= t; - addr += t; - } - - /* Skip to high memory if needed. */ - if ((addr == RAM_TOPMEM) && (tot >= RAM_UMAMEM)) { - /* - * We have more RAM available, but we are at the - * top of conventional RAM. So, the next 384K are - * skipped, and placed into different mappings so - * they can be re-mapped later. - */ - t = RAM_UMAMEM; /* 384KB */ - - isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); - - /* Update and enable the remap. */ - mem_mapping_del(&ram_remapped_mapping); - mem_mapping_add(&ram_remapped_mapping, - addr + tot, t, - ram_readb, ram_readw, NULL, - ram_writeb, ram_writew, NULL, - ptr, MEM_MAPPING_EXTERNAL, - &ram_remapped_mapping); - mem_mapping_set_exec(&ram_remapped_mapping, ptr); - mem_mapping_set_dev(&ram_remapped_mapping, dev); - mem_mapping_disable(&ram_remapped_mapping); - - /* Tell the memory system this is external RAM. */ - mem_set_mem_state(addr + tot, t, - MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - - /* Update pointers. */ - ptr += t; - tot -= t; - addr += t; - } - } - - /* - * Next, on systems that support it (80286 and up), we can add - * (some of) our RAM to the system as Extended Memory, that is, - * memory located above 1MB. This memory cannot be addressed in - * real mode (so, not by DOS, for example) but it can be used in - * protected mode. - */ - if (AT && addr > 0 && tot > 0) { - t = tot; - isamem_log("ISAMEM: RAM at %05iKB (%iKB)\n", addr>>10, t>>10); - - /* Create, initialize and enable the high-memory mapping. */ - mem_mapping_add(&dev->high_mapping, addr, t, - ram_readb, ram_readw, NULL, - ram_writeb, ram_writew, NULL, - ptr, MEM_MAPPING_EXTERNAL, &dev->high_mapping); - mem_mapping_set_dev(&dev->high_mapping, dev); - - /* Tell the memory system this is external RAM. */ - mem_set_mem_state(addr, t, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - - /* Update pointers. */ - ptr += t; - tot -= t; - addr += t; - } - - /* If EMS is enabled, use the remainder for EMS. */ - if (dev->flags & FLAG_EMS) { - /* EMS 3.2 cannot have more than 2048KB per board. */ - t = k; - if (t > EMS_MAXSIZE) - t = EMS_MAXSIZE; - - /* Set up where EMS begins in local RAM, and how much we have. */ - dev->ems_start = ptr - dev->ram; - dev->ems_size = t >> 10; - dev->ems_pages = t / EMS_PGSIZE; - isamem_log("ISAMEM: EMS enabled, I/O=%04xH, %iKB (%i pages)", - dev->base_addr, dev->ems_size, dev->ems_pages); - if (dev->frame_addr > 0) - isamem_log(", Frame=%05XH", dev->frame_addr); - isamem_log("\n"); - - /* - * For each supported page (we can have a maximum of 4), - * create, initialize and disable the mappings, and set - * up the I/O control handler. - */ - for (i = 0; i < EMS_MAXPAGE; i++) { - /* Create and initialize a page mapping. */ - mem_mapping_add(&dev->ems[i].mapping, - dev->frame_addr + (EMS_PGSIZE*i), EMS_PGSIZE, - ems_readb, - (dev->flags&FLAG_WIDE) ? ems_readw : NULL, - NULL, - ems_writeb, - (dev->flags&FLAG_WIDE) ? ems_writew : NULL, - NULL, - ptr, MEM_MAPPING_EXTERNAL, - &dev->ems[i].mapping); - mem_mapping_set_dev(&dev->ems[i].mapping, dev); - - /* For now, disable it. */ - mem_mapping_disable(&dev->ems[i].mapping); - - /* Set up an I/O port handler. */ - io_sethandler(dev->base_addr + (EMS_PGSIZE*i), 2, - ems_read,NULL,NULL, ems_write,NULL,NULL, dev); - } - } - - /* Just so its not NULL. */ - return((void *)dev); -} - - -/* Remove the device from the system. */ -static void -isamem_close(void *priv) -{ - memdev_t *dev = (memdev_t *)priv; - int i; - - if (dev->flags & FLAG_EMS) { - for (i = 0; i < EMS_MAXPAGE; i++) { - io_removehandler(dev->base_addr + (EMS_PGSIZE*i), 2, - ems_read,NULL,NULL, ems_write,NULL,NULL, dev); - - } - } - - if (dev->ram != NULL) - free(dev->ram); - - if (dev != NULL) - free(dev); -} - - -static const device_config_t ibmxt_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - { { 0 } }, - { { 0 } }, - { 0, 256, 16 } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 256, - { { 0 } }, - { { 0 } }, - { 0, 640-64, 64 } - }, - { - "", "", -1 - } -}; - -static const device_t ibmxt_device = { - "IBM PC/XT Memory Expansion", - DEVICE_ISA, - 0, - isamem_init, - isamem_close, - NULL, - NULL, - NULL, - NULL, - ibmxt_config -}; - - -static const device_config_t ibmat_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 512, - { { 0 } }, - { { 0 } }, - { 0, 4096, 512 } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 512, - { { 0 } }, - { { 0 } }, - { 0, 16128, 128 } - }, - { - "", "", -1 - } -}; - -static const device_t ibmat_device = { - "IBM PC/AT Memory Expansion", - DEVICE_ISA, - 1, - isamem_init, isamem_close, NULL, - NULL, NULL, NULL, - ibmat_config -}; - -static const device_config_t p5pak_config[] = - { - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - { { 0 } }, - { { 0 } }, - { 0, 384, 64 } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 512, - { { 0 } }, - { { 0 } }, - { 64, 576, 64 } - }, - { - "", "", -1 - } - }; - -static const device_t p5pak_device = { - "Paradise Systems 5-PAK", - DEVICE_ISA, - 2, - isamem_init, isamem_close, NULL, - NULL, NULL, NULL, - p5pak_config -}; - -static const device_config_t ems5150_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 256, - { { 0 } }, - { { 0 } }, - { 0, 2048, 64 } - }, - { - "base", "Address", CONFIG_HEX16, "", 0, - { - { - "Disabled", 0 - }, - { - "Board 1", 0x0208 - }, - { - "Board 2", 0x020a - }, - { - "Board 3", 0x020c - }, - { - "Board 4", 0x020e - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; - -static const device_t ems5150_device = { - "Micro Mainframe EMS-5150(T)", - DEVICE_ISA, - 3, - isamem_init, isamem_close, NULL, - NULL, NULL, NULL, - ems5150_config -}; - -static const device_config_t ev159_config[] = -{ - { - "size", "Memory Size", CONFIG_SPINNER, "", 512, - { { 0 } }, - { { 0 } }, - { 0, 3072, 512 } - }, - { - "start", "Start Address", CONFIG_SPINNER, "", 0, - { { 0 } }, - { { 0 } }, - { 0, 16128, 128 } - }, - { - "length", "Contiguous Size", CONFIG_SPINNER, "", 0, - { { 0 } }, - { { 0 } }, - { 0, 16384, 128 } - }, - { - "width", "I/O Width", CONFIG_SELECTION, "", 0, - { - { - "8-bit", 0 - }, - { - "16-bit", 1 - }, - { - "" - } - }, - }, - { - "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, - { - { - "Standard (150ns)", 0 - }, - { - "High-Speed (120ns)", 1 - }, - { - "" - } - } - }, - { - "ems", "EMS mode", CONFIG_SELECTION, "", 0, - { - { - "Disabled", 0 - }, - { - "Enabled", 1 - }, - { - "" - } - }, - }, - { - "base", "Address", CONFIG_HEX16, "", 0x0258, - { - { - "208H", 0x0208 - }, - { - "218H", 0x0218 - }, - { - "258H", 0x0258 - }, - { - "268H", 0x0268 - }, - { - "2A8H", 0x02A8 - }, - { - "2B8H", 0x02B8 - }, - { - "2E8H", 0x02E8 - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; - -static const device_t ev159_device = { - "Everex EV-159 RAM 3000 Deluxe", - DEVICE_ISA, - 10, - isamem_init, isamem_close, NULL, - NULL, NULL, NULL, - ev159_config -}; - - -#ifdef USE_ISAMEM_RAMPAGE -static const device_config_t rampage_config[] = -{ - { - "base", "Address", CONFIG_HEX16, "", 0x0258, - { - { - "208H", 0x0208 - }, - { - "218H", 0x0218 - }, - { - "258H", 0x0258 - }, - { - "268H", 0x0268 - }, - { - "2A8H", 0x02A8 - }, - { - "2B8H", 0x02B8 - }, - { - "2E8H", 0x02E8 - }, - { - "" - } - }, - }, - { - "frame", "Frame Address", CONFIG_HEX20, "", 0, - { - { - "Disabled", 0x00000 - }, - { - "C000H", 0xC0000 - }, - { - "D000H", 0xD0000 - }, - { - "E000H", 0xE0000 - }, - { - "" - } - }, - }, - { - "width", "I/O Width", CONFIG_SELECTION, "", 8, - { - { - "8-bit", 8 - }, - { - "16-bit", 16 - }, - { - "" - } - }, - }, - { - "speed", "Transfer Speed", CONFIG_SELECTION, "", 0, - { - { - "Standard", 0 - }, - { - "High-Speed", 1 - }, - { - "" - } - } - }, - { - "size", "Memory Size", CONFIG_SPINNER, "", 128, - { { 0 } }, - { { 0 } }, - { 0, 8192, 128 } - }, - { - "", "", -1 - } -}; - -static const device_t isamem_rampage_device = { - "AST RAMpage/XT", - DEVICE_ISA, - 11, - isamem_init, isamem_close, NULL, - NULL, NULL, NULL, - rampage_config -}; -#endif - - -static const struct { - const char *name; - const char *internal_name; - const device_t *dev; -} boards[] = { - { "None", "none", NULL, }, - { "IBM PC/XT Memory Expansion", "ibmxt", &ibmxt_device, }, - { "IBM PC/AT Memory Expansion", "ibmat", &ibmat_device, }, - { "Micro Mainframe EMS-5150(T)", "ems5150", &ems5150_device }, - { "Paradise Systems 5-PAK", "p5pak", &p5pak_device }, - { "Everex EV-159 RAM 3000 Deluxe", "ev159", &ev159_device, }, - { "", "", NULL, }, -}; - - -void -isamem_reset(void) -{ - const device_t *dev; - int k, i; - - for (i = 0; i < ISAMEM_MAX; i++) { - k = isamem_type[i]; - if (k == 0) continue; - - /* Clone the device. */ - dev = device_clone(boards[k].dev); - - /* Add the instance to the system. */ - device_add(dev); - } -} - - -char * -isamem_get_name(int board) -{ - return((char *)boards[board].name); -} - - -char * -isamem_get_internal_name(int board) -{ - return((char *)boards[board].internal_name); -} - - - -int -isamem_get_from_internal_name(char *s) -{ - int c = 0; - - while (strlen((char *) boards[c].internal_name)) { - if (!strcmp((char *)boards[c].internal_name, s)) - return(c); - c++; - } - - /* Not found. */ - return(0); -} - - -const device_t * -isamem_get_device(int board) -{ - return(boards[board].dev); -} diff --git a/src/isamem - Cópia.h b/src/isamem - Cópia.h deleted file mode 100644 index 955103d71..000000000 --- a/src/isamem - Cópia.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Definitions for the ISAMEM cards. - * - * Version: @(#)isamem.h 1.0.1 2018/08/18 - * - * Authors: Fred N. van Kempen, - * - * Copyright 2018 Fred N. van Kempen. - * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#ifndef ISAMEM_H -# define ISAMEM_H - - -#define ISAMEM_MAX 4 /* max #cards in system */ - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Global variables. */ -extern const device_t isamem_device; -extern const device_t isamem_brat80_device; -extern const device_t isamem_ev159_device; - - -/* Functions. */ -extern void isamem_reset(void); - -extern char *isamem_get_name(int t); -extern char *isamem_get_internal_name(int t); -extern int isamem_get_from_internal_name(char *s); -extern const device_t *isamem_get_device(int t); - -#ifdef __cplusplus -} -#endif - - -#endif /*ISAMEM_H*/ diff --git a/src/machine/m_amstrad - Cópia.c b/src/machine/m_amstrad - Cópia.c deleted file mode 100644 index 7f91c89cc..000000000 --- a/src/machine/m_amstrad - Cópia.c +++ /dev/null @@ -1,1306 +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. - * - * Emulation of the Amstrad series of PC's: PC1512, PC1640 and - * PC200, including their keyboard, mouse and video devices, as - * well as the PC2086 and PC3086 systems. - * - * PC1512: The PC1512 extends CGA with a bit-planar 640x200x16 mode. - * Most CRTC registers are fixed. - * - * The Technical Reference Manual lists the video waitstate - * time as between 12 and 46 cycles. We currently always use - * the lower number. - * - * PC1640: Mostly standard EGA, but with CGA & Hercules emulation. - * - * PC200: CGA with some NMI stuff. But we don't need that as it's only - * used for TV and LCD displays, and we're emulating a CRT. - * - * TODO: This module is not complete yet: - * - * PC1512: The BIOS assumes 512K RAM, because I cannot figure out how to - * read the status of the LK4 jumper on the mainboard, which is - * somehow linked to the bus gate array on the NDMACS line... - * - * PC1612: EGA mode does not seem to work in the PC1640; it works fine - * in alpha mode, but in highres ("ECD350") mode, it displays - * some semi-random junk. Video-memory pointer maybe? - * - * Version: @(#)m_amstrad.c 1.0.15 2018/09/19 - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../nmi.h" -#include "../pic.h" -#include "../pit.h" -#include "../ppi.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../nvr.h" -#include "../keyboard.h" -#include "../mouse.h" -#include "../game/gameport.h" -#include "../lpt.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../sound/sound.h" -#include "../sound/snd_speaker.h" -#include "../video/video.h" -#include "../video/vid_cga.h" -#include "../video/vid_ega.h" -#include "../video/vid_paradise.h" -#include "machine.h" - - -#define STAT_PARITY 0x80 -#define STAT_RTIMEOUT 0x40 -#define STAT_TTIMEOUT 0x20 -#define STAT_LOCK 0x10 -#define STAT_CD 0x08 -#define STAT_SYSFLAG 0x04 -#define STAT_IFULL 0x02 -#define STAT_OFULL 0x01 - - -typedef struct { - rom_t bios_rom; /* 1640 */ - cga_t cga; /* 1640/200 */ - ega_t ega; /* 1640 */ - uint8_t crtc[32]; - int crtcreg; - int cga_enabled; /* 1640 */ - uint8_t cgacol, - cgamode, - stat; - uint8_t plane_write, /* 1512/200 */ - plane_read, /* 1512/200 */ - border; /* 1512/200 */ - int linepos, - displine; - int sc, vc; - int cgadispon; - int con, coff, - cursoron, - cgablink; - int64_t vsynctime; - int vadj; - uint16_t ma, maback; - int dispon; - int blink; - int64_t dispontime, /* 1512/1640 */ - dispofftime; /* 1512/1640 */ - int64_t vidtime; /* 1512/1640 */ - int firstline, - lastline; - uint8_t *vram; -} amsvid_t; - -typedef struct { - /* Machine stuff. */ - uint8_t dead; - uint8_t stat1, - stat2; - - /* Keyboard stuff. */ - int8_t wantirq; - uint8_t key_waiting; - uint8_t pa; - uint8_t pb; - - /* Mouse stuff. */ - uint8_t mousex, - mousey; - int oldb; - - /* Video stuff. */ - amsvid_t *vid; -} amstrad_t; - - -static uint8_t key_queue[16]; -static int key_queue_start = 0, - key_queue_end = 0; -static uint8_t crtc_mask[32] = { - 0xff, 0xff, 0xff, 0xff, 0x7f, 0x1f, 0x7f, 0x7f, - 0xf3, 0x1f, 0x7f, 0x1f, 0x3f, 0xff, 0x3f, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static video_timings_t timing_pc1512 = {VIDEO_BUS, 0,0,0, 0,0,0}; /*PC1512 video code handles waitstates itself*/ -static video_timings_t timing_pc1640 = {VIDEO_ISA, 8,16,32, 8,16,32}; -static video_timings_t timing_pc200 = {VIDEO_ISA, 8,16,32, 8,16,32}; - - -#ifdef ENABLE_AMSTRAD_LOG -int amstrad_do_log = ENABLE_AMSTRAD_LOG; -#endif - - -static void -amstrad_log(const char *fmt, ...) -{ -#ifdef ENABLE_AMSTRAD_LOG - va_list ap; - - if (amstrad_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -static void -recalc_timings_1512(amsvid_t *vid) -{ - double _dispontime, _dispofftime, disptime; - - disptime = 128; /*Fixed on PC1512*/ - _dispontime = 80; - _dispofftime = disptime - _dispontime; - _dispontime *= CGACONST; - _dispofftime *= CGACONST; - vid->dispontime = (int64_t)(_dispontime * (1 << TIMER_SHIFT)); - vid->dispofftime = (int64_t)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -static void -vid_out_1512(uint16_t addr, uint8_t val, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - uint8_t old; - - switch (addr) { - case 0x03d4: - vid->crtcreg = val & 31; - return; - - case 0x03d5: - old = vid->crtc[vid->crtcreg]; - vid->crtc[vid->crtcreg] = val & crtc_mask[vid->crtcreg]; - if (old != val) { - if (vid->crtcreg < 0xe || vid->crtcreg > 0x10) { - fullchange = changeframecount; - recalc_timings_1512(vid); - } - } - return; - - case 0x03d8: - if ((val & 0x12) == 0x12 && (vid->cgamode & 0x12) != 0x12) { - vid->plane_write = 0xf; - vid->plane_read = 0; - } - vid->cgamode = val; - return; - - case 0x03d9: - vid->cgacol = val; - return; - - case 0x03dd: - vid->plane_write = val; - return; - - case 0x03de: - vid->plane_read = val & 3; - return; - - case 0x03df: - vid->border = val; - return; - } -} - - -static uint8_t -vid_in_1512(uint16_t addr, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - uint8_t ret = 0xff; - - switch (addr) { - case 0x03d4: - ret = vid->crtcreg; - - case 0x03d5: - ret = vid->crtc[vid->crtcreg]; - - case 0x03da: - ret = vid->stat; - } - - return(ret); -} - - -static void -vid_write_1512(uint32_t addr, uint8_t val, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - egawrites++; - cycles -= 12; - addr &= 0x3fff; - - if ((vid->cgamode & 0x12) == 0x12) { - if (vid->plane_write & 1) vid->vram[addr] = val; - if (vid->plane_write & 2) vid->vram[addr | 0x4000] = val; - if (vid->plane_write & 4) vid->vram[addr | 0x8000] = val; - if (vid->plane_write & 8) vid->vram[addr | 0xc000] = val; - } else - vid->vram[addr] = val; -} - - -static uint8_t -vid_read_1512(uint32_t addr, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - egareads++; - cycles -= 12; - addr &= 0x3fff; - - if ((vid->cgamode & 0x12) == 0x12) - return(vid->vram[addr | (vid->plane_read << 14)]); - - return(vid->vram[addr]); -} - - -static void -vid_poll_1512(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - uint16_t ca = (vid->crtc[15] | (vid->crtc[14] << 8)) & 0x3fff; - int drawcursor; - int x, c; - uint8_t chr, attr; - uint16_t dat, dat2, dat3, dat4; - int cols[4]; - int col; - int oldsc; - - if (! vid->linepos) { - vid->vidtime += vid->dispofftime; - vid->stat |= 1; - vid->linepos = 1; - oldsc = vid->sc; - if (vid->dispon) { - if (vid->displine < vid->firstline) { - vid->firstline = vid->displine; - video_wait_for_buffer(); - } - vid->lastline = vid->displine; - for (c = 0; c < 8; c++) { - if ((vid->cgamode & 0x12) == 0x12) { - buffer->line[vid->displine][c] = (vid->border & 15) + 16; - if (vid->cgamode & 1) - buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = 0; - else - buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = 0; - } else { - buffer->line[vid->displine][c] = (vid->cgacol & 15) + 16; - if (vid->cgamode & 1) - buffer->line[vid->displine][c + (vid->crtc[1] << 3) + 8] = (vid->cgacol & 15) + 16; - else - buffer->line[vid->displine][c + (vid->crtc[1] << 4) + 8] = (vid->cgacol & 15) + 16; - } - } - if (vid->cgamode & 1) { - for (x = 0; x < 80; x++) { - chr = vid->vram[ ((vid->ma << 1) & 0x3fff)]; - attr = vid->vram[(((vid->ma << 1) + 1) & 0x3fff)]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->cgamode & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((vid->blink & 16) && (attr & 0x80) && !drawcursor) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - if (drawcursor) { - for (c = 0; c < 8; c++) - buffer->line[vid->displine][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - buffer->line[vid->displine][(x << 3) + c + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - vid->ma++; - } - } else if (! (vid->cgamode & 2)) { - for (x = 0; x < 40; x++) { - chr = vid->vram[((vid->ma << 1) & 0x3fff)]; - attr = vid->vram[(((vid->ma << 1) + 1) & 0x3fff)]; - drawcursor = ((vid->ma == ca) && vid->con && vid->cursoron); - if (vid->cgamode & 0x20) { - cols[1] = (attr & 15) + 16; - cols[0] = ((attr >> 4) & 7) + 16; - if ((vid->blink & 16) && (attr & 0x80)) - cols[1] = cols[0]; - } else { - cols[1] = (attr & 15) + 16; - cols[0] = (attr >> 4) + 16; - } - vid->ma++; - if (drawcursor) { - for (c = 0; c < 8; c++) - buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = - buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0] ^ 15; - } else { - for (c = 0; c < 8; c++) - buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = - buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[(fontdat[chr][vid->sc & 7] & (1 << (c ^ 7))) ? 1 : 0]; - } - } - } else if (! (vid->cgamode & 16)) { - cols[0] = (vid->cgacol & 15) | 16; - col = (vid->cgacol & 16) ? 24 : 16; - if (vid->cgamode & 4) { - cols[1] = col | 3; - cols[2] = col | 4; - cols[3] = col | 7; - } else if (vid->cgacol & 32) { - cols[1] = col | 3; - cols[2] = col | 5; - cols[3] = col | 7; - } else { - cols[1] = col | 2; - cols[2] = col | 4; - cols[3] = col | 6; - } - for (x = 0; x < 40; x++) { - dat = (vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000)] << 8) | vid->vram[((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000) + 1]; - vid->ma++; - for (c = 0; c < 8; c++) { - buffer->line[vid->displine][(x << 4) + (c << 1) + 8] = - buffer->line[vid->displine][(x << 4) + (c << 1) + 1 + 8] = cols[dat >> 14]; - dat <<= 2; - } - } - } else { - for (x = 0; x < 40; x++) { - ca = ((vid->ma << 1) & 0x1fff) + ((vid->sc & 1) * 0x2000); - dat = (vid->vram[ca] << 8) | vid->vram[ca + 1]; - dat2 = (vid->vram[ca + 0x4000] << 8) | vid->vram[ca + 0x4001]; - dat3 = (vid->vram[ca + 0x8000] << 8) | vid->vram[ca + 0x8001]; - dat4 = (vid->vram[ca + 0xc000] << 8) | vid->vram[ca + 0xc001]; - - vid->ma++; - for (c = 0; c < 16; c++) { - buffer->line[vid->displine][(x << 4) + c + 8] = (((dat >> 15) | ((dat2 >> 15) << 1) | ((dat3 >> 15) << 2) | ((dat4 >> 15) << 3)) & (vid->cgacol & 15)) + 16; - dat <<= 1; - dat2 <<= 1; - dat3 <<= 1; - dat4 <<= 1; - } - } - } - } else { - cols[0] = ((vid->cgamode & 0x12) == 0x12) ? 0 : (vid->cgacol & 15) + 16; - if (vid->cgamode & 1) - hline(buffer, 0, vid->displine, (vid->crtc[1] << 3) + 16, cols[0]); - else - hline(buffer, 0, vid->displine, (vid->crtc[1] << 4) + 16, cols[0]); - } - - vid->sc = oldsc; - if (vid->vsynctime) - vid->stat |= 8; - vid->displine++; - if (vid->displine >= 360) - vid->displine = 0; - } else { - vid->vidtime += vid->dispontime; - if ((vid->lastline - vid->firstline) == 199) - vid->dispon = 0; /*Amstrad PC1512 always displays 200 lines, regardless of CRTC settings*/ - if (vid->dispon) - vid->stat &= ~1; - vid->linepos = 0; - if (vid->vsynctime) { - vid->vsynctime--; - if (! vid->vsynctime) - vid->stat &= ~8; - } - if (vid->sc == (vid->crtc[11] & 31)) { - vid->con = 0; - vid->coff = 1; - } - if (vid->vadj) { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - vid->vadj--; - if (! vid->vadj) { - vid->dispon = 1; - vid->ma = vid->maback = (vid->crtc[13] | (vid->crtc[12] << 8)) & 0x3fff; - vid->sc = 0; - } - } else if (vid->sc == vid->crtc[9]) { - vid->maback = vid->ma; - vid->sc = 0; - vid->vc++; - vid->vc &= 127; - - if (vid->displine == 32) { - vid->vc = 0; - vid->vadj = 6; - if ((vid->crtc[10] & 0x60) == 0x20) - vid->cursoron = 0; - else - vid->cursoron = vid->blink & 16; - } - - if (vid->displine >= 262) { - vid->dispon = 0; - vid->displine = 0; - vid->vsynctime = 46; - - if (vid->cgamode&1) - x = (vid->crtc[1] << 3) + 16; - else - x = (vid->crtc[1] << 4) + 16; - vid->lastline++; - - if ((x != xsize) || ((vid->lastline - vid->firstline) != ysize) || video_force_resize_get()) { - xsize = x; - ysize = vid->lastline - vid->firstline; - if (xsize < 64) xsize = 656; - if (ysize < 32) ysize = 200; - set_screen_size(xsize, (ysize << 1) + 16); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - video_blit_memtoscreen_8(0, vid->firstline - 4, 0, (vid->lastline - vid->firstline) + 8, xsize, (vid->lastline - vid->firstline) + 8); - - video_res_x = xsize - 16; - video_res_y = ysize; - if (vid->cgamode & 1) { - video_res_x /= 8; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->cgamode & 2)) { - video_res_x /= 16; - video_res_y /= vid->crtc[9] + 1; - video_bpp = 0; - } else if (! (vid->cgamode & 16)) { - video_res_x /= 2; - video_bpp = 2; - } else { - video_bpp = 4; - } - - vid->firstline = 1000; - vid->lastline = 0; - vid->blink++; - } - } else { - vid->sc++; - vid->sc &= 31; - vid->ma = vid->maback; - } - if (vid->sc == (vid->crtc[10] & 31)) - vid->con = 1; - } -} - - -static void -vid_init_1512(amstrad_t *ams) -{ - amsvid_t *vid; - - /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); - - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_pc1512); - - vid->vram = malloc(0x10000); - vid->cgacol = 7; - vid->cgamode = 0x12; - - timer_add(vid_poll_1512, &vid->vidtime, TIMER_ALWAYS_ENABLED, vid); - mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - vid_read_1512, NULL, NULL, vid_write_1512, NULL, NULL, - NULL, 0, vid); - io_sethandler(0x03d0, 16, - vid_in_1512, NULL, NULL, vid_out_1512, NULL, NULL, vid); - - overscan_x = overscan_y = 16; - - ams->vid = vid; -} - - -static void -vid_close_1512(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - free(vid->vram); - - free(vid); -} - - -static void -vid_speed_change_1512(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - recalc_timings_1512(vid); -} - - -static const device_t vid_1512_device = { - "Amstrad PC1512 (video)", - 0, 0, - NULL, vid_close_1512, NULL, - NULL, - vid_speed_change_1512, - NULL -}; - - -static void -recalc_timings_1640(amsvid_t *vid) -{ - cga_recalctimings(&vid->cga); - ega_recalctimings(&vid->ega); - - if (vid->cga_enabled) { - overscan_x = overscan_y = 16; - - vid->dispontime = vid->cga.dispontime; - vid->dispofftime = vid->cga.dispofftime; - } else { - overscan_x = 16; overscan_y = 28; - - vid->dispontime = vid->ega.dispontime; - vid->dispofftime = vid->ega.dispofftime; - } -} - - -static void -vid_out_1640(uint16_t addr, uint8_t val, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - switch (addr) { - case 0x03db: - vid->cga_enabled = val & 0x40; - if (vid->cga_enabled) { - mem_mapping_enable(&vid->cga.mapping); - mem_mapping_disable(&vid->ega.mapping); - } else { - mem_mapping_disable(&vid->cga.mapping); - switch (vid->ega.gdcreg[6] & 0xc) { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xa0000, 0x20000); - break; - - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xa0000, 0x10000); - break; - - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xb0000, 0x08000); - break; - - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&vid->ega.mapping, - 0xb8000, 0x08000); - break; - } - } - return; - } - - if (vid->cga_enabled) - cga_out(addr, val, &vid->cga); - else - ega_out(addr, val, &vid->ega); -} - - -static uint8_t -vid_in_1640(uint16_t addr, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - switch (addr) { - } - - if (vid->cga_enabled) - return(cga_in(addr, &vid->cga)); - else - return(ega_in(addr, &vid->ega)); -} - - -static void -vid_poll_1640(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - if (vid->cga_enabled) { - overscan_x = overscan_y = 16; - - vid->cga.vidtime = vid->vidtime; - cga_poll(&vid->cga); - vid->vidtime = vid->cga.vidtime; - } else { - overscan_x = 16; overscan_y = 28; - - vid->ega.vidtime = vid->vidtime; - ega_poll(&vid->ega); - vid->vidtime = vid->ega.vidtime; - } -} - - -static void -vid_init_1640(amstrad_t *ams) -{ - amsvid_t *vid; - - /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); - - video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_pc1640); - - rom_init(&vid->bios_rom, L"roms/machines/pc1640/40100", - 0xc0000, 0x8000, 0x7fff, 0, 0); - - ega_init(&vid->ega, 9, 0); - vid->cga.vram = vid->ega.vram; - vid->cga_enabled = 1; - cga_init(&vid->cga); - - mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, &vid->cga); - mem_mapping_add(&vid->ega.mapping, 0, 0, - ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, 0, &vid->ega); - io_sethandler(0x03a0, 64, - vid_in_1640, NULL, NULL, vid_out_1640, NULL, NULL, vid); - - timer_add(vid_poll_1640, &vid->vidtime, TIMER_ALWAYS_ENABLED, vid); - - overscan_x = overscan_y = 16; - - ams->vid = vid; -} - - -static void -vid_close_1640(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - free(vid->ega.vram); - - free(vid); -} - - -static void -vid_speed_changed_1640(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - recalc_timings_1640(vid); -} - - -static const device_t vid_1640_device = { - "Amstrad PC1640 (video)", - 0, 0, - NULL, vid_close_1640, NULL, - NULL, - vid_speed_changed_1640, - NULL -}; - - -static void -vid_out_200(uint16_t addr, uint8_t val, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - cga_t *cga = &vid->cga; - uint8_t old; - - switch (addr) { - case 0x03d5: - if (!(vid->plane_read & 0x40) && cga->crtcreg <= 11) { - if (vid->plane_read & 0x80) - nmi = 1; - - vid->plane_write = 0x20 | (cga->crtcreg & 0x1f); - vid->border = val; - return; - } - old = cga->crtc[cga->crtcreg]; - cga->crtc[cga->crtcreg] = val & crtc_mask[cga->crtcreg]; - if (old != val) { - if (cga->crtcreg < 0xe || cga->crtcreg > 0x10) { - fullchange = changeframecount; - cga_recalctimings(cga); - } - } - return; - - case 0x03d8: - old = cga->cgamode; - cga->cgamode = val; - if ((cga->cgamode ^ old) & 3) - cga_recalctimings(cga); - vid->plane_write |= 0x80; - if (vid->plane_read & 0x80) - nmi = 1; - return; - - case 0x03de: - vid->plane_read = val; - vid->plane_write = 0x1f; - if (val & 0x80) - vid->plane_write |= 0x40; - return; - } - - cga_out(addr, val, cga); -} - - -static uint8_t -vid_in_200(uint16_t addr, void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - cga_t *cga = &vid->cga; - uint8_t ret; - - switch (addr) { - case 0x03d8: - return(cga->cgamode); - - case 0x03dd: - ret = vid->plane_write; - vid->plane_write &= 0x1f; - nmi = 0; - return(ret); - - case 0x03de: - return((vid->plane_read & 0xc7) | 0x10); /*External CGA*/ - - case 0x03df: - return(vid->border); - } - - return(cga_in(addr, cga)); -} - - -static void -vid_init_200(amstrad_t *ams) -{ - amsvid_t *vid; - cga_t *cga; - - /* Allocate a video controller block. */ - vid = (amsvid_t *)malloc(sizeof(amsvid_t)); - memset(vid, 0x00, sizeof(amsvid_t)); - - video_inform(VIDEO_FLAG_TYPE_CGA, &timing_pc200); - - cga = &vid->cga; - cga->vram = malloc(0x4000); - cga_init(cga); - - mem_mapping_add(&vid->cga.mapping, 0xb8000, 0x08000, - cga_read, NULL, NULL, cga_write, NULL, NULL, NULL, 0, cga); - io_sethandler(0x03d0, 16, - vid_in_200, NULL, NULL, vid_out_200, NULL, NULL, vid); - - timer_add(cga_poll, &cga->vidtime, TIMER_ALWAYS_ENABLED, cga); - - overscan_x = overscan_y = 16; - - ams->vid = vid; -} - - -static void -vid_close_200(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - free(vid->cga.vram); - - free(vid); -} - - -static void -vid_speed_changed_200(void *priv) -{ - amsvid_t *vid = (amsvid_t *)priv; - - cga_recalctimings(&vid->cga); -} - - -static const device_t vid_200_device = { - "Amstrad PC200 (video)", - 0, 0, - NULL, vid_close_200, NULL, - NULL, - vid_speed_changed_200, - NULL -}; - - -static void -ms_write(uint16_t addr, uint8_t val, void *priv) -{ - amstrad_t *ams = (amstrad_t *)priv; - - if (addr == 0x78) - ams->mousex = 0; - else - ams->mousey = 0; -} - - -static uint8_t -ms_read(uint16_t addr, void *priv) -{ - amstrad_t *ams = (amstrad_t *)priv; - - if (addr == 0x78) - return(ams->mousex); - - return(ams->mousey); -} - - -static int -ms_poll(int x, int y, int z, int b, void *priv) -{ - amstrad_t *ams = (amstrad_t *)priv; - - ams->mousex += x; - ams->mousey -= y; - - if ((b & 1) && !(ams->oldb & 1)) - keyboard_send(0x7e); - if ((b & 2) && !(ams->oldb & 2)) - keyboard_send(0x7d); - if (!(b & 1) && (ams->oldb & 1)) - keyboard_send(0xfe); - if (!(b & 2) && (ams->oldb & 2)) - keyboard_send(0xfd); - - ams->oldb = b; - - return(0); -} - - -static void -kbd_adddata(uint16_t val) -{ - key_queue[key_queue_end] = val; - amstrad_log("keyboard_amstrad : %02X added to key queue at %i\n", - val, key_queue_end); - key_queue_end = (key_queue_end + 1) & 0xf; -} - - -static void -kbd_adddata_ex(uint16_t val) -{ - kbd_adddata_process(val, kbd_adddata); -} - - -static void -kbd_write(uint16_t port, uint8_t val, void *priv) -{ - amstrad_t *ams = (amstrad_t *)priv; - - amstrad_log("keyboard_amstrad : write %04X %02X %02X\n", port, val, ams->pb); - - switch (port) { - case 0x61: - /* - * PortB - System Control. - * - * 7 Enable Status-1/Disable Keyboard Code on Port A. - * 6 Enable incoming Keyboard Clock. - * 5 Prevent external parity errors from causing NMI. - * 4 Disable parity checking of on-board system Ram. - * 3 Undefined (Not Connected). - * 2 Enable Port C LSB / Disable MSB. (See 1.8.3) - * 1 Speaker Drive. - * 0 8253 GATE 2 (Speaker Modulate). - * - * This register is controlled by BIOS and/or ROS. - */ - amstrad_log("AMSkb: write PB %02x (%02x)\n", val, ams->pb); - if (!(ams->pb & 0x40) && (val & 0x40)) { /*Reset keyboard*/ - amstrad_log("AMSkb: reset keyboard\n"); - kbd_adddata(0xaa); - } - ams->pb = val; - ppi.pb = val; - - timer_process(); - timer_update_outstanding(); - - speaker_update(); - speaker_gated = val & 0x01; - speaker_enable = val & 0x02; - if (speaker_enable) - was_speaker_enable = 1; - pit_set_gate(&pit, 2, val & 0x01); - - if (val & 0x80) { - /* Keyboard enabled, so enable PA reading. */ - ams->pa = 0x00; - } - break; - - case 0x63: - break; - - case 0x64: - ams->stat1 = val; - break; - - case 0x65: - ams->stat2 = val; - break; - - case 0x66: - pc_reset(1); - break; - - default: - amstrad_log("AMSkb: bad keyboard write %04X %02X\n", port, val); - } -} - - -static uint8_t -kbd_read(uint16_t port, void *priv) -{ - amstrad_t *ams = (amstrad_t *)priv; - uint8_t ret = 0xff; - - switch (port) { - case 0x60: - if (ams->pb & 0x80) { - /* - * PortA - System Status 1 - * - * 7 Always 0 (KBD7) - * 6 Second Floppy disk drive installed (KBD6) - * 5 DDM1 - Default Display Mode bit 1 (KBD5) - * 4 DDM0 - Default Display Mode bit 0 (KBD4) - * 3 Always 1 (KBD3) - * 2 Always 1 (KBD2) - * 1 8087 NDP installed (KBD1) - * 0 Always 1 (KBD0) - * - * DDM00 - * 00 unknown, external color? - * 01 Color,alpha,40x25, bright white on black. - * 10 Color,alpha,80x25, bright white on black. - * 11 External Monochrome,80x25. - * - * Following a reset, the hardware selects VDU mode - * 2. The ROS then sets the initial VDU state based - * on the DDM value. - */ - ret = (0x0d | ams->stat1) & 0x7f; - } else { - ret = ams->pa; - if (key_queue_start == key_queue_end) { - ams->wantirq = 0; - } else { - ams->key_waiting = key_queue[key_queue_start]; - key_queue_start = (key_queue_start + 1) & 0xf; - ams->wantirq = 1; - } - } - break; - - case 0x61: - ret = ams->pb; - break; - - case 0x62: - /* - * PortC - System Status 2. - * - * 7 On-board system RAM parity error. - * 6 External parity error (I/OCHCK from expansion bus). - * 5 8253 PIT OUT2 output. - * 4 Undefined (Not Connected). - *------------------------------------------- - * LSB MSB (depends on PB2) - *------------------------------------------- - * 3 RAM3 Undefined - * 2 RAM2 Undefined - * 1 RAM1 Undefined - * 0 RAM0 RAM4 - * - * PC7 is forced to 0 when on-board system RAM parity - * checking is disabled by PB4. - * - * RAM4:0 - * 01110 512K bytes on-board. - * 01111 544K bytes (32K external). - * 10000 576K bytes (64K external). - * 10001 608K bytes (96K external). - * 10010 640K bytes (128K external or fitted on-board). - */ - if (ams->pb & 0x04) - ret = ams->stat2 & 0x0f; - else - ret = ams->stat2 >> 4; - ret |= (ppispeakon ? 0x20 : 0); - if (nmi) - ret |= 0x40; - break; - - default: - amstrad_log("AMDkb: bad keyboard read %04X\n", port); - } - - return(ret); -} - - -static void -kbd_poll(void *priv) -{ - amstrad_t *ams = (amstrad_t *)priv; - - keyboard_delay += (1000 * TIMER_USEC); - - if (ams->wantirq) { - ams->wantirq = 0; - ams->pa = ams->key_waiting; - picint(2); - amstrad_log("keyboard_amstrad : take IRQ\n"); - } - - if (key_queue_start != key_queue_end && !ams->pa) { - ams->key_waiting = key_queue[key_queue_start]; - amstrad_log("Reading %02X from the key queue at %i\n", - ams->key_waiting, key_queue_start); - key_queue_start = (key_queue_start + 1) & 0xf; - ams->wantirq = 1; - } -} - - -static void -ams_write(uint16_t port, uint8_t val, void *priv) -{ - amstrad_t *ams = (amstrad_t *)priv; - - switch (port) { - case 0xdead: - ams->dead = val; - break; - } -} - - -static uint8_t -ams_read(uint16_t port, void *priv) -{ - amstrad_t *ams = (amstrad_t *)priv; - uint8_t ret = 0xff; - - switch (port) { - case 0x0379: /* printer control, also set LK1-3. - * 0 English Language. - * 1 German Language. - * 2 French Language. - * 3 Spanish Language. - * 4 Danish Language. - * 5 Swedish Language. - * 6 Italian Language. - * 7 Diagnostic Mode. - */ - ret = 0x02; /* ENGLISH. no Diags mode */ - break; - - case 0x037a: /* printer status */ - switch(romset) { - case ROM_PC1512: - ret = 0x20; - break; - - case ROM_PC200: - ret = 0x80; - break; - - default: - ret = 0x00; - } - break; - - case 0xdead: - ret = ams->dead; - break; - } - - return(ret); -} - - -void -machine_amstrad_init(const machine_t *model) -{ - amstrad_t *ams; - - ams = (amstrad_t *)malloc(sizeof(amstrad_t)); - memset(ams, 0x00, sizeof(amstrad_t)); - - device_add(&amstrad_nvr_device); - - machine_common_init(model); - - nmi_init(); - - lpt2_remove_ams(); - - io_sethandler(0x0379, 2, - ams_read, NULL, NULL, NULL, NULL, NULL, ams); - - io_sethandler(0xdead, 1, - ams_read, NULL, NULL, ams_write, NULL, NULL, ams); - - io_sethandler(0x0078, 1, - ms_read, NULL, NULL, ms_write, NULL, NULL, ams); - - io_sethandler(0x007a, 1, - ms_read, NULL, NULL, ms_write, NULL, NULL, ams); - -// device_add(&fdc_at_actlow_device); - - switch(romset) { - case ROM_PC1512: - device_add(&fdc_xt_device); - break; - - case ROM_PC1640: - device_add(&fdc_xt_device); - break; - - case ROM_PC200: - device_add(&fdc_xt_device); - break; - - case ROM_PC2086: - device_add(&fdc_at_actlow_device); - break; - - case ROM_PC3086: - device_add(&fdc_at_actlow_device); - break; - - case ROM_MEGAPC: - device_add(&fdc_at_actlow_device); - break; - } - - if (gfxcard == GFX_INTERNAL) switch(romset) { - case ROM_PC1512: - loadfont(L"roms/machines/pc1512/40078", 2); - vid_init_1512(ams); - device_add_ex(&vid_1512_device, ams->vid); - break; - - case ROM_PC1640: - vid_init_1640(ams); - device_add_ex(&vid_1640_device, ams->vid); - break; - - case ROM_PC200: - loadfont(L"roms/machines/pc200/40109.bin", 1); - vid_init_200(ams); - device_add_ex(&vid_200_device, ams->vid); - break; - - case ROM_PC2086: - device_add(¶dise_pvga1a_pc2086_device); - break; - - case ROM_PC3086: - device_add(¶dise_pvga1a_pc3086_device); - break; - - case ROM_MEGAPC: - device_add(¶dise_wd90c11_megapc_device); - break; - } - - /* Initialize the (custom) keyboard/mouse interface. */ - ams->wantirq = 0; - io_sethandler(0x0060, 7, - kbd_read, NULL, NULL, kbd_write, NULL, NULL, ams); - timer_add(kbd_poll, &keyboard_delay, TIMER_ALWAYS_ENABLED, ams); - keyboard_set_table(scancode_xt); - keyboard_send = kbd_adddata_ex; - keyboard_scan = 1; - - /* Tell mouse driver about our internal mouse. */ - mouse_reset(); - mouse_set_poll(ms_poll, ams); - - if (joystick_type != 7) - device_add(&gameport_device); -} diff --git a/src/machine/m_at.c$ b/src/machine/m_at.c$ deleted file mode 100644 index 6b1cc3c73..000000000 --- a/src/machine/m_at.c$ +++ /dev/null @@ -1,111 +0,0 @@ -#include -#include -#include -#include -#include "../86box.h" -#include "../pic.h" -#include "../pit.h" -#include "../dma.h" -#include "../mem.h" -#include "../device.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../nvr.h" -#include "../game/gameport.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../disk/hdc.h" -#include "machine.h" - - -void -machine_at_common_init(const machine_t *model) -{ - machine_common_init(model); - - pit_set_out_func(&pit, 1, pit_refresh_timer_at); - pic2_init(); - dma16_init(); - - if (lpt_enabled) - lpt2_remove(); - - device_add(&at_nvr_device); - - if (joystick_type != 7) - device_add(&gameport_device); -} - - -void -machine_at_init(const machine_t *model) -{ - machine_at_common_init(model); - - device_add(&keyboard_at_device); -} - - -void -machine_at_ps2_init(const machine_t *model) -{ - machine_at_common_init(model); - - device_add(&keyboard_ps2_device); -} - - -void -machine_at_common_ide_init(const machine_t *model) -{ - machine_at_common_init(model); - - device_add(&ide_isa_2ch_opt_device); -} - - -void -machine_at_ide_init(const machine_t *model) -{ - machine_at_init(model); - - device_add(&ide_isa_2ch_opt_device); -} - - -void -machine_at_ps2_ide_init(const machine_t *model) -{ - machine_at_ps2_init(model); - - device_add(&ide_isa_2ch_opt_device); -} - - -void -machine_at_top_remap_init(const machine_t *model) -{ - machine_at_init(model); - - if (mem_size >= 1024) - mem_remap_top_384k(); -} - - -void -machine_at_ide_top_remap_init(const machine_t *model) -{ - machine_at_ide_init(model); - - if (mem_size >= 1024) - mem_remap_top_384k(); -} - - -void -machine_at_ibm_init(const machine_t *model) -{ - machine_at_top_remap_init(model); - - device_add(&fdc_at_device); -} diff --git a/src/machine/m_at_headland - Cópia.c b/src/machine/m_at_headland - Cópia.c deleted file mode 100644 index b9634f0ed..000000000 --- a/src/machine/m_at_headland - Cópia.c +++ /dev/null @@ -1,578 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -#include -#include -#include -#include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../cpu/x86.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../keyboard.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "machine.h" -#include "../video/video.h" -#include "../video/vid_et4000.h" -#include "../video/vid_oak_oti.h" - - -static int headland_index; -static uint8_t headland_regs[256]; -static uint8_t headland_port_92 = 0xFC, headland_ems_mar = 0, headland_cri = 0; -static uint8_t headland_regs_cr[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; -static uint16_t headland_ems_mr[64]; - -static mem_mapping_t headland_low_mapping; -static mem_mapping_t headland_ems_mapping[64]; -static mem_mapping_t headland_mid_mapping; -static mem_mapping_t headland_high_mapping; -static mem_mapping_t headland_4000_9FFF_mapping[24]; - -/* TODO - Headland chipset's memory address mapping emulation isn't fully implemented yet, - so memory configuration is hardcoded now. */ -static int headland_mem_conf_cr0[41] = { 0x00, 0x00, 0x20, 0x40, 0x60, 0xA0, 0x40, 0xE0, - 0xA0, 0xC0, 0xE0, 0xE0, 0xC0, 0xE0, 0xE0, 0xE0, - 0xE0, 0x20, 0x40, 0x40, 0xA0, 0xC0, 0xE0, 0xE0, - 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, - 0x20, 0x40, 0x60, 0x60, 0xC0, 0xE0, 0xE0, 0xE0, - 0xE0 }; -static int headland_mem_conf_cr1[41] = { 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, - 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, - 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, - 0x40 }; - - -static uint32_t -get_headland_addr(uint32_t addr, uint16_t *mr) -{ - if (mr && (headland_regs_cr[0] & 2) && (*mr & 0x200)) { - addr = (addr & 0x3fff) | ((*mr & 0x1F) << 14); - - if (headland_regs_cr[1] & 0x40) { - if ((headland_regs_cr[4] & 0x80) && (headland_regs_cr[6] & 1)) { - if (headland_regs_cr[0] & 0x80) { - addr |= (*mr & 0x60) << 14; - if (*mr & 0x100) - addr += ((*mr & 0xC00) << 13) + (((*mr & 0x80) + 0x80) << 15); - else - addr += (*mr & 0x80) << 14; - } else if (*mr & 0x100) - addr += ((*mr & 0xC00) << 13) + (((*mr & 0x80) + 0x20) << 15); - else - addr += (*mr & 0x80) << 12; - } else if (headland_regs_cr[0] & 0x80) - addr |= (*mr & 0x100) ? ((*mr & 0x80) + 0x400) << 12 : (*mr & 0xE0) << 14; - else - addr |= (*mr & 0x100) ? ((*mr & 0xE0) + 0x40) << 14 : (*mr & 0x80) << 12; - } else { - if ((headland_regs_cr[4] & 0x80) && (headland_regs_cr[6] & 1)) { - if (headland_regs_cr[0] & 0x80) { - addr |= ((*mr & 0x60) << 14); - if (*mr & 0x180) - addr += ((*mr & 0xC00) << 13) + (((*mr & 0x180) - 0x60) << 16); - } else - addr |= ((*mr & 0x60) << 14) | ((*mr & 0x180) << 16) | ((*mr & 0xC00) << 13); - } else if (headland_regs_cr[0] & 0x80) - addr |= (*mr & 0x1E0) << 14; - else - addr |= (*mr & 0x180) << 12; - } - } else if (mr == NULL && (headland_regs_cr[0] & 4) == 0 && mem_size >= 1024 && addr >= 0x100000) - addr -= 0x60000; - - return addr; -} - - -static void -headland_set_global_EMS_state(int state) -{ - int i; - uint32_t base_addr, virt_addr; - - for (i=0; i<32; i++) { - base_addr = (i + 16) << 14; - if (i >= 24) - base_addr += 0x20000; - if ((state & 2) && (headland_ems_mr[((state & 1) << 5) | i] & 0x200)) { - virt_addr = get_headland_addr(base_addr, &headland_ems_mr[((state & 1) << 5) | i]); - if (i < 24) - mem_mapping_disable(&headland_4000_9FFF_mapping[i]); - mem_mapping_disable(&headland_ems_mapping[(((state ^ 1) & 1) << 5) | i]); - mem_mapping_enable(&headland_ems_mapping[((state & 1) << 5) | i]); - if (virt_addr < (mem_size << 10)) - mem_mapping_set_exec(&headland_ems_mapping[((state & 1) << 5) | i], ram + virt_addr); - else - mem_mapping_set_exec(&headland_ems_mapping[((state & 1) << 5) | i], NULL); - } else { - mem_mapping_set_exec(&headland_ems_mapping[((state & 1) << 5) | i], ram + base_addr); - mem_mapping_disable(&headland_ems_mapping[(((state ^ 1) & 1) << 5) | i]); - mem_mapping_disable(&headland_ems_mapping[((state & 1) << 5) | i]); - - if (i < 24) - mem_mapping_enable(&headland_4000_9FFF_mapping[i]); - } - } - flushmmucache(); -} - - -static void -headland_memmap_state_update(void) -{ - int i; - uint32_t addr; - - for (i=0; i<24; i++) { - addr = get_headland_addr(0x40000 + (i << 14), NULL); - mem_mapping_set_exec(&headland_4000_9FFF_mapping[i], addr < (mem_size << 10) ? ram + addr : NULL); - } - - mem_set_mem_state(0xA0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); - - if (mem_size > 640) { - if ((headland_regs_cr[0] & 4) == 0) { - mem_mapping_set_addr(&headland_mid_mapping, 0x100000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10); - mem_mapping_set_exec(&headland_mid_mapping, ram + 0xA0000); - if (mem_size > 1024) { - mem_mapping_set_addr(&headland_high_mapping, 0x160000, (mem_size - 1024) << 10); - mem_mapping_set_exec(&headland_high_mapping, ram + 0x100000); - } - } else { - mem_mapping_set_addr(&headland_mid_mapping, 0xA0000, mem_size > 1024 ? 0x60000 : (mem_size - 640) << 10); - mem_mapping_set_exec(&headland_mid_mapping, ram + 0xA0000); - if (mem_size > 1024) { - mem_mapping_set_addr(&headland_high_mapping, 0x100000, (mem_size - 1024) << 10); - mem_mapping_set_exec(&headland_high_mapping, ram + 0x100000); - } - } - } - - headland_set_global_EMS_state(headland_regs_cr[0] & 3); -} - - -static void -headland_write(uint16_t addr, uint8_t val, void *priv) -{ - uint8_t old_val, index; - uint32_t base_addr, virt_addr; - - switch(addr) { - case 0x22: - headland_index = val; - break; - - case 0x23: - old_val = headland_regs[headland_index]; - if ((headland_index == 0xc1) && !is486) - val = 0; - headland_regs[headland_index] = val; - if (headland_index == 0x82) { - shadowbios = val & 0x10; - shadowbios_write = !(val & 0x10); - if (shadowbios) - mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_DISABLED); - else - mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL); - } else if (headland_index == 0x87) { - if ((val & 1) && !(old_val & 1)) - softresetx86(); - } - break; - - case 0x92: - if ((mem_a20_alt ^ val) & 2) { - mem_a20_alt = val & 2; - mem_a20_recalc(); - } - if ((~headland_port_92 & val) & 1) { - softresetx86(); - cpu_set_edx(); - } - headland_port_92 = val | 0xFC; - break; - - case 0x1EC: - headland_ems_mr[headland_ems_mar & 0x3F] = val | 0xFF00; - index = headland_ems_mar & 0x1F; - base_addr = (index + 16) << 14; - if (index >= 24) - base_addr += 0x20000; - if ((headland_regs_cr[0] & 2) && ((headland_regs_cr[0] & 1) == ((headland_ems_mar & 0x20) >> 5))) { - virt_addr = get_headland_addr(base_addr, &headland_ems_mr[headland_ems_mar & 0x3F]); - if (index < 24) - mem_mapping_disable(&headland_4000_9FFF_mapping[index]); - if (virt_addr < (mem_size << 10)) - mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], ram + virt_addr); - else - mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], NULL); - mem_mapping_enable(&headland_ems_mapping[headland_ems_mar & 0x3F]); - flushmmucache(); - } - if (headland_ems_mar & 0x80) - headland_ems_mar++; - break; - - case 0x1ED: - headland_cri = val; - break; - - case 0x1EE: - headland_ems_mar = val; - break; - - case 0x1EF: - old_val = headland_regs_cr[headland_cri]; - switch(headland_cri) { - case 0: - headland_regs_cr[0] = (val & 0x1F) | headland_mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; - mem_set_mem_state(0xE0000, 0x10000, (val & 8 ? MEM_READ_INTERNAL : MEM_READ_EXTERNAL) | MEM_WRITE_DISABLED); - mem_set_mem_state(0xF0000, 0x10000, (val & 0x10 ? MEM_READ_INTERNAL: MEM_READ_EXTERNAL) | MEM_WRITE_DISABLED); - headland_memmap_state_update(); - break; - case 1: - headland_regs_cr[1] = (val & 0xBF) | headland_mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; - headland_memmap_state_update(); - break; - case 2: - case 3: - case 5: - headland_regs_cr[headland_cri] = val; - headland_memmap_state_update(); - break; - case 4: - headland_regs_cr[4] = (headland_regs_cr[4] & 0xF0) | (val & 0x0F); - if (val & 1) { - mem_mapping_disable(&bios_mapping[0]); - mem_mapping_disable(&bios_mapping[1]); - mem_mapping_disable(&bios_mapping[2]); - mem_mapping_disable(&bios_mapping[3]); - } else { - mem_mapping_enable(&bios_mapping[0]); - mem_mapping_enable(&bios_mapping[1]); - mem_mapping_enable(&bios_mapping[2]); - mem_mapping_enable(&bios_mapping[3]); - } - break; - case 6: - if (headland_regs_cr[4] & 0x80) { - headland_regs_cr[headland_cri] = (val & 0xFE) | (mem_size > 8192 ? 1 : 0); - headland_memmap_state_update(); - } - break; - default: - break; - } - break; - - default: - break; - } -} - - -static void -headland_writew(uint16_t addr, uint16_t val, void *priv) -{ - uint8_t index; - uint32_t base_addr, virt_addr; - - switch(addr) { - case 0x1EC: - headland_ems_mr[headland_ems_mar & 0x3F] = val; - index = headland_ems_mar & 0x1F; - base_addr = (index + 16) << 14; - if (index >= 24) - base_addr += 0x20000; - if ((headland_regs_cr[0] & 2) && (headland_regs_cr[0] & 1) == ((headland_ems_mar & 0x20) >> 5)) { - if(val & 0x200) { - virt_addr = get_headland_addr(base_addr, &headland_ems_mr[headland_ems_mar & 0x3F]); - if (index < 24) - mem_mapping_disable(&headland_4000_9FFF_mapping[index]); - if (virt_addr < (mem_size << 10)) - mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], ram + virt_addr); - else - mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], NULL); - mem_mapping_enable(&headland_ems_mapping[headland_ems_mar & 0x3F]); - } else { - mem_mapping_set_exec(&headland_ems_mapping[headland_ems_mar & 0x3F], ram + base_addr); - mem_mapping_disable(&headland_ems_mapping[headland_ems_mar & 0x3F]); - if (index < 24) - mem_mapping_enable(&headland_4000_9FFF_mapping[index]); - } - flushmmucache(); - } - if (headland_ems_mar & 0x80) - headland_ems_mar++; - break; - - default: - break; - } -} - - -static uint8_t -headland_read(uint16_t addr, void *priv) -{ - uint8_t val; - - switch(addr) { - case 0x22: - val = headland_index; - break; - - case 0x23: - if ((headland_index >= 0xc0 || headland_index == 0x20) && cpu_iscyrix) - val = 0xff; /*Don't conflict with Cyrix config registers*/ - else - val = headland_regs[headland_index]; - break; - - case 0x92: - val = headland_port_92 | 0xFC; - break; - - case 0x1EC: - val = headland_ems_mr[headland_ems_mar & 0x3F]; - if (headland_ems_mar & 0x80) - headland_ems_mar++; - break; - - case 0x1ED: - val = headland_cri; - break; - - case 0x1EE: - val = headland_ems_mar; - break; - - case 0x1EF: - switch(headland_cri) { - case 0: - val = (headland_regs_cr[0] & 0x1F) | headland_mem_conf_cr0[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; - break; - case 1: - val = (headland_regs_cr[1] & 0xBF) | headland_mem_conf_cr1[(mem_size > 640 ? mem_size : mem_size - 128) >> 9]; - break; - case 6: - if (headland_regs_cr[4] & 0x80) - val = (headland_regs_cr[6] & 0xFE) | (mem_size > 8192 ? 1 : 0); - else - val = 0; - break; - default: - val = headland_regs_cr[headland_cri]; - break; - } - break; - - default: - val = 0xFF; - break; - } - return val; -} - - -static uint16_t -headland_readw(uint16_t addr, void *priv) -{ - uint16_t val; - - switch(addr) { - case 0x1EC: - val = headland_ems_mr[headland_ems_mar & 0x3F] | ((headland_regs_cr[4] & 0x80) ? 0xF000 : 0xFC00); - if (headland_ems_mar & 0x80) - headland_ems_mar++; - break; - - default: - val = 0xFFFF; - break; - } - - return val; -} - - -static uint8_t -mem_read_headlandb(uint32_t addr, void *priv) -{ - uint8_t val = 0xff; - - addr = get_headland_addr(addr, priv); - if (addr < (mem_size << 10)) - val = ram[addr]; - - return val; -} - - -static uint16_t -mem_read_headlandw(uint32_t addr, void *priv) -{ - uint16_t val = 0xffff; - - addr = get_headland_addr(addr, priv); - if (addr < (mem_size << 10)) - val = *(uint16_t *)&ram[addr]; - - return val; -} - - -static uint32_t -mem_read_headlandl(uint32_t addr, void *priv) -{ - uint32_t val = 0xffffffff; - - addr = get_headland_addr(addr, priv); - if (addr < (mem_size << 10)) - val = *(uint32_t *)&ram[addr]; - - return val; -} - - -static void -mem_write_headlandb(uint32_t addr, uint8_t val, void *priv) -{ - addr = get_headland_addr(addr, priv); - if (addr < (mem_size << 10)) - ram[addr] = val; -} - - -static void -mem_write_headlandw(uint32_t addr, uint16_t val, void *priv) -{ - addr = get_headland_addr(addr, priv); - if (addr < (mem_size << 10)) - *(uint16_t *)&ram[addr] = val; -} - - -static void -mem_write_headlandl(uint32_t addr, uint32_t val, void *priv) -{ - addr = get_headland_addr(addr, priv); - if (addr < (mem_size << 10)) - *(uint32_t *)&ram[addr] = val; -} - - -static void -headland_init(int ht386) -{ - int i; - - for(i=0; i<8; i++) - headland_regs_cr[i] = 0; - headland_regs_cr[0] = 4; - - if (ht386) { - headland_regs_cr[4] = 0x20; - io_sethandler(0x0092, 0x0001, headland_read, NULL, NULL, headland_write, NULL, NULL, NULL); - } else - headland_regs_cr[4] = 0; - - io_sethandler(0x01EC, 0x0001, headland_read, headland_readw, NULL, headland_write, headland_writew, NULL, NULL); - io_sethandler(0x01ED, 0x0003, headland_read, NULL, NULL, headland_write, NULL, NULL, NULL); - - for(i=0; i<64; i++) - headland_ems_mr[i] = 0; - - mem_mapping_disable(&ram_low_mapping); - mem_mapping_disable(&ram_mid_mapping); - mem_mapping_disable(&ram_high_mapping); - - mem_mapping_add(&headland_low_mapping, 0, 0x40000, mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, ram, MEM_MAPPING_INTERNAL, NULL); - - if(mem_size > 640) { - mem_mapping_add(&headland_mid_mapping, 0xA0000, 0x60000, mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, ram + 0xA0000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&headland_mid_mapping); - } - - if(mem_size > 1024) { - mem_mapping_add(&headland_high_mapping, 0x100000, ((mem_size - 1024) * 1024), mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&headland_high_mapping); - } - - for (i = 0; i < 24; i++) { - mem_mapping_add(&headland_4000_9FFF_mapping[i], 0x40000 + (i << 14), 0x4000, mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, mem_size > 256 + (i << 4) ? ram + 0x40000 + (i << 14) : NULL, MEM_MAPPING_INTERNAL, NULL); - mem_mapping_enable(&headland_4000_9FFF_mapping[i]); - } - - for (i = 0; i < 64; i++) { - headland_ems_mr[i] = 0; - mem_mapping_add(&headland_ems_mapping[i], ((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14, 0x04000, mem_read_headlandb, mem_read_headlandw, mem_read_headlandl, mem_write_headlandb, mem_write_headlandw, mem_write_headlandl, ram + (((i & 31) + ((i & 31) >= 24 ? 24 : 16)) << 14), 0, &headland_ems_mr[i]); - mem_mapping_disable(&headland_ems_mapping[i]); - } - - headland_memmap_state_update(); -} - - -static void -machine_at_headland_common_init(int ht386) -{ - device_add(&keyboard_at_ami_device); - device_add(&fdc_at_device); - - headland_init(ht386); -} - -void -machine_at_headland_init(const machine_t *model) -{ - machine_at_common_ide_init(model); - - machine_at_headland_common_init(1); -} - - -const device_t * -at_tg286m_get_device(void) -{ - return &et4000k_tg286_isa_device; -} - - -void -machine_at_tg286m_init(const machine_t *model) -{ - machine_at_common_init(model); - - machine_at_headland_common_init(0); - - if (gfxcard == GFX_INTERNAL) - device_add(&et4000k_tg286_isa_device); -} - - -const device_t * -at_ama932j_get_device(void) -{ - return &oti067_ama932j_device; -} - - -void -machine_at_ama932j_init(const machine_t *model) -{ - machine_at_common_ide_init(model); - - machine_at_headland_common_init(1); - - if (gfxcard == GFX_INTERNAL) - device_add(&oti067_ama932j_device); -} diff --git a/src/machine/m_europc - Cópia.c b/src/machine/m_europc - Cópia.c deleted file mode 100644 index 6ef985396..000000000 --- a/src/machine/m_europc - Cópia.c +++ /dev/null @@ -1,767 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Schneider EuroPC system. - * - * NOTES: BIOS info (taken from MAME, thanks guys!!) - * - * f000:e107 bios checksum test - * memory test - * f000:e145 irq vector init - * f000:e156 - * f000:e169-d774 test of special registers 254/354 - * f000:e16c-e817 - * f000:e16f - * f000:ec08 test of special registers 800a rtc time - * or date error, rtc corrected - * f000:ef66 0xf - * f000:db3e 0x8..0xc - * f000:d7f8 - * f000:db5f - * f000:e172 - * f000:ecc5 801a video setup error - * f000:d6c9 copyright output - * f000:e1b7 - * f000:e1be DI bits set mean output text!!! (801a) - * f000: 0x8000 output - * 1 rtc error - * 2 rtc time or date error - * 4 checksum error in setup - * 8 rtc status corrected - * 10 video setup error - * 20 video ram bad - * 40 monitor type not recogniced - * 80 mouse port enabled - * 100 joystick port enabled - * f000:e1e2-dc0c CPU speed is 4.77 mhz - * f000:e1e5-f9c0 keyboard processor error - * f000:e1eb-c617 external lpt1 at 0x3bc - * f000:e1ee-e8ee external coms at - * - * Routines: - * f000:c92d output text at bp - * f000:db3e RTC read reg cl - * f000:e8ee piep - * f000:e95e RTC write reg cl - * polls until JIM 0xa is zero, - * output cl at jim 0xa - * write ah hinibble as lownibble into jim 0xa - * write ah lownibble into jim 0xa - * f000:ef66 RTC read reg cl - * polls until jim 0xa is zero, - * output cl at jim 0xa - * read low 4 nibble at jim 0xa - * read low 4 nibble at jim 0xa - * return first nibble<<4|second nibble in ah - * f000:f046 seldom compares ret - * f000:fe87 0 -> ds - * - * Memory: - * 0000:0469 bit 0: b0000 memory available - * bit 1: b8000 memory available - * 0000:046a: 00 jim 250 01 jim 350 - * - * WARNING THIS IS A WORK-IN-PROGRESS MODULE. USE AT OWN RISK. - * - * Version: @(#)europc.c 1.0.7 2018/08/04 - * - * Author: Fred N. van Kempen, - * - * Inspired by the "jim.c" file originally present, but a - * fully re-written module, based on the information from - * Schneider's schematics and technical manuals, and the - * input from people with real EuroPC hardware. - * - * Copyright 2017,2018 Fred N. van Kempen. - * - * Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain the entire - * above notice, this list of conditions and the following - * disclaimer. - * - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the - * following disclaimer in the documentation and/or other - * materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names - * of its contributors may be used to endorse or promote - * products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../nmi.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../keyboard.h" -#include "../mouse.h" -#include "../game/gameport.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../disk/hdc.h" -#include "../video/video.h" -#include "machine.h" - - -#define EUROPC_DEBUG 0 /* current debugging level */ - - -/* M3002 RTC chip registers. */ -#define MRTC_SECONDS 0x00 /* BCD, 00-59 */ -#define MRTC_MINUTES 0x01 /* BCD, 00-59 */ -#define MRTC_HOURS 0x02 /* BCD, 00-23 */ -#define MRTC_DAYS 0x03 /* BCD, 01-31 */ -#define MRTC_MONTHS 0x04 /* BCD, 01-12 */ -#define MRTC_YEARS 0x05 /* BCD, 00-99 (year only) */ -#define MRTC_WEEKDAY 0x06 /* BCD, 01-07 */ -#define MRTC_WEEKNO 0x07 /* BCD, 01-52 */ -#define MRTC_CONF_A 0x08 /* EuroPC config, binary */ -#define MRTC_CONF_B 0x09 /* EuroPC config, binary */ -#define MRTC_CONF_C 0x0a /* EuroPC config, binary */ -#define MRTC_CONF_D 0x0b /* EuroPC config, binary */ -#define MRTC_CONF_E 0x0c /* EuroPC config, binary */ -#define MRTC_CHECK_LO 0x0d /* Checksum, low byte */ -#define MRTC_CHECK_HI 0x0e /* Checksum, high byte */ -#define MRTC_CTRLSTAT 0x0f /* RTC control/status, binary */ - -typedef struct { - uint16_t jim; /* JIM base address */ - - uint8_t regs[16]; /* JIM internal regs (8) */ - - nvr_t nvr; /* NVR */ - uint8_t nvr_stat; - uint8_t nvr_addr; -} europc_t; - - -static europc_t europc; - - -#ifdef ENABLE_EUROPC_LOG -int europc_do_log = ENABLE_EUROPC_LOG; -#endif - - -static void -europc_log(const char *fmt, ...) -{ -#ifdef ENABLE_EUROPC_LOG - va_list ap; - - if (europc_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -/* - * This is called every second through the NVR/RTC hook. - * - * We fake a 'running' RTC by updating its registers on - * each passing second. Not exactly accurate, but good - * enough. - * - * Note that this code looks nasty because of all the - * BCD to decimal vv going on. - * - * FIXME: should we mark NVR as dirty? - */ -static void -europc_rtc_tick(nvr_t *nvr) -{ - uint8_t *regs; - int mon, yr; - - /* Only if RTC is running.. */ - regs = nvr->regs; - if (! (regs[MRTC_CTRLSTAT] & 0x01)) return; - - regs[MRTC_SECONDS] = RTC_BCDINC(nvr->regs[MRTC_SECONDS], 1); - if (regs[MRTC_SECONDS] >= RTC_BCD(60)) { - regs[MRTC_SECONDS] = RTC_BCD(0); - regs[MRTC_MINUTES] = RTC_BCDINC(regs[MRTC_MINUTES], 1); - if (regs[MRTC_MINUTES] >= RTC_BCD(60)) { - regs[MRTC_MINUTES] = RTC_BCD(0); - regs[MRTC_HOURS] = RTC_BCDINC(regs[MRTC_HOURS], 1); - if (regs[MRTC_HOURS] >= RTC_BCD(24)) { - regs[MRTC_HOURS] = RTC_BCD(0); - regs[MRTC_DAYS] = RTC_BCDINC(regs[MRTC_DAYS], 1); - mon = RTC_DCB(regs[MRTC_MONTHS]); - yr = RTC_DCB(regs[MRTC_YEARS]) + 1900; - if (RTC_DCB(regs[MRTC_DAYS]) > nvr_get_days(mon, yr)) { - regs[MRTC_DAYS] = RTC_BCD(1); - regs[MRTC_MONTHS] = RTC_BCDINC(regs[MRTC_MONTHS], 1); - if (regs[MRTC_MONTHS] > RTC_BCD(12)) { - regs[MRTC_MONTHS] = RTC_BCD(1); - regs[MRTC_YEARS] = RTC_BCDINC(regs[MRTC_YEARS], 1) & 0xff; - } - } - } - } - } -} - - -/* Get the current NVR time. */ -static void -rtc_time_get(uint8_t *regs, struct tm *tm) -{ - /* NVR is in BCD data mode. */ - tm->tm_sec = RTC_DCB(regs[MRTC_SECONDS]); - tm->tm_min = RTC_DCB(regs[MRTC_MINUTES]); - tm->tm_hour = RTC_DCB(regs[MRTC_HOURS]); - tm->tm_wday = (RTC_DCB(regs[MRTC_WEEKDAY]) - 1); - tm->tm_mday = RTC_DCB(regs[MRTC_DAYS]); - tm->tm_mon = (RTC_DCB(regs[MRTC_MONTHS]) - 1); - tm->tm_year = RTC_DCB(regs[MRTC_YEARS]); -#if USE_Y2K - tm->tm_year += (RTC_DCB(regs[MRTC_CENTURY]) * 100) - 1900; -#endif -} - - -/* Set the current NVR time. */ -static void -rtc_time_set(uint8_t *regs, struct tm *tm) -{ - /* NVR is in BCD data mode. */ - regs[MRTC_SECONDS] = RTC_BCD(tm->tm_sec); - regs[MRTC_MINUTES] = RTC_BCD(tm->tm_min); - regs[MRTC_HOURS] = RTC_BCD(tm->tm_hour); - regs[MRTC_WEEKDAY] = RTC_BCD(tm->tm_wday + 1); - regs[MRTC_DAYS] = RTC_BCD(tm->tm_mday); - regs[MRTC_MONTHS] = RTC_BCD(tm->tm_mon + 1); - regs[MRTC_YEARS] = RTC_BCD(tm->tm_year % 100); -#if USE_Y2K - regs[MRTC_CENTURY] = RTC_BCD((tm->tm_year+1900) / 100); -#endif -} - - -static void -rtc_start(nvr_t *nvr) -{ - struct tm tm; - - /* Initialize the internal and chip times. */ - if (time_sync & TIME_SYNC_ENABLED) { - /* Use the internal clock's time. */ - nvr_time_get(&tm); - rtc_time_set(nvr->regs, &tm); - } else { - /* Set the internal clock from the chip time. */ - rtc_time_get(nvr->regs, &tm); - nvr_time_set(&tm); - } - -#if 0 - /* Start the RTC - BIOS will do this. */ - nvr->regs[MRTC_CTRLSTAT] = 0x01; -#endif -} - - -/* Create a valid checksum for the current NVR data. */ -static uint8_t -rtc_checksum(uint8_t *ptr) -{ - uint8_t sum; - int i; - - /* Calculate all bytes with XOR. */ - sum = 0x00; - for (i=MRTC_CONF_A; i<=MRTC_CONF_E; i++) - sum += ptr[i]; - - return(sum); -} - - -/* Reset the machine's NVR to a sane state. */ -static void -rtc_reset(nvr_t *nvr) -{ - /* Initialize the RTC to a known state. */ - nvr->regs[MRTC_SECONDS] = RTC_BCD(0); /* seconds */ - nvr->regs[MRTC_MINUTES] = RTC_BCD(0); /* minutes */ - nvr->regs[MRTC_HOURS] = RTC_BCD(0); /* hours */ - nvr->regs[MRTC_DAYS] = RTC_BCD(1); /* days */ - nvr->regs[MRTC_MONTHS] = RTC_BCD(1); /* months */ - nvr->regs[MRTC_YEARS] = RTC_BCD(80); /* years */ - nvr->regs[MRTC_WEEKDAY] = RTC_BCD(1); /* weekday */ - nvr->regs[MRTC_WEEKNO] = RTC_BCD(1); /* weekno */ - - /* - * EuroPC System Configuration: - * - * [A] unknown - * - * [B] 7 1 bootdrive extern - * 0 bootdribe intern - * 6:5 11 invalid hard disk type - * 10 hard disk installed, type 2 - * 01 hard disk installed, type 1 - * 00 hard disk not installed - * 4:3 11 invalid external drive type - * 10 external drive 720K - * 01 external drive 360K - * 00 external drive disabled - * 2 unknown - * 1:0 11 invalid internal drive type - * 10 internal drive 360K - * 01 internal drive 720K - * 00 internal drive disabled - * - * [C] 7:6 unknown - * 5 monitor detection OFF - * 4 unknown - * 3:2 11 illegal memory size - * 10 512K - * 01 256K - * 00 640K - * 1:0 11 illegal game port - * 10 gameport as mouse port - * 01 gameport as joysticks - * 00 gameport disabled - * - * [D] 7:6 10 9MHz CPU speed - * 01 7MHz CPU speed - * 00 4.77 MHz CPU - * 5 unknown - * 4 external: color, internal: mono - * 3 unknown - * 2 internal video ON - * 1:0 11 mono - * 10 color80 - * 01 color40 - * 00 special (EGA,VGA etc) - * - * [E] 7:4 unknown - * 3:0 country (00=Deutschland, 0A=ASCII) - */ - nvr->regs[MRTC_CONF_A] = 0x00; /* CONFIG A */ - nvr->regs[MRTC_CONF_B] = 0x0A; /* CONFIG B */ - nvr->regs[MRTC_CONF_C] = 0x28; /* CONFIG C */ - nvr->regs[MRTC_CONF_D] = 0x12; /* CONFIG D */ - nvr->regs[MRTC_CONF_E] = 0x0A; /* CONFIG E */ - - nvr->regs[MRTC_CHECK_LO] = 0x00; /* checksum (LO) */ - nvr->regs[MRTC_CHECK_HI] = 0x00; /* checksum (HI) */ - - nvr->regs[MRTC_CTRLSTAT] = 0x01; /* status/control */ - - /* Generate a valid checksum. */ - nvr->regs[MRTC_CHECK_LO] = rtc_checksum(nvr->regs); -} - - -/* Execute a JIM control command. */ -static void -jim_set(europc_t *sys, uint8_t reg, uint8_t val) -{ - switch(reg) { - case 0: /* MISC control (WO) */ - // bit0: enable MOUSE - // bit1: enable joystick - break; - - case 2: /* AGA control */ - if (! (val & 0x80)) { - /* Reset AGA. */ - break; - } - - switch (val) { - case 0x1f: /* 0001 1111 */ - case 0x0b: /* 0000 1011 */ - //europc_jim.mode=AGA_MONO; - europc_log("EuroPC: AGA Monochrome mode!\n"); - break; - - case 0x18: /* 0001 1000 */ - case 0x1a: /* 0001 1010 */ - //europc_jim.mode=AGA_COLOR; - break; - - case 0x0e: /* 0000 1100 */ - /*80 columns? */ - europc_log("EuroPC: AGA 80-column mode!\n"); - break; - - case 0x0d: /* 0000 1011 */ - /*40 columns? */ - europc_log("EuroPC: AGA 40-column mode!\n"); - break; - - default: - //europc_jim.mode=AGA_OFF; - break; - } - break; - - case 4: /* CPU Speed control */ - switch(val & 0xc0) { - case 0x00: /* 4.77 MHz */ -// cpu_set_clockscale(0, 1.0/2); - break; - - case 0x40: /* 7.16 MHz */ -// cpu_set_clockscale(0, 3.0/4); - break; - - default: /* 9.54 MHz */ -// cpu_set_clockscale(0, 1);break; - break; - } - break; - - default: - break; - } - - sys->regs[reg] = val; -} - - -/* Write to one of the JIM registers. */ -static void -jim_write(uint16_t addr, uint8_t val, void *priv) -{ - europc_t *sys = (europc_t *)priv; - uint8_t b; - -#if EUROPC_DEBUG > 1 - europc_log("EuroPC: jim_wr(%04x, %02x)\n", addr, val); -#endif - - switch (addr & 0x000f) { - case 0x00: /* JIM internal registers (WRONLY) */ - case 0x01: - case 0x02: - case 0x03: - case 0x04: /* JIM internal registers (R/W) */ - case 0x05: - case 0x06: - case 0x07: - jim_set(sys, (addr & 0x07), val); - break; - - case 0x0a: /* M3002 RTC INDEX/DATA register */ - switch(sys->nvr_stat) { - case 0: /* save index */ - sys->nvr_addr = val & 0x0f; - sys->nvr_stat++; - break; - - case 1: /* save data HI nibble */ - b = sys->nvr.regs[sys->nvr_addr] & 0x0f; - b |= (val << 4); - sys->nvr.regs[sys->nvr_addr] = b; - sys->nvr_stat++; - nvr_dosave++; - break; - - case 2: /* save data LO nibble */ - b = sys->nvr.regs[sys->nvr_addr] & 0xf0; - b |= (val & 0x0f); - sys->nvr.regs[sys->nvr_addr] = b; - sys->nvr_stat = 0; - nvr_dosave++; - break; - } - break; - - default: - europc_log("EuroPC: invalid JIM write %02x, val %02x\n", addr, val); - break; - } -} - - -/* Read from one of the JIM registers. */ -static uint8_t -jim_read(uint16_t addr, void *priv) -{ - europc_t *sys = (europc_t *)priv; - uint8_t r = 0xff; - - switch (addr & 0x000f) { - case 0x00: /* JIM internal registers (WRONLY) */ - case 0x01: - case 0x02: - case 0x03: - r = 0x00; - break; - - case 0x04: /* JIM internal registers (R/W) */ - case 0x05: - case 0x06: - case 0x07: - r = sys->regs[addr & 0x07]; - break; - - case 0x0a: /* M3002 RTC INDEX/DATA register */ - switch(sys->nvr_stat) { - case 0: - r = 0x00; - break; - - case 1: /* read data HI nibble */ - r = (sys->nvr.regs[sys->nvr_addr] >> 4); - sys->nvr_stat++; - break; - - case 2: /* read data LO nibble */ - r = (sys->nvr.regs[sys->nvr_addr] & 0x0f); - sys->nvr_stat = 0; - break; - } - break; - - default: - europc_log("EuroPC: invalid JIM read %02x\n", addr); - break; - } - -#if EUROPC_DEBUG > 1 - europc_log("EuroPC: jim_rd(%04x): %02x\n", addr, r); -#endif - - return(r); -} - - -/* Initialize the mainboard 'device' of the machine. */ -static void * -europc_boot(const device_t *info) -{ - europc_t *sys = &europc; - uint8_t b; - -#if EUROPC_DEBUG - europc_log("EuroPC: booting mainboard..\n"); -#endif - - europc_log("EuroPC: NVR=[ %02x %02x %02x %02x %02x ] %sVALID\n", - sys->nvr.regs[MRTC_CONF_A], sys->nvr.regs[MRTC_CONF_B], - sys->nvr.regs[MRTC_CONF_C], sys->nvr.regs[MRTC_CONF_D], - sys->nvr.regs[MRTC_CONF_E], - (sys->nvr.regs[MRTC_CHECK_LO]!=rtc_checksum(sys->nvr.regs))?"IN":""); - - /* - * Now that we have initialized the NVR (either from file, - * or by setting it to defaults) we can start overriding it - * with values set by the user. - */ - b = (sys->nvr.regs[MRTC_CONF_D] & ~0x17); - switch(gfxcard) { - case GFX_CGA: /* Color, CGA */ - case GFX_COLORPLUS: /* Color, Hercules ColorPlus */ - b |= 0x12; /* external video, CGA80 */ - break; - - case GFX_MDA: /* Monochrome, MDA */ - case GFX_HERCULES: /* Monochrome, Hercules */ - case GFX_INCOLOR: /* Color, ? */ - b |= 0x03; /* external video, mono */ - break; - - default: /* EGA, VGA etc */ - b |= 0x10; /* external video, special */ - - } - sys->nvr.regs[MRTC_CONF_D] = b; - - /* Update the memory size. */ - b = (sys->nvr.regs[MRTC_CONF_C] & 0xf3); - switch(mem_size) { - case 256: - b |= 0x04; - break; - - case 512: - b |= 0x08; - break; - - case 640: - b |= 0x00; - break; - } - sys->nvr.regs[MRTC_CONF_C] = b; - - /* Update CPU speed. */ - b = (sys->nvr.regs[MRTC_CONF_D] & 0x3f); - switch(cpu) { - case 0: /* 8088, 4.77 MHz */ - b |= 0x00; - break; - - case 1: /* 8088, 7.15 MHz */ - b |= 0x40; - break; - - case 2: /* 8088, 9.56 MHz */ - b |= 0x80; - break; - } - sys->nvr.regs[MRTC_CONF_D] = b; - - /* Set up game port. */ - b = (sys->nvr.regs[MRTC_CONF_C] & 0xfc); - if (mouse_type == MOUSE_TYPE_LOGIBUS) { - b |= 0x01; /* enable port as MOUSE */ - } else if (joystick_type != 7) { - b |= 0x02; /* enable port as joysticks */ - device_add(&gameport_device); - } - sys->nvr.regs[MRTC_CONF_C] = b; - -#if 0 - /* Set up floppy types. */ - sys->nvr.regs[MRTC_CONF_B] = 0x2a; -#endif - - /* Validate the NVR checksum and save. */ - sys->nvr.regs[MRTC_CHECK_LO] = rtc_checksum(sys->nvr.regs); - nvr_dosave++; - - /* - * Allocate the system's I/O handlers. - * - * The first one is for the JIM. Note that although JIM usually - * resides at 0x0250, a special solder jumper on the mainboard - * (JS9) can be used to "move" it to 0x0350, to get it out of - * the way of other cards that need this range. - */ - io_sethandler(sys->jim, 16, - jim_read,NULL,NULL, jim_write,NULL,NULL, sys); - - /* Only after JIM has been initialized. */ - (void)device_add(&keyboard_xt_device); - - /* Enable and set up the FDC. */ - (void)device_add(&fdc_xt_device); - - /* - * Set up and enable the HD20 disk controller. - * - * We only do this if we have not configured another one. - */ - if (hdc_current == 1) - (void)device_add(&xta_hd20_device); - - return(sys); -} - - -static void -europc_close(void *priv) -{ - nvr_t *nvr = &europc.nvr; - - if (nvr->fn != NULL) - free(nvr->fn); -} - - -static const device_config_t europc_config[] = { - { - "js9", "JS9 Jumper (JIM)", CONFIG_INT, "", 0, - { - { - "Disabled (250h)", 0 - }, - { - "Enabled (350h)", 1 - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; - - -const device_t europc_device = { - "EuroPC System Board", - 0, 0, - europc_boot, europc_close, NULL, - NULL, NULL, NULL, - europc_config -}; - - -/* - * This function sets up the Scheider EuroPC machine. - * - * Its task is to allocate a clean machine data block, - * and then simply enable the mainboard "device" which - * allows it to reset (dev init) and configured by the - * user. - */ -void -machine_europc_init(const machine_t *model) -{ - machine_common_init(model); - nmi_init(); - - /* Clear the machine state. */ - memset(&europc, 0x00, sizeof(europc_t)); - europc.jim = 0x0250; - - mem_add_bios(); - - /* This is machine specific. */ - europc.nvr.size = model->nvrmask + 1; - europc.nvr.irq = -1; - - /* Set up any local handlers here. */ - europc.nvr.reset = rtc_reset; - europc.nvr.start = rtc_start; - europc.nvr.tick = europc_rtc_tick; - - /* Initialize the actual NVR. */ - nvr_init(&europc.nvr); - - /* Enable and set up the mainboard device. */ - device_add(&europc_device); -} diff --git a/src/machine/m_ps1 - Cópia.c b/src/machine/m_ps1 - Cópia.c deleted file mode 100644 index 4e7a555ae..000000000 --- a/src/machine/m_ps1 - Cópia.c +++ /dev/null @@ -1,572 +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. - * - * Emulation of the IBM PS/1 models 2011, 2121 and 2133. - * - * Model 2011: The initial model, using a 10MHz 80286. - * - * Model 2121: This is similar to model 2011 but some of the functionality - * has moved to a chip at ports 0xe0 (index)/0xe1 (data). The - * only functions I have identified are enables for the first - * 512K and next 128K of RAM, in bits 0 of registers 0 and 1 - * respectively. - * - * Port 0x105 has bit 7 forced high. Without this 128K of - * memory will be missed by the BIOS on cold boots. - * - * The reserved 384K is remapped to the top of extended memory. - * If this is not done then you get an error on startup. - * - * NOTES: Floppy does not seem to work. --FvK - * The "ROM DOS" shell does not seem to work. We do have the - * correct BIOS images now, and they do load, but they do not - * boot. Sometimes, they do, and then it shows an "Incorrect - * DOS" error message?? --FvK - * - * Version: @(#)m_ps1.c 1.0.11 2018/09/15 - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../pit.h" -#include "../mem.h" -#include "../nmi.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../nvr.h" -#include "../game/gameport.h" -#include "../lpt.h" -#include "../serial.h" -#include "../keyboard.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../sound/sound.h" -#include "../sound/snd_sn76489.h" -#include "../video/video.h" -#include "../video/vid_vga.h" -#include "../video/vid_ti_cf62011.h" -#include "machine.h" - - -typedef struct { - sn76489_t sn76489; - uint8_t status, ctrl; - int64_t timer_latch, timer_count, timer_enable; - uint8_t fifo[2048]; - int fifo_read_idx, fifo_write_idx; - int fifo_threshold; - uint8_t dac_val; - int16_t buffer[SOUNDBUFLEN]; - int pos; -} ps1snd_t; - -typedef struct { - int model; - - rom_t high_rom; - - uint8_t ps1_91, - ps1_92, - ps1_94, - ps1_102, - ps1_103, - ps1_104, - ps1_105, - ps1_190; - int ps1_e0_addr; - uint8_t ps1_e0_regs[256]; -} ps1_t; - - -static void -update_irq_status(ps1snd_t *snd) -{ - if (((snd->status & snd->ctrl) & 0x12) && (snd->ctrl & 0x01)) - picint(1 << 7); - else - picintc(1 << 7); -} - - -static uint8_t -snd_read(uint16_t port, void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - uint8_t ret = 0xff; - - switch (port & 7) { - case 0: /* ADC data */ - snd->status &= ~0x10; - update_irq_status(snd); - ret = 0; - break; - - case 2: /* status */ - ret = snd->status; - ret |= (snd->ctrl & 0x01); - if ((snd->fifo_write_idx - snd->fifo_read_idx) >= 2048) - ret |= 0x08; /* FIFO full */ - if (snd->fifo_read_idx == snd->fifo_write_idx) - ret |= 0x04; /* FIFO empty */ - break; - - case 3: /* FIFO timer */ - /* - * The PS/1 Technical Reference says this should return - * thecurrent value, but the PS/1 BIOS and Stunt Island - * expect it not to change. - */ - ret = snd->timer_latch; - break; - - case 4: - case 5: - case 6: - case 7: - ret = 0; - } - - return(ret); -} - - -static void -snd_write(uint16_t port, uint8_t val, void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - - switch (port & 7) { - case 0: /* DAC output */ - if ((snd->fifo_write_idx - snd->fifo_read_idx) < 2048) { - snd->fifo[snd->fifo_write_idx & 2047] = val; - snd->fifo_write_idx++; - } - break; - - case 2: /* control */ - snd->ctrl = val; - if (! (val & 0x02)) - snd->status &= ~0x02; - update_irq_status(snd); - break; - - case 3: /* timer reload value */ - snd->timer_latch = val; - snd->timer_count = (int64_t) ((0xff-val) * TIMER_USEC); - snd->timer_enable = (val != 0); - break; - - case 4: /* almost empty */ - snd->fifo_threshold = val * 4; - break; - } -} - - -static void -snd_update(ps1snd_t *snd) -{ - for (; snd->pos < sound_pos_global; snd->pos++) - snd->buffer[snd->pos] = (int8_t)(snd->dac_val ^ 0x80) * 0x20; -} - - -static void -snd_callback(void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - - snd_update(snd); - - if (snd->fifo_read_idx != snd->fifo_write_idx) { - snd->dac_val = snd->fifo[snd->fifo_read_idx & 2047]; - snd->fifo_read_idx++; - } - - if ((snd->fifo_write_idx - snd->fifo_read_idx) == snd->fifo_threshold) - snd->status |= 0x02; /*FIFO almost empty*/ - - snd->status |= 0x10; /*ADC data ready*/ - update_irq_status(snd); - - snd->timer_count += snd->timer_latch * TIMER_USEC; -} - - -static void -snd_get_buffer(int32_t *buffer, int len, void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - int c; - - snd_update(snd); - - for (c = 0; c < len * 2; c++) - buffer[c] += snd->buffer[c >> 1]; - - snd->pos = 0; -} - - -static void * -snd_init(const device_t *info) -{ - ps1snd_t *snd; - - snd = malloc(sizeof(ps1snd_t)); - memset(snd, 0x00, sizeof(ps1snd_t)); - - sn76489_init(&snd->sn76489, 0x0205, 0x0001, SN76496, 4000000); - - io_sethandler(0x0200, 1, snd_read,NULL,NULL, snd_write,NULL,NULL, snd); - io_sethandler(0x0202, 6, snd_read,NULL,NULL, snd_write,NULL,NULL, snd); - - timer_add(snd_callback, &snd->timer_count, &snd->timer_enable, snd); - - sound_add_handler(snd_get_buffer, snd); - - return(snd); -} - - -static void -snd_close(void *priv) -{ - ps1snd_t *snd = (ps1snd_t *)priv; - - free(snd); -} - - -static const device_t snd_device = { - "PS/1 Audio Card", - 0, 0, - snd_init, snd_close, NULL, - NULL, - NULL, - NULL -}; - - -static void -recalc_memory(ps1_t *ps) -{ - /* Enable first 512K */ - mem_set_mem_state(0x00000, 0x80000, - (ps->ps1_e0_regs[0] & 0x01) ? - (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : - (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); - - /* Enable 512-640K */ - mem_set_mem_state(0x80000, 0x20000, - (ps->ps1_e0_regs[1] & 0x01) ? - (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : - (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); -} - - -static void -ps1_write(uint16_t port, uint8_t val, void *priv) -{ - ps1_t *ps = (ps1_t *)priv; - - switch (port) { - case 0x0092: - if (ps->model != 2011) { - if (val & 1) { - softresetx86(); - cpu_set_edx(); - } - ps->ps1_92 = val & ~1; - } else { - ps->ps1_92 = val; - } - mem_a20_alt = val & 2; - mem_a20_recalc(); - break; - - case 0x0094: - ps->ps1_94 = val; - break; - - case 0x00e0: - if (ps->model != 2011) { - ps->ps1_e0_addr = val; - } - break; - - case 0x00e1: - if (ps->model != 2011) { - ps->ps1_e0_regs[ps->ps1_e0_addr] = val; - recalc_memory(ps); - } - break; - - case 0x0102: - lpt1_remove(); - if (val & 0x04) - serial_setup(1, SERIAL1_ADDR, SERIAL1_IRQ); - else - serial_remove(1); - if (val & 0x10) { - switch ((val >> 5) & 3) { - case 0: - lpt1_init(0x03bc); - break; - case 1: - lpt1_init(0x0378); - break; - case 2: - lpt1_init(0x0278); - break; - } - } - ps->ps1_102 = val; - break; - - case 0x0103: - ps->ps1_103 = val; - break; - - case 0x0104: - ps->ps1_104 = val; - break; - - case 0x0105: - ps->ps1_105 = val; - break; - - case 0x0190: - ps->ps1_190 = val; - break; - } -} - - -static uint8_t -ps1_read(uint16_t port, void *priv) -{ - ps1_t *ps = (ps1_t *)priv; - uint8_t ret = 0xff; - - switch (port) { - case 0x0091: - ret = ps->ps1_91; - ps->ps1_91 = 0; - break; - - case 0x0092: - ret = ps->ps1_92; - break; - - case 0x0094: - ret = ps->ps1_94; - break; - - case 0x00e1: - if (ps->model != 2011) { - ret = ps->ps1_e0_regs[ps->ps1_e0_addr]; - } - break; - - case 0x0102: - if (ps->model == 2011) - ret = ps->ps1_102 | 0x08; - else - ret = ps->ps1_102; - break; - - case 0x0103: - ret = ps->ps1_103; - break; - - case 0x0104: - ret = ps->ps1_104; - break; - - case 0x0105: - if (ps->model == 2011) - ret = ps->ps1_105; - else - ret = ps->ps1_105 | 0x80; - break; - - case 0x0190: - ret = ps->ps1_190; - break; - - default: - break; - } - - return(ret); -} - - -static void -ps1_setup(int model) -{ - ps1_t *ps; - void *priv; - - ps = (ps1_t *)malloc(sizeof(ps1_t)); - memset(ps, 0x00, sizeof(ps1_t)); - ps->model = model; - - io_sethandler(0x0091, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - io_sethandler(0x0092, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - io_sethandler(0x0094, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - io_sethandler(0x0102, 4, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - io_sethandler(0x0190, 1, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - - lpt1_remove(); - lpt1_init(0x3bc); - - if (model == 2011) { - rom_init(&ps->high_rom, - L"roms/machines/ibmps1es/f80000.bin", - 0xf80000, 0x80000, 0x7ffff, 0, MEM_MAPPING_EXTERNAL); - - lpt2_remove(); - - serial_remove(1); - serial_remove(2); - - /* Enable the PS/1 VGA controller. */ - if (model == 2011) - device_add(&ps1vga_device); - else - device_add(&ibm_ps1_2121_device); - - device_add(&snd_device); - - device_add(&fdc_at_actlow_device); - - /* Enable the builtin HDC. */ - if (hdc_current == 1) { - priv = device_add(&ps1_hdc_device); - - ps1_hdc_inform(priv, ps); - } - - mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, - mem_read_romext,mem_read_romextw,mem_read_romextl, - NULL,NULL, NULL, romext, 0, NULL); - } - - if (model == 2121) { - io_sethandler(0x00e0, 2, - ps1_read, NULL, NULL, ps1_write, NULL, NULL, ps); - -#if 0 - rom_init(&ps->high_rom, - L"roms/machines/ibmps1_2121/fc0000.bin", - 0xfc0000, 0x20000, 0x1ffff, 0, MEM_MAPPING_EXTERNAL); -#endif - - /* Initialize the video controller. */ - if (gfxcard == GFX_INTERNAL) - device_add(&ibm_ps1_2121_device); - - device_add(&fdc_at_ps1_device); - - device_add(&ide_isa_device); - - device_add(&snd_device); - } - - if (model == 2133) { - device_add(&fdc_at_device); - - device_add(&ide_isa_device); - } -} - - -static void -ps1_common_init(const machine_t *model) -{ - machine_common_init(model); - - mem_remap_top(384); - - pit_set_out_func(&pit, 1, pit_refresh_timer_at); - - dma16_init(); - pic2_init(); - - device_add(&ps_nvr_device); - - device_add(&keyboard_ps2_device); - - /* Audio uses ports 200h and 202-207h, so only initialize gameport on 201h. */ - if (joystick_type != 7) - device_add(&gameport_201_device); -} - - -/* Set the Card Selected Flag */ -void -ps1_set_feedback(void *priv) -{ - ps1_t *ps = (ps1_t *)priv; - - ps->ps1_91 |= 0x01; -} - - -void -machine_ps1_m2011_init(const machine_t *model) -{ - ps1_common_init(model); - - ps1_setup(2011); -} - - -void -machine_ps1_m2121_init(const machine_t *model) -{ - ps1_common_init(model); - - ps1_setup(2121); -} - - -void -machine_ps1_m2133_init(const machine_t *model) -{ - ps1_common_init(model); - - ps1_setup(2133); - - nmi_mask = 0x80; -} diff --git a/src/machine/m_xt_t1000 - Cópia.c b/src/machine/m_xt_t1000 - Cópia.c deleted file mode 100644 index 29149a498..000000000 --- a/src/machine/m_xt_t1000 - Cópia.c +++ /dev/null @@ -1,1107 +0,0 @@ -/* - * VARCem Virtual ARchaeological Computer EMulator. - * An emulator of (mostly) x86-based PC systems and devices, - * using the ISA,EISA,VLB,MCA and PCI system buses, roughly - * spanning the era between 1981 and 1995. - * - * This file is part of the VARCem Project. - * - * Implementation of the Toshiba T1000 and T1200 portables. - * - * The T1000 is the T3100e's little brother -- a real laptop - * with a rechargeable battery. - * - * Features: 80C88 at 4.77MHz - * - 512k system RAM - * - 640x200 monochrome LCD - * - 82-key keyboard - * - Real-time clock. Not the normal 146818, but a TC8521, - * which is a 4-bit chip. - * - A ROM drive (128k, 256k or 512k) which acts as a mini - * hard drive and contains a copy of DOS 2.11. - * - 160 bytes of non-volatile RAM for the CONFIG.SYS used - * when booting from the ROM drive. Possibly physically - * located in the keyboard controller RAM. - * - * An optional memory expansion board can be fitted. This adds - * 768k of RAM, which can be used for up to three purposes: - * > Conventional memory -- 128k between 512k and 640k - * > HardRAM -- a battery-backed RAM drive. - * > EMS - * - * This means that there are up to three different - * implementations of non-volatile RAM in the same computer - * (52 nibbles in the TC8521, 160 bytes of CONFIG.SYS, and - * up to 768k of HardRAM). - * - * The T1200 is a slightly upgraded version with a turbo mode - * (double CPU clock, 9.54MHz) and an optional hard drive. - * The interface for this is proprietary both at the physical - * and programming level. - * - * 01F2h: If hard drive is present, low 4 bits are 0Ch [20Mb] - * or 0Dh [10Mb]. - * - * The hard drive is a 20MB (615/2/26) RLL 3.5" drive. - * - * The TC8521 is a 4-bit RTC, so each memory location can only - * hold a single BCD digit. Hence everything has 'ones' and - * 'tens' digits. - * - * NOTE: Still need to figure out a way to load/save ConfigSys and - * HardRAM stuff. Needs to be linked in to the NVR code. - * - * Version: @(#)m_xt_t1000.c 1.0.11 2018/09/15 - * - * Authors: Fred N. van Kempen, - * Miran Grca, - * Sarah Walker, - * - * Copyright 2018 Fred N. van Kempen. - * Copyright 2018 Miran Grca. - * Copyright 2018 Sarah Walker. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the: - * - * Free Software Foundation, Inc. - * 59 Temple Place - Suite 330 - * Boston, MA 02111-1307 - * USA. - */ -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../pit.h" -#include "../nmi.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../keyboard.h" -#include "../lpt.h" -#include "../mem.h" -#include "../floppy/fdd.h" -#include "../floppy/fdc.h" -#include "../game/gameport.h" -#include "../video/video.h" -#include "../plat.h" -#include "machine.h" -#include "m_xt_t1000.h" - - -#define T1000_ROMSIZE (512*1024UL) /* Maximum ROM drive size is 512k */ - - -enum TC8521_ADDR { - /* Page 0 registers */ - TC8521_SECOND1 = 0, - TC8521_SECOND10, - TC8521_MINUTE1, - TC8521_MINUTE10, - TC8521_HOUR1, - TC8521_HOUR10, - TC8521_WEEKDAY, - TC8521_DAY1, - TC8521_DAY10, - TC8521_MONTH1, - TC8521_MONTH10, - TC8521_YEAR1, - TC8521_YEAR10, - TC8521_PAGE, /* PAGE register */ - TC8521_TEST, /* TEST register */ - TC8521_RESET, /* RESET register */ - - /* Page 1 registers */ - TC8521_24HR = 0x1A, - TC8521_LEAPYEAR = 0x1B -}; - - -typedef struct { - /* ROM drive */ - uint8_t *romdrive; - uint8_t rom_ctl; - uint32_t rom_offset; - mem_mapping_t rom_mapping; - - /* CONFIG.SYS drive. */ - uint8_t t1000_nvram[160]; - uint8_t t1200_nvram[2048]; - - /* System control registers */ - uint8_t sys_ctl[16]; - uint8_t syskeys; - uint8_t turbo; - - /* NVRAM control */ - uint8_t nvr_c0; - uint8_t nvr_tick; - int nvr_addr; - uint8_t nvr_active; - mem_mapping_t nvr_mapping; /* T1200 NVRAM mapping */ - - /* EMS data */ - uint8_t ems_reg[4]; - mem_mapping_t mapping[4]; - uint32_t page_exec[4]; - uint8_t ems_port_index; - uint16_t ems_port; - uint8_t is_640k; - uint32_t ems_base; - int32_t ems_pages; - - fdc_t *fdc; - - nvr_t nvr; - int is_t1200; -} t1000_t; - - -static t1000_t t1000; - - -#ifdef ENABLE_T1000_LOG -int t1000_do_log = ENABLE_T1000_LOG; -#endif - - -static void -t1000_log(const char *fmt, ...) -{ -#ifdef ENABLE_TANDY_LOG - va_list ap; - - if (t1000_do_log) - { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -/* Set the chip time. */ -static void -tc8521_time_set(uint8_t *regs, struct tm *tm) -{ - regs[TC8521_SECOND1] = (tm->tm_sec % 10); - regs[TC8521_SECOND10] = (tm->tm_sec / 10); - regs[TC8521_MINUTE1] = (tm->tm_min % 10); - regs[TC8521_MINUTE10] = (tm->tm_min / 10); - if (regs[TC8521_24HR] & 0x01) { - regs[TC8521_HOUR1] = (tm->tm_hour % 10); - regs[TC8521_HOUR10] = (tm->tm_hour / 10); - } else { - regs[TC8521_HOUR1] = ((tm->tm_hour % 12) % 10); - regs[TC8521_HOUR10] = (((tm->tm_hour % 12) / 10) | - ((tm->tm_hour >= 12) ? 2 : 0)); - } - regs[TC8521_WEEKDAY] = tm->tm_wday; - regs[TC8521_DAY1] = (tm->tm_mday % 10); - regs[TC8521_DAY10] = (tm->tm_mday / 10); - regs[TC8521_MONTH1] = ((tm->tm_mon + 1) % 10); - regs[TC8521_MONTH10] = ((tm->tm_mon + 1) / 10); - regs[TC8521_YEAR1] = ((tm->tm_year - 80) % 10); - regs[TC8521_YEAR10] = (((tm->tm_year - 80) % 100) / 10); -} - - -/* Get the chip time. */ -#define nibbles(a) (regs[(a##1)] + 10 * regs[(a##10)]) -static void -tc8521_time_get(uint8_t *regs, struct tm *tm) -{ - tm->tm_sec = nibbles(TC8521_SECOND); - tm->tm_min = nibbles(TC8521_MINUTE); - if (regs[TC8521_24HR] & 0x01) - tm->tm_hour = nibbles(TC8521_HOUR); - else - tm->tm_hour = ((nibbles(TC8521_HOUR) % 12) + - (regs[TC8521_HOUR10] & 0x02) ? 12 : 0); -//FIXME: wday - tm->tm_mday = nibbles(TC8521_DAY); - tm->tm_mon = (nibbles(TC8521_MONTH) - 1); - tm->tm_year = (nibbles(TC8521_YEAR) + 1980); -} - - -/* This is called every second through the NVR/RTC hook. */ -static void -tc8521_tick(nvr_t *nvr) -{ - t1000_log("TC8521: ping\n"); -} - - -static void -tc8521_start(nvr_t *nvr) -{ - struct tm tm; - - /* Initialize the internal and chip times. */ - if (time_sync & TIME_SYNC_ENABLED) { - /* Use the internal clock's time. */ - nvr_time_get(&tm); - tc8521_time_set(nvr->regs, &tm); - } else { - /* Set the internal clock from the chip time. */ - tc8521_time_get(nvr->regs, &tm); - nvr_time_set(&tm); - } - -#if 0 - /* Start the RTC - BIOS will do this. */ - nvr->regs[TC8521_PAGE] |= 0x80; -#endif -} - - -/* Write to one of the chip registers. */ -static void -tc8521_write(uint16_t addr, uint8_t val, void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - uint8_t page; - - /* Get to the correct register page. */ - addr &= 0x0f; - page = nvr->regs[0x0d] & 0x03; - if (addr < 0x0d) - addr += (16 * page); - - if (addr >= 0x10 && nvr->regs[addr] != val) - nvr_dosave = 1; - - /* Store the new value. */ - nvr->regs[addr] = val; -} - - -/* Read from one of the chip registers. */ -static uint8_t -tc8521_read(uint16_t addr, void *priv) -{ - nvr_t *nvr = (nvr_t *)priv; - uint8_t page; - - /* Get to the correct register page. */ - addr &= 0x0f; - page = nvr->regs[0x0d] & 0x03; - if (addr < 0x0d) - addr += (16 * page); - - /* Grab and return the desired value. */ - return(nvr->regs[addr]); -} - - -/* Reset the 8521 to a default state. */ -static void -tc8521_reset(nvr_t *nvr) -{ - /* Clear the NVRAM. */ - memset(nvr->regs, 0xff, nvr->size); - - /* Reset the RTC registers. */ - memset(nvr->regs, 0x00, 16); - nvr->regs[TC8521_WEEKDAY] = 0x01; - nvr->regs[TC8521_DAY1] = 0x01; - nvr->regs[TC8521_MONTH1] = 0x01; -} - - -static void -tc8521_init(nvr_t *nvr, int size) -{ - /* This is machine specific. */ - nvr->size = size; - nvr->irq = -1; - - /* Set up any local handlers here. */ - nvr->reset = tc8521_reset; - nvr->start = tc8521_start; - nvr->tick = tc8521_tick; - - /* Initialize the actual NVR. */ - nvr_init(nvr); - - io_sethandler(0x02c0, 16, - tc8521_read,NULL,NULL, tc8521_write,NULL,NULL, nvr); -} - - -/* Given an EMS page ID, return its physical address in RAM. */ -static uint32_t -ems_execaddr(t1000_t *sys, int pg, uint16_t val) -{ - if (!(val & 0x80)) return(0); /* Bit 7 reset => not mapped */ - if (!sys->ems_pages) return(0); /* No EMS available: all used by - * HardRAM or conventional RAM */ - val &= 0x7f; - -#if 0 - t1000_log("Select EMS page: %d of %d\n", val, sys->ems_pages); -#endif - if (val < sys->ems_pages) { - /* EMS is any memory above 512k, - with ems_base giving the start address */ - return((512 * 1024) + (sys->ems_base * 0x10000) + (0x4000 * val)); - } - - return(0); -} - - -static uint8_t -ems_in(uint16_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - -#if 0 - t1000_log("ems_in(%04x)=%02x\n", addr, sys->ems_reg[(addr >> 14) & 3]); -#endif - return(sys->ems_reg[(addr >> 14) & 3]); -} - - -static void -ems_out(uint16_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = (addr >> 14) & 3; - -#if 0 - t1000_log("ems_out(%04x, %02x) pg=%d\n", addr, val, pg); -#endif - sys->ems_reg[pg] = val; - sys->page_exec[pg] = ems_execaddr(sys, pg, val); - if (sys->page_exec[pg]) { - /* Page present */ - mem_mapping_enable(&sys->mapping[pg]); - mem_mapping_set_exec(&sys->mapping[pg], ram + sys->page_exec[pg]); - } else { - mem_mapping_disable(&sys->mapping[pg]); - } -} - - -/* Hardram size is in 64k units */ -static void -ems_set_hardram(t1000_t *sys, uint8_t val) -{ - int n; - - val &= 0x1f; /* Mask off pageframe address */ - if (val && mem_size > 512) - sys->ems_base = val; - else - sys->ems_base = 0; - -#if 0 - t1000_log("EMS base set to %02x\n", val); -#endif - sys->ems_pages = ((mem_size - 512) / 16) - 4 * sys->ems_base; - if (sys->ems_pages < 0) sys->ems_pages = 0; - - /* Recalculate EMS mappings */ - for (n = 0; n < 4; n++) - ems_out(n << 14, sys->ems_reg[n], sys); -} - - -static void -ems_set_640k(t1000_t *sys, uint8_t val) -{ - if (val && mem_size >= 640) { - mem_mapping_set_addr(&ram_low_mapping, 0, 640 * 1024); - sys->is_640k = 1; - } else { - mem_mapping_set_addr(&ram_low_mapping, 0, 512 * 1024); - sys->is_640k = 0; - } -} - - -static void -ems_set_port(t1000_t *sys, uint8_t val) -{ - int n; - -#if 0 - t1000_log("ems_set_port(%d)", val & 0x0f); -#endif - if (sys->ems_port) { - for (n = 0; n <= 0xc000; n += 0x4000) { - io_removehandler(sys->ems_port+n, 1, - ems_in,NULL,NULL, ems_out,NULL,NULL, sys); - } - sys->ems_port = 0; - } - - val &= 0x0f; - sys->ems_port_index = val; - if (val == 7) { - /* No EMS */ - sys->ems_port = 0; - } else { - sys->ems_port = 0x208 | (val << 4); - for (n = 0; n <= 0xc000; n += 0x4000) { - io_sethandler(sys->ems_port+n, 1, - ems_in,NULL,NULL, ems_out,NULL,NULL, sys); - } - sys->ems_port = 0; - } - -#if 0 - t1000_log(" -> %04x\n", sys->ems_port); -#endif -} - - -static int -addr_to_page(uint32_t addr) -{ - return((addr - 0xd0000) / 0x4000); -} - - -/* Read RAM in the EMS page frame. */ -static uint8_t -ems_read_ram(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return(0xff); - addr = sys->page_exec[pg] + (addr & 0x3fff); - - return(ram[addr]); -} - - -static uint16_t -ems_read_ramw(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return(0xff); - -#if 0 - t1000_log("ems_read_ramw addr=%05x ", addr); -#endif - addr = sys->page_exec[pg] + (addr & 0x3FFF); - -#if 0 - t1000_log("-> %06x val=%04x\n", addr, *(uint16_t *)&ram[addr]); -#endif - - return(*(uint16_t *)&ram[addr]); -} - - -static uint32_t -ems_read_raml(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return(0xff); - addr = sys->page_exec[pg] + (addr & 0x3fff); - - return(*(uint32_t *)&ram[addr]); -} - - -/* Write RAM in the EMS page frame. */ -static void -ems_write_ram(uint32_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - - addr = sys->page_exec[pg] + (addr & 0x3fff); - if (ram[addr] != val) nvr_dosave = 1; - - ram[addr] = val; -} - - -static void -ems_write_ramw(uint32_t addr, uint16_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - -#if 0 - t1000_log("ems_write_ramw addr=%05x ", addr); -#endif - addr = sys->page_exec[pg] + (addr & 0x3fff); - -#if 0 - t1000_log("-> %06x val=%04x\n", addr, val); -#endif - - if (*(uint16_t *)&ram[addr] != val) nvr_dosave = 1; - - *(uint16_t *)&ram[addr] = val; -} - - -static void -ems_write_raml(uint32_t addr, uint32_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - int pg = addr_to_page(addr); - - if (pg < 0) return; - - addr = sys->page_exec[pg] + (addr & 0x3fff); - if (*(uint32_t *)&ram[addr] != val) nvr_dosave = 1; - - *(uint32_t *)&ram[addr] = val; -} - - -static uint8_t -read_ctl(uint16_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - uint8_t ret = 0xff; - - switch (addr & 0x0f) { - case 1: - ret = sys->syskeys; - break; - - case 0x0f: /* Detect EMS board */ - switch (sys->sys_ctl[0x0e]) { - case 0x50: - if (mem_size > 512) break; - ret = (0x90 | sys->ems_port_index); - break; - - case 0x51: - /* 0x60 is the page frame address: - (0xd000 - 0xc400) / 0x20 */ - ret = (sys->ems_base | 0x60); - break; - - case 0x52: - ret = (sys->is_640k ? 0x80 : 0); - break; - } - break; - - default: - ret = (sys->sys_ctl[addr & 0x0f]); - } - - return(ret); -} - - -static void -t1200_turbo_set(uint8_t value) -{ - if (value == t1000.turbo) return; - - t1000.turbo = value; - if (! value) - cpu_dynamic_switch(0); - else - cpu_dynamic_switch(cpu); -} - - -static void -write_ctl(uint16_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - sys->sys_ctl[addr & 0x0f] = val; - switch (addr & 0x0f) { - case 4: /* Video control */ - if (sys->sys_ctl[3] == 0x5A) { - t1000_video_options_set((val & 0x20) ? 1 : 0); - t1000_display_set((val & 0x40) ? 0 : 1); - if (sys->is_t1200) - t1200_turbo_set((val & 0x80) ? 1 : 0); - } - break; - - /* It looks as if the T1200, like the T3100, can disable - * its builtin video chipset if it detects the presence of - * another video card. */ - case 6: if (sys->is_t1200) - { - t1000_video_enable(val & 0x01 ? 0 : 1); - } - break; - - case 0x0f: /* EMS control */ - switch (sys->sys_ctl[0x0e]) { - case 0x50: - ems_set_port(sys, val); - break; - - case 0x51: - ems_set_hardram(sys, val); - break; - - case 0x52: - ems_set_640k(sys, val); - break; - } - break; - } -} - - -/* Ports 0xC0 to 0xC3 appear to have two purposes: - * - * > Access to the 160 bytes of non-volatile RAM containing CONFIG.SYS - * > Reading the floppy changeline. I don't know why the Toshiba doesn't - * use the normal port 0x3F7 for this, but it doesn't. - * - */ -static uint8_t -t1000_read_nvram(uint16_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - uint8_t tmp = 0xff; - - switch (addr) { - case 0xc2: /* Read next byte from NVRAM */ - if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) - tmp = sys->t1000_nvram[sys->nvr_addr]; - sys->nvr_addr++; - break; - - case 0xc3: /* Read floppy changeline and NVRAM ready state */ - tmp = fdc_read(0x03f7, t1000.fdc); - - tmp = (tmp & 0x80) >> 3; /* Bit 4 is changeline */ - tmp |= (sys->nvr_active & 0xc0);/* Bits 6,7 are r/w mode */ - tmp |= 0x2e; /* Bits 5,3,2,1 always 1 */ - tmp |= (sys->nvr_active & 0x40) >> 6; /* Ready state */ - break; - } - - return(tmp); -} - - -static void -t1000_write_nvram(uint16_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - /* - * On the real T1000, port 0xC1 is only usable as the high byte - * of a 16-bit write to port 0xC0, with 0x5A in the low byte. - */ - switch (addr) { - case 0xc0: - sys->nvr_c0 = val; - break; - - case 0xc1: /* Write next byte to NVRAM */ - if (sys->nvr_addr >= 0 && sys->nvr_addr < 160) { - if (sys->t1000_nvram[sys->nvr_addr] != val) - nvr_dosave = 1; - sys->t1000_nvram[sys->nvr_addr] = val; - } - sys->nvr_addr++; - break; - - case 0xc2: - break; - - case 0xc3: - /* - * At start of NVRAM read / write, 0x80 is written to - * port 0xC3. This seems to reset the NVRAM address - * counter. A single byte is then written (0xff for - * write, 0x00 for read) which appears to be ignored. - * Simulate that by starting the address counter off - * at -1. - */ - sys->nvr_active = val; - if (val == 0x80) sys->nvr_addr = -1; - break; - } -} - - -static -uint8_t read_t1200_nvram(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - return sys->t1200_nvram[addr & 0x7FF]; -} - - -static void write_t1200_nvram(uint32_t addr, uint8_t value, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - if (sys->t1200_nvram[addr & 0x7FF] != value) - nvr_dosave = 1; - - sys->t1200_nvram[addr & 0x7FF] = value; -} - - -/* Port 0xC8 controls the ROM drive */ -static uint8_t -t1000_read_rom_ctl(uint16_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - return(sys->rom_ctl); -} - - -static void -t1000_write_rom_ctl(uint16_t addr, uint8_t val, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - sys->rom_ctl = val; - if (sys->romdrive && (val & 0x80)) { - /* Enable */ - sys->rom_offset = ((val & 0x7f) * 0x10000) % T1000_ROMSIZE; - mem_mapping_set_addr(&sys->rom_mapping, 0xa0000, 0x10000); - mem_mapping_set_exec(&sys->rom_mapping, sys->romdrive + sys->rom_offset); - mem_mapping_enable(&sys->rom_mapping); - } else { - mem_mapping_disable(&sys->rom_mapping); - } -} - - -/* Read the ROM drive */ -static uint8_t -t1000_read_rom(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - if (! sys->romdrive) return(0xff); - - return(sys->romdrive[sys->rom_offset + (addr & 0xffff)]); -} - - -static uint16_t -t1000_read_romw(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - if (! sys->romdrive) return(0xffff); - - return(*(uint16_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); -} - - -static uint32_t -t1000_read_roml(uint32_t addr, void *priv) -{ - t1000_t *sys = (t1000_t *)priv; - - if (! sys->romdrive) return(0xffffffff); - - return(*(uint32_t *)(&sys->romdrive[sys->rom_offset + (addr & 0xffff)])); -} - - -const device_t * -t1000_get_device(void) -{ - return(&t1000_video_device); -} - - -void -machine_xt_t1000_init(const machine_t *model) -{ - FILE *f; - int pg; - - memset(&t1000, 0x00, sizeof(t1000)); - t1000.is_t1200 = 0; - t1000.turbo = 0xff; - t1000.ems_port_index = 7; /* EMS disabled */ - - /* Load the T1000 CGA Font ROM. */ - loadfont(L"roms/machines/t1000/t1000font.rom", 2); - - /* - * The ROM drive is optional. - * - * If the file is missing, continue to boot; the BIOS will - * complain 'No ROM drive' but boot normally from floppy. - */ - f = rom_fopen(L"roms/machines/t1000/t1000dos.rom", L"rb"); - if (f != NULL) { - t1000.romdrive = malloc(T1000_ROMSIZE); - if (t1000.romdrive) { - memset(t1000.romdrive, 0xff, T1000_ROMSIZE); - fread(t1000.romdrive, T1000_ROMSIZE, 1, f); - } - fclose(f); - } - mem_mapping_add(&t1000.rom_mapping, 0xa0000, 0x10000, - t1000_read_rom,t1000_read_romw,t1000_read_roml, - NULL,NULL,NULL, NULL, MEM_MAPPING_INTERNAL, &t1000); - mem_mapping_disable(&t1000.rom_mapping); - - /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) { - mem_mapping_add(&t1000.mapping[pg], 0xd0000 + (0x4000 * pg), 16384, - ems_read_ram,ems_read_ramw,ems_read_raml, - ems_write_ram,ems_write_ramw,ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, &t1000); - - /* Start them all off disabled */ - mem_mapping_disable(&t1000.mapping[pg]); - } - - /* Non-volatile RAM for CONFIG.SYS */ - io_sethandler(0xc0, 4, - t1000_read_nvram,NULL,NULL, - t1000_write_nvram,NULL,NULL, &t1000); - - /* ROM drive */ - io_sethandler(0xc8, 1, - t1000_read_rom_ctl,NULL,NULL, - t1000_write_rom_ctl,NULL,NULL, &t1000); - - /* System control functions, and add-on memory board */ - io_sethandler(0xe0, 16, - read_ctl,NULL,NULL, write_ctl,NULL,NULL, &t1000); - - machine_common_init(model); - - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - device_add(&keyboard_xt_device); - t1000.fdc = device_add(&fdc_xt_device); - nmi_init(); - - tc8521_init(&t1000.nvr, model->nvrmask + 1); - - t1000_nvr_load(); - nvr_set_ven_save(t1000_nvr_save); - - if (gfxcard == GFX_INTERNAL) - device_add(&t1000_video_device); -} - - -const device_t * -t1200_get_device(void) -{ - return(&t1200_video_device); -} - - -void -machine_xt_t1200_init(const machine_t *model) -{ - int pg; - - memset(&t1000, 0x00, sizeof(t1000)); - t1000.is_t1200 = 1; - t1000.ems_port_index = 7; /* EMS disabled */ - - /* Load the T1200 CGA Font ROM. */ - loadfont(L"roms/machines/t1200/t1000font.bin", 2); - - /* Map the EMS page frame */ - for (pg = 0; pg < 4; pg++) { - mem_mapping_add(&t1000.mapping[pg], - 0xd0000 + (0x4000 * pg), 16384, - ems_read_ram,ems_read_ramw,ems_read_raml, - ems_write_ram,ems_write_ramw,ems_write_raml, - NULL, MEM_MAPPING_EXTERNAL, &t1000); - - /* Start them all off disabled */ - mem_mapping_disable(&t1000.mapping[pg]); - } - - /* System control functions, and add-on memory board */ - io_sethandler(0xe0, 16, - read_ctl,NULL,NULL, write_ctl,NULL,NULL, &t1000); - - machine_common_init(model); - - mem_mapping_add(&t1000.nvr_mapping, - 0x000f0000, 2048, - read_t1200_nvram, NULL, NULL, - write_t1200_nvram, NULL, NULL, - NULL, 0, &t1000); - - pit_set_out_func(&pit, 1, pit_refresh_timer_xt); - device_add(&keyboard_xt_device); - t1000.fdc = device_add(&fdc_xt_device); - nmi_init(); - - tc8521_init(&t1000.nvr, model->nvrmask + 1); - - t1200_nvr_load(); - nvr_set_ven_save(t1200_nvr_save); - - if (gfxcard == GFX_INTERNAL) - device_add(&t1200_video_device); -} - - -void -t1000_syskey(uint8_t andmask, uint8_t ormask, uint8_t xormask) -{ - t1000.syskeys &= ~andmask; - t1000.syskeys |= ormask; - t1000.syskeys ^= xormask; -} - - -static void -t1000_configsys_load(void) -{ - FILE *f; - - memset(t1000.t1000_nvram, 0x1a, sizeof(t1000.t1000_nvram)); - f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"rb"); - if (f != NULL) { - fread(t1000.t1000_nvram, sizeof(t1000.t1000_nvram), 1, f); - fclose(f); - } -} - - -static void -t1000_configsys_save(void) -{ - FILE *f; - - f = plat_fopen(nvr_path(L"t1000_config.nvr"), L"wb"); - if (f != NULL) { - fwrite(t1000.t1000_nvram, sizeof(t1000.t1000_nvram), 1, f); - fclose(f); - } -} - - -static void -t1200_state_load(void) -{ - FILE *f; - - memset(t1000.t1200_nvram, 0, sizeof(t1000.t1200_nvram)); - f = plat_fopen(nvr_path(L"t1200_state.nvr"), L"rb"); - if (f != NULL) { - fread(t1000.t1200_nvram, sizeof(t1000.t1200_nvram), 1, f); - fclose(f); - } -} - - -static void -t1200_state_save(void) -{ - FILE *f; - - f = plat_fopen(nvr_path(L"t1200_state.nvr"), L"wb"); - if (f != NULL) { - fwrite(t1000.t1200_nvram, sizeof(t1000.t1200_nvram), 1, f); - fclose(f); - } -} - - -/* All RAM beyond 512k is non-volatile */ -static void -t1000_emsboard_load(void) -{ - FILE *f; - - if (mem_size > 512) { - f = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"rb"); - if (f != NULL) { - fread(&ram[512 * 1024], 1024, (mem_size - 512), f); - fclose(f); - } - } -} - - -static void -t1000_emsboard_save(void) -{ - FILE *f; - - if (mem_size > 512) { - f = plat_fopen(nvr_path(L"t1000_ems.nvr"), L"wb"); - if (f != NULL) { - fwrite(&ram[512 * 1024], 1024, (mem_size - 512), f); - fclose(f); - } - } -} - - -void -t1000_nvr_load(void) -{ - t1000_emsboard_load(); - t1000_configsys_load(); -} - - -void -t1000_nvr_save(void) -{ - t1000_emsboard_save(); - t1000_configsys_save(); -} - - -void -t1200_nvr_load(void) -{ - t1000_emsboard_load(); - t1200_state_load(); -} - - -void -t1200_nvr_save(void) -{ - t1000_emsboard_save(); - t1200_state_save(); -} diff --git a/src/pc - Cópia.c b/src/pc - Cópia.c deleted file mode 100644 index 5f302cd4e..000000000 --- a/src/pc - Cópia.c +++ /dev/null @@ -1,1156 +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. - * - * Main emulator module where most things are controlled. - * - * Version: @(#)pc.c 1.0.76 2018/09/02 - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "86box.h" -#include "config.h" -#include "cpu/cpu.h" -#ifdef USE_DYNAREC -# include "cpu/codegen.h" -#endif -#include "cpu/x86_ops.h" -#include "io.h" -#include "mem.h" -#include "rom.h" -#include "dma.h" -#include "pci.h" -#include "pic.h" -#include "pit.h" -#include "random.h" -#include "timer.h" -#include "device.h" -#include "nvr.h" -#include "machine/machine.h" -#include "bugger.h" -#include "isamem.h" -#include "isartc.h" -#include "lpt.h" -#include "serial.h" -#include "keyboard.h" -#include "mouse.h" -#include "game/gameport.h" -#include "floppy/fdd.h" -#include "floppy/fdc.h" -#include "disk/hdd.h" -#include "disk/hdc.h" -#include "disk/hdc_ide.h" -#include "scsi/scsi.h" -#include "cdrom/cdrom.h" -#include "disk/zip.h" -#include "scsi/scsi_disk.h" -#include "cdrom/cdrom_image.h" -#include "cdrom/cdrom_null.h" -#include "network/network.h" -#include "sound/sound.h" -#include "sound/midi.h" -#include "sound/snd_speaker.h" -#include "video/video.h" -#include "ui.h" -#include "plat.h" -#include "plat_midi.h" - - -/* Commandline options. */ -int dump_on_exit = 0; /* (O) dump regs on exit */ -int do_dump_config = 0; /* (O) dump config on load */ -int start_in_fullscreen = 0; /* (O) start in fullscreen */ -#ifdef _WIN32 -int force_debug = 0; /* (O) force debug output */ -#endif -#ifdef USE_WX -int video_fps = RENDER_FPS; /* (O) render speed in fps */ -#endif -int settings_only = 0; /* (O) show only the settings dialog */ -#ifdef _WIN32 -uint64_t unique_id = 0; -uint64_t source_hwnd = 0; -#endif -wchar_t log_path[1024] = { L'\0'}; /* (O) full path of logfile */ - -/* Configuration values. */ -int window_w, window_h, /* (C) window size and */ - window_x, window_y, /* position info */ - window_remember, - vid_resize, /* (C) allow resizing */ - invert_display, /* (C) invert the display */ - suppress_overscan = 0; /* (C) suppress overscans */ -int scale = 0; /* (C) screen scale factor */ -int vid_api = 0; /* (C) video renderer */ -int vid_cga_contrast = 0, /* (C) video */ - video_fullscreen = 0, /* (C) video */ - video_fullscreen_scale = 0, /* (C) video */ - video_fullscreen_first = 0, /* (C) video */ - enable_overscan = 0, /* (C) video */ - force_43 = 0; /* (C) video */ -int serial_enabled[SERIAL_MAX] = {0,0}, /* (C) enable serial ports */ - lpt_enabled = 0, /* (C) enable LPT ports */ - bugger_enabled = 0, /* (C) enable ISAbugger */ - isamem_type[ISAMEM_MAX] = { 0,0,0,0 }, /* (C) enable ISA mem cards */ - isartc_type = 0; /* (C) enable ISA RTC card */ -int gfxcard = 0; /* (C) graphics/video card */ -int sound_is_float = 1, /* (C) sound uses FP values */ - GAMEBLASTER = 0, /* (C) sound option */ - GUS = 0, /* (C) sound option */ - SSI2001 = 0, /* (C) sound option */ - voodoo_enabled = 0; /* (C) video option */ -uint32_t mem_size = 0; /* (C) memory size */ -int cpu_manufacturer = 0, /* (C) cpu manufacturer */ - cpu_use_dynarec = 0, /* (C) cpu uses/needs Dyna */ - cpu = 3, /* (C) cpu type */ - enable_external_fpu = 0; /* (C) enable external FPU */ -int time_sync = 0; /* (C) enable time sync */ - -/* Statistics. */ -extern int - mmuflush, - readlnum, - writelnum; - -int fps, framecount; /* emulator % */ - -int CPUID; -int output; -int atfullspeed; -int cpuspeed2; -int clockrate; - -int gfx_present[GFX_MAX]; /* should not be here */ - -wchar_t exe_path[1024]; /* path (dir) of executable */ -wchar_t usr_path[1024]; /* path (dir) of user data */ -wchar_t cfg_path[1024]; /* full path of config file */ -FILE *stdlog = NULL; /* file to log output to */ -int scrnsz_x = SCREEN_RES_X, /* current screen size, X */ - scrnsz_y = SCREEN_RES_Y; /* current screen size, Y */ -int config_changed; /* config has changed */ -int romset; /* current machine ID */ -int title_update; -int64_t main_time; - - -int unscaled_size_x = SCREEN_RES_X, /* current unscaled size X */ - unscaled_size_y = SCREEN_RES_Y, /* current unscaled size Y */ - efscrnsz_y = SCREEN_RES_Y; - - -#ifndef RELEASE_BUILD -static char buff[1024]; -static int seen = 0; - -static int suppr_seen = 1; -#endif - -/* - * Log something to the logfile or stdout. - * - * To avoid excessively-large logfiles because some - * module repeatedly logs, we keep track of what is - * being logged, and catch repeating entries. - */ -void -pclog_ex(const char *fmt, va_list ap) -{ -#ifndef RELEASE_BUILD - char temp[1024]; - - if (stdlog == NULL) { - if (log_path[0] != L'\0') { - stdlog = plat_fopen(log_path, L"w"); - if (stdlog == NULL) - stdlog = stdout; - } else { - stdlog = stdout; - } - } - - vsprintf(temp, fmt, ap); - if (suppr_seen && ! strcmp(buff, temp)) { - seen++; - } else { - if (suppr_seen && seen) { - fprintf(stdlog, "*** %d repeats ***\n", seen); - } - seen = 0; - strcpy(buff, temp); - fprintf(stdlog, temp, ap); - } - - fflush(stdlog); -#endif -} - - -void -pclog_toggle_suppr(void) -{ -#ifndef RELEASE_BUILD - suppr_seen ^= 1; -#endif -} - - -/* Log something. We only do this in non-release builds. */ -void -pclog(const char *fmt, ...) -{ -#ifndef RELEASE_BUILD - va_list ap; - - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); -#endif -} - - -/* Log a fatal error, and display a UI message before exiting. */ -void -fatal(const char *fmt, ...) -{ - char temp[1024]; - va_list ap; - char *sp; - - va_start(ap, fmt); - - if (stdlog == NULL) { - if (log_path[0] != L'\0') { - stdlog = plat_fopen(log_path, L"w"); - if (stdlog == NULL) - stdlog = stdout; - } else { - stdlog = stdout; - } - } - - vsprintf(temp, fmt, ap); - fprintf(stdlog, "%s", temp); - fflush(stdlog); - va_end(ap); - - nvr_save(); - - config_save(); - - dumppic(); - dumpregs(1); - - /* Make sure the message does not have a trailing newline. */ - if ((sp = strchr(temp, '\n')) != NULL) *sp = '\0'; - - ui_msgbox(MBX_ERROR|MBX_FATAL|MBX_ANSI, temp); - - fflush(stdlog); - - exit(-1); -} - - -#ifdef ENABLE_PC_LOG -int pc_do_log = ENABLE_PC_LOG; -#endif - - -static void -pc_log(const char *format, ...) -{ -#ifdef ENABLE_PC_LOG - va_list ap; - - if (pc_do_log) { - va_start(ap, format); - pclog_ex(format, ap); - va_end(ap); - } -#endif -} - - -/* - * Perform initial startup of the PC. - * - * This is the platform-indepenent part of the startup, - * where we check commandline arguments and load a - * configuration file. - */ -int -pc_init(int argc, wchar_t *argv[]) -{ - wchar_t path[2048]; - wchar_t *cfg = NULL, *p; - char temp[128]; - struct tm *info; - time_t now; - int c; - uint32_t *uid, *shwnd; - - /* Grab the executable's full path. */ - plat_get_exe_name(exe_path, sizeof(exe_path)-1); - p = plat_get_filename(exe_path); - *p = L'\0'; - - /* - * Get the current working directory. - * - * This is normally the directory from where the - * program was run. If we have been started via - * a shortcut (desktop icon), however, the CWD - * could have been set to something else. - */ - plat_getcwd(usr_path, sizeof_w(usr_path)-1); - memset(path, 0x00, sizeof(path)); - - for (c=1; c= CPU_286) - setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - else - setpitclock(14318184.0); - } - atfullspeed = 1; - - nvr_period_recalc(); -} - - -void -pc_speed_changed(void) -{ - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) - setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - else - setpitclock(14318184.0); - - nvr_period_recalc(); -} - - -#if 0 -/* Re-load system configuration and restart. */ -/* FIXME: this has to be reviewed! */ -void -pc_reload(wchar_t *fn) -{ - int i; - - config_write(cfg_path); - - for (i=0; i=0; c--) { - if (gfx_present[c]) { - gfxcard = c; - config_save(); - - /* This can loop if all cards now bad.. */ - goto again2; - } - } - } - - // cpuspeed2 = (AT) ? 2 : 1; - cpuspeed2 = (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) ? 2 : 1; - atfullspeed = 0; - - random_init(); - - mem_init(); - -#ifdef USE_DYNAREC - codegen_init(); -#endif - - keyboard_init(); - joystick_init(); - video_init(); - device_init(); - - timer_reset(); - - fdd_init(); - - sound_init(); - - hdc_init(hdc_name); - - cdrom_hard_reset(); - - zip_hard_reset(); - - scsi_disk_hard_reset(); - - scsi_card_init(); - - pc_full_speed(); - shadowbios = 0; - - return(1); -} - - -/* Insert keystrokes into the machine's keyboard buffer. */ -static void -pc_keyboard_send(uint8_t val) -{ - if (AT) - keyboard_at_adddata_keyboard_raw(val); - else - keyboard_send(val); -} - - -void -pc_send_ca(uint8_t sc) -{ - pc_keyboard_send(29); /* Ctrl key pressed */ - pc_keyboard_send(56); /* Alt key pressed */ - pc_keyboard_send(sc); - pc_keyboard_send(sc | 0x80); - pc_keyboard_send(184); /* Alt key released */ - pc_keyboard_send(157); /* Ctrl key released */ -} - - -/* Send the machine a Control-Alt-DEL sequence. */ -void -pc_send_cad(void) -{ - pc_send_ca(83); -} - - -/* Send the machine a Control-Alt-ESC sequence. */ -void -pc_send_cae(void) -{ - pc_send_ca(1); -} - - -void -pc_reset_hard_close(void) -{ - suppress_overscan = 0; - - nvr_save(); - - mouse_close(); - - lpt_devices_close(); - - device_close_all(); - - midi_close(); - - cdrom_close(); - - closeal(); -} - - -/* - * This is basically the spot where we start up the actual machine, - * by issuing a 'hard reset' to the entire configuration. Order is - * somewhat important here. Functions here should be named _reset - * really, as that is what they do. - */ -void -pc_reset_hard_init(void) -{ - /* - * First, we reset the modules that are not part of - * the actual machine, but which support some of the - * modules that are. - */ - - /* Reset the general machine support modules. */ - io_init(); - timer_reset(); - - device_init(); - - sound_reset(); - - /* This is needed to initialize the serial timer. */ - serial_init(); - - cdrom_hard_reset(); - - zip_hard_reset(); - - scsi_disk_hard_reset(); - - /* Initialize the actual machine and its basic modules. */ - video_font_reset(); /* Reset (deallocate) the video font arrays. */ - machine_init(); - - /* Reset any ISA memory cards. */ - isamem_reset(); - - /* Reset any ISA RTC cards. */ - isartc_reset(); - - fdd_reset(); - - /* - * Once the machine has been initialized, all that remains - * should be resetting all devices set up for it, to their - * current configurations ! - * - * For now, we will call their reset functions here, but - * that will be a call to device_reset_all() later ! - */ - - /* Reset some basic devices. */ - speaker_init(); - serial_reset(); - lpt_devices_init(); - shadowbios = 0; - - /* - * This has to be after the serial initialization so that - * serial_init() doesn't break the serial mouse by resetting - * the RCR callback to NULL. - */ - mouse_reset(); - - /* Reset the video card. */ - video_reset(gfxcard); - - /* Reset the Hard Disk Controller module. */ - hdc_reset(); - - /* Reset and reconfigure the SCSI layer. */ - scsi_card_init(); - - /* Reset and reconfigure the Sound Card layer. */ - sound_card_reset(); - - /* Reset and reconfigure the Network Card layer. */ - network_reset(); - - if (joystick_type != 7) - gameport_update_joystick_type(); - - if (config_changed) { - ui_sb_update_panes(); - - config_save(); - - config_changed = 0; - } - - /* Needs the status bar... */ - if (bugger_enabled) - device_add(&bugger_device); - - /* Reset the CPU module. */ - resetx86(); - dma_reset(); - pic_reset(); - cpu_cache_int_enabled = cpu_cache_ext_enabled = 0; - - if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) - setpitclock(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed); - else - setpitclock(14318184.0); -} - - -void -pc_reset_hard(void) -{ - pc_reset_hard_close(); - - pc_reset_hard_init(); -} - - -void -pc_reset(int hard) -{ - plat_pause(1); - - plat_delay_ms(100); - - nvr_save(); - - config_save(); - - if (hard) - pc_reset_hard(); - else - pc_send_cad(); - - plat_pause(0); -} - - -void -pc_close(thread_t *ptr) -{ - int i; - - /* Wait a while so things can shut down. */ - plat_delay_ms(200); - - /* Claim the video blitter. */ - startblit(); - - /* Terminate the main thread. */ - if (ptr != NULL) { - thread_kill(ptr); - - /* Wait some more. */ - plat_delay_ms(200); - } - - nvr_save(); - - config_save(); - - plat_mouse_capture(0); - - lpt_devices_close(); - - for (i=0; i 0 && !dopause) { - /* Yes, so do one frame now. */ - start_time = plat_timer_read(); - drawits -= 10; - if (drawits > 50) - drawits = 0; - - /* Run a block of code. */ - startblit(); - clockrate = machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].rspeed; - - if (is386) { -#ifdef USE_DYNAREC - if (cpu_use_dynarec) - exec386_dynarec(clockrate/100); - else -#endif - exec386(clockrate/100); - } else if (machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type >= CPU_286) { - exec386(clockrate/100); - } else { - execx86(clockrate/100); - } - - mouse_process(); - - joystick_process(); - - endblit(); - - /* Done with this frame, update statistics. */ - framecount++; - if (++framecountx >= 100) { - framecountx = 0; - - readlnum = writelnum = 0; - egareads = egawrites = 0; - mmuflush = 0; - frames = 0; - } - - if (title_update) { - mbstowcs(wmachine, machine_getname(), strlen(machine_getname())+1); - mbstowcs(wcpu, machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name, - strlen(machines[machine].cpu[cpu_manufacturer].cpus[cpu_effective].name)+1); - swprintf(temp, sizeof_w(temp), - L"%ls v%ls - %i%% - %ls - %ls - %ls", - EMU_NAME_W,EMU_VERSION_W,fps,wmachine,wcpu, - (!mouse_capture) ? plat_get_string(IDS_2077) - : (mouse_get_buttons() > 2) ? plat_get_string(IDS_2078) : plat_get_string(IDS_2079)); - - ui_window_title(temp); - - title_update = 0; - } - - /* One more frame done! */ - done++; - - /* Every 200 frames we save the machine status. */ - if (++frames >= 200 && nvr_dosave) { - nvr_save(); - nvr_dosave = 0; - frames = 0; - } - - end_time = plat_timer_read(); - main_time += (end_time - start_time); - } else { - /* Just so we dont overload the host OS. */ - plat_delay_ms(1); - } - - /* If needed, handle a screen resize. */ - if (doresize && !video_fullscreen) { - plat_resize(scrnsz_x, scrnsz_y); - - doresize = 0; - } - } - - pc_log("PC: main thread done.\n"); -} - - -/* Handler for the 1-second timer to refresh the window title. */ -void -pc_onesec(void) -{ - fps = framecount; - framecount = 0; - - title_update = 1; -} - - -void -set_screen_size(int x, int y) -{ - int owsx = scrnsz_x; - int owsy = scrnsz_y; - int temp_overscan_x = overscan_x; - int temp_overscan_y = overscan_y; - double dx, dy, dtx, dty; - - /* Make sure we keep usable values. */ -#if 0 - pc_log("SetScreenSize(%d, %d) resize=%d\n", x, y, vid_resize); -#endif - if (x < 320) x = 320; - if (y < 200) y = 200; - if (x > 2048) x = 2048; - if (y > 2048) y = 2048; - - /* Save the new values as "real" (unscaled) resolution. */ - unscaled_size_x = x; - efscrnsz_y = y; - - if (suppress_overscan) - temp_overscan_x = temp_overscan_y = 0; - - if (force_43) { - dx = (double)x; - dtx = (double)temp_overscan_x; - - dy = (double)y; - dty = (double)temp_overscan_y; - - /* Account for possible overscan. */ - if (!(video_is_ega_vga()) && (temp_overscan_y == 16)) { - /* CGA */ - dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } else if (!(video_is_ega_vga()) && (temp_overscan_y < 16)) { - /* MDA/Hercules */ - dy = (x / 4.0) * 3.0; - } else { - if (enable_overscan) { - /* EGA/(S)VGA with overscan */ - dy = (((dx - dtx) / 4.0) * 3.0) + dty; - } else { - /* EGA/(S)VGA without overscan */ - dy = (x / 4.0) * 3.0; - } - } - unscaled_size_y = (int)dy; - } else { - unscaled_size_y = efscrnsz_y; - } - - switch(scale) { - case 0: /* 50% */ - scrnsz_x = (unscaled_size_x>>1); - scrnsz_y = (unscaled_size_y>>1); - break; - - case 1: /* 100% */ - scrnsz_x = unscaled_size_x; - scrnsz_y = unscaled_size_y; - break; - - case 2: /* 150% */ - scrnsz_x = ((unscaled_size_x*3)>>1); - scrnsz_y = ((unscaled_size_y*3)>>1); - break; - - case 3: /* 200% */ - scrnsz_x = (unscaled_size_x<<1); - scrnsz_y = (unscaled_size_y<<1); - break; - } - - /* If the resolution has changed, let the main thread handle it. */ - if ((owsx != scrnsz_x) || (owsy != scrnsz_y)) - doresize = 1; - else - doresize = 0; -} - - -void -set_screen_size_natural(void) -{ - set_screen_size(unscaled_size_x, unscaled_size_y); -} - - -int -get_actual_size_x(void) -{ - return(unscaled_size_x); -} - - -int -get_actual_size_y(void) -{ - return(efscrnsz_y); -} diff --git a/src/scsi - Cópia/scsi.c b/src/scsi - Cópia/scsi.c deleted file mode 100644 index 8fc535dc3..000000000 --- a/src/scsi - Cópia/scsi.c +++ /dev/null @@ -1,235 +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. - * - * Handling of the SCSI controllers. - * - * Version: @(#)scsi.c 1.0.20 2018/06/02 - * - * Authors: Miran Grca, - * Fred N. van Kempen, - * TheCollector1995, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" -#include "../device.h" -#include "../disk/hdc.h" -#include "../disk/hdd.h" -#include "../plat.h" -#include "scsi.h" -#include "../cdrom/cdrom.h" -#include "../disk/zip.h" -#include "scsi_disk.h" -#include "scsi_device.h" -#include "scsi_aha154x.h" -#include "scsi_buslogic.h" -#include "scsi_ncr5380.h" -#include "scsi_ncr53c810.h" -#ifdef WALTJE -# include "scsi_wd33c93.h" -#endif -#include "scsi_x54x.h" - - -scsi_device_t SCSIDevices[SCSI_ID_MAX]; -char scsi_fn[SCSI_NUM][512]; -uint16_t scsi_disk_location[SCSI_NUM]; - -int scsi_card_current = 0; -int scsi_card_last = 0; - -uint32_t SCSI_BufferLength; -static volatile -mutex_t *scsiMutex; - - -typedef const struct { - const char *name; - const char *internal_name; - const device_t *device; -} SCSI_CARD; - - -static SCSI_CARD scsi_cards[] = { - { "None", "none", NULL, }, - { "[ISA] Adaptec AHA-1540B","aha1540b", &aha1540b_device, }, - { "[ISA] Adaptec AHA-1542C","aha1542c", &aha1542c_device, }, - { "[ISA] Adaptec AHA-1542CF","aha1542cf", &aha1542cf_device, }, - { "[ISA] BusLogic BT-542BH","bt542bh", &buslogic_device, }, - { "[ISA] BusLogic BT-545S", "bt545s", &buslogic_545s_device,}, - { "[ISA] Longshine LCS-6821N","lcs6821n", &scsi_lcs6821n_device,}, - { "[ISA] Ranco RT1000B", "rt1000b", &scsi_rt1000b_device, }, - { "[ISA] Trantor T130B", "t130b", &scsi_t130b_device, }, - { "[ISA] Sumo SCSI-AT", "scsiat", &scsi_scsiat_device, }, -#ifdef WALTJE - { "[ISA] Generic WDC33C93", "wd33c93", &scsi_wd33c93_device, }, -#endif - { "[MCA] Adaptec AHA-1640", "aha1640", &aha1640_device, }, - { "[MCA] BusLogic BT-640A", "bt640a", &buslogic_640a_device,}, - { "[PCI] BusLogic BT-958D", "bt958d", &buslogic_pci_device, }, - { "[PCI] NCR 53C810", "ncr53c810", &ncr53c810_pci_device,}, - { "[VLB] BusLogic BT-445S", "bt445s", &buslogic_445s_device,}, - { "", "", NULL, }, -}; - - -#ifdef ENABLE_SCSI_LOG -int scsi_do_log = ENABLE_SCSI_LOG; -#endif - - -static void -scsi_log(const char *fmt, ...) -{ -#ifdef ENABLE_SCSI_LOG - va_list ap; - - if (scsi_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -int scsi_card_available(int card) -{ - if (scsi_cards[card].device) - return(device_available(scsi_cards[card].device)); - - return(1); -} - - -char *scsi_card_getname(int card) -{ - return((char *) scsi_cards[card].name); -} - - -const device_t *scsi_card_getdevice(int card) -{ - return(scsi_cards[card].device); -} - - -int scsi_card_has_config(int card) -{ - if (! scsi_cards[card].device) return(0); - - return(scsi_cards[card].device->config ? 1 : 0); -} - - -char *scsi_card_get_internal_name(int card) -{ - return((char *) scsi_cards[card].internal_name); -} - - -int scsi_card_get_from_internal_name(char *s) -{ - int c = 0; - - while (strlen((char *) scsi_cards[c].internal_name)) { - if (!strcmp((char *) scsi_cards[c].internal_name, s)) - return(c); - c++; - } - - return(0); -} - - -void scsi_mutex(uint8_t start) -{ - if (start) - scsiMutex = thread_create_mutex(L"86Box.SCSIMutex"); - else - thread_close_mutex((mutex_t *) scsiMutex); -} - - -void scsi_card_init(void) -{ - int i; - - if (!scsi_cards[scsi_card_current].device) - return; - - scsi_log("Building SCSI hard disk map...\n"); - build_scsi_disk_map(); - scsi_log("Building SCSI CD-ROM map...\n"); - build_scsi_cdrom_map(); - scsi_log("Building SCSI ZIP map...\n"); - build_scsi_zip_map(); - - for (i=0; i - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016-2018 TheCollector1995. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#ifndef EMU_SCSI_H -#define EMU_SCSI_H - - -#ifdef WALTJE -#define SCSI_TIME (50 * (1 << TIMER_SHIFT)) -#else -#define SCSI_TIME (5 * 100 * (1 << TIMER_SHIFT)) -#endif - - -/* Configuration. */ -#define SCSI_ID_MAX 16 /* 16 on wide buses */ -#define SCSI_LUN_MAX 8 /* always 8 */ - - -/* SCSI commands. */ -#define GPCMD_TEST_UNIT_READY 0x00 -#define GPCMD_REZERO_UNIT 0x01 -#define GPCMD_REQUEST_SENSE 0x03 -#define GPCMD_FORMAT_UNIT 0x04 -#define GPCMD_IOMEGA_SENSE 0x06 -#define GPCMD_READ_6 0x08 -#define GPCMD_WRITE_6 0x0a -#define GPCMD_SEEK_6 0x0b -#define GPCMD_IOMEGA_SET_PROTECTION_MODE 0x0c -#define GPCMD_IOMEGA_EJECT 0x0d /* ATAPI only? */ -#define GPCMD_INQUIRY 0x12 -#define GPCMD_VERIFY_6 0x13 -#define GPCMD_MODE_SELECT_6 0x15 -#define GPCMD_SCSI_RESERVE 0x16 -#define GPCMD_SCSI_RELEASE 0x17 -#define GPCMD_MODE_SENSE_6 0x1a -#define GPCMD_START_STOP_UNIT 0x1b -#define GPCMD_SEND_DIAGNOSTIC 0x1d -#define GPCMD_PREVENT_REMOVAL 0x1e -#define GPCMD_READ_FORMAT_CAPACITIES 0x23 -#define GPCMD_READ_CDROM_CAPACITY 0x25 -#define GPCMD_READ_10 0x28 -#define GPCMD_WRITE_10 0x2a -#define GPCMD_SEEK_10 0x2b -#define GPCMD_WRITE_AND_VERIFY_10 0x2e -#define GPCMD_VERIFY_10 0x2f -#define GPCMD_READ_BUFFER 0x3c -#define GPCMD_WRITE_SAME_10 0x41 -#define GPCMD_READ_SUBCHANNEL 0x42 -#define GPCMD_READ_TOC_PMA_ATIP 0x43 -#define GPCMD_READ_HEADER 0x44 -#define GPCMD_PLAY_AUDIO_10 0x45 -#define GPCMD_GET_CONFIGURATION 0x46 -#define GPCMD_PLAY_AUDIO_MSF 0x47 -#define GPCMD_PLAY_AUDIO_TRACK_INDEX 0x48 -#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a -#define GPCMD_PAUSE_RESUME 0x4b -#define GPCMD_STOP_PLAY_SCAN 0x4e -#define GPCMD_READ_DISC_INFORMATION 0x51 -#define GPCMD_READ_TRACK_INFORMATION 0x52 -#define GPCMD_MODE_SELECT_10 0x55 -#define GPCMD_MODE_SENSE_10 0x5a -#define GPCMD_PLAY_AUDIO_12 0xa5 -#define GPCMD_READ_12 0xa8 -#define GPCMD_WRITE_12 0xaa -#define GPCMD_READ_DVD_STRUCTURE 0xad /* For reading. */ -#define GPCMD_WRITE_AND_VERIFY_12 0xae -#define GPCMD_VERIFY_12 0xaf -#define GPCMD_PLAY_CD_OLD 0xb4 -#define GPCMD_READ_CD_OLD 0xb8 -#define GPCMD_READ_CD_MSF 0xb9 -#define GPCMD_SCAN 0xba -#define GPCMD_SET_SPEED 0xbb -#define GPCMD_PLAY_CD 0xbc -#define GPCMD_MECHANISM_STATUS 0xbd -#define GPCMD_READ_CD 0xbe -#define GPCMD_SEND_DVD_STRUCTURE 0xbf /* This is for writing only, irrelevant to PCem. */ -#define GPCMD_PAUSE_RESUME_ALT 0xc2 -#define GPCMD_SCAN_ALT 0xcd /* Should be equivalent to 0xba */ -#define GPCMD_SET_SPEED_ALT 0xda /* Should be equivalent to 0xbb */ - -/* Mode page codes for mode sense/set */ -#define GPMODE_R_W_ERROR_PAGE 0x01 -#define GPMODE_CDROM_PAGE 0x0d -#define GPMODE_CDROM_AUDIO_PAGE 0x0e -#define GPMODE_CAPABILITIES_PAGE 0x2a -#define GPMODE_ALL_PAGES 0x3f - -/* Mode page codes for presence */ -#define GPMODEP_R_W_ERROR_PAGE 0x0000000000000002LL -#define GPMODEP_UNK_PAGE_02 0x0000000000000004LL -#define GPMODEP_UNK_PAGE_03 0x0000000000000008LL -#define GPMODEP_UNK_PAGE_04 0x0000000000000010LL -#define GPMODEP_UNK_PAGE_05 0x0000000000000020LL -#define GPMODEP_UNK_PAGE_08 0x0000000000000100LL -#define GPMODEP_CDROM_PAGE 0x0000000000002000LL -#define GPMODEP_CDROM_AUDIO_PAGE 0x0000000000004000LL -#define GPMODEP_CAPABILITIES_PAGE 0x0000040000000000LL -#define GPMODEP_UNK_PAGE_2F 0x0000800000000000LL -#define GPMODEP_UNK_PAGE_30 0x0001000000000000LL -#define GPMODEP_ALL_PAGES 0x8000000000000000LL - -/* SCSI Status Codes */ -#define SCSI_STATUS_OK 0 -#define SCSI_STATUS_CHECK_CONDITION 2 - -/* SCSI Sense Keys */ -#define SENSE_NONE 0 -#define SENSE_NOT_READY 2 -#define SENSE_ILLEGAL_REQUEST 5 -#define SENSE_UNIT_ATTENTION 6 - -/* SCSI Additional Sense Codes */ -#define ASC_AUDIO_PLAY_OPERATION 0x00 -#define ASC_NOT_READY 0x04 -#define ASC_ILLEGAL_OPCODE 0x20 -#define ASC_LBA_OUT_OF_RANGE 0x21 -#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 -#define ASC_INV_LUN 0x25 -#define ASC_INV_FIELD_IN_PARAMETER_LIST 0x26 -#define ASC_WRITE_PROTECTED 0x27 -#define ASC_MEDIUM_MAY_HAVE_CHANGED 0x28 -#define ASC_CAPACITY_DATA_CHANGED 0x2A -#define ASC_INCOMPATIBLE_FORMAT 0x30 -#define ASC_MEDIUM_NOT_PRESENT 0x3a -#define ASC_DATA_PHASE_ERROR 0x4b -#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK 0x64 - -#define ASCQ_UNIT_IN_PROCESS_OF_BECOMING_READY 0x01 -#define ASCQ_INITIALIZING_COMMAND_REQUIRED 0x02 -#define ASCQ_CAPACITY_DATA_CHANGED 0x09 -#define ASCQ_AUDIO_PLAY_OPERATION_IN_PROGRESS 0x11 -#define ASCQ_AUDIO_PLAY_OPERATION_PAUSED 0x12 -#define ASCQ_AUDIO_PLAY_OPERATION_COMPLETED 0x13 - -/* Tell RISC OS that we have a 4x CD-ROM drive (600kb/sec data, 706kb/sec raw). - Not that it means anything */ -#define CDROM_SPEED 706 /* 0x2C2 */ - -#define BUFFER_SIZE (256*1024) - -#define RW_DELAY (TIMER_USEC * 500) - -/* Some generally useful CD-ROM information */ -#define CD_MINS 75 /* max. minutes per CD */ -#define CD_SECS 60 /* seconds per minute */ -#define CD_FRAMES 75 /* frames per second */ -#define CD_FRAMESIZE 2048 /* bytes per frame, "cooked" mode */ -#define CD_MAX_BYTES (CD_MINS * CD_SECS * CD_FRAMES * CD_FRAMESIZE) -#define CD_MAX_SECTORS (CD_MAX_BYTES / 512) - -/* Event notification classes for GET EVENT STATUS NOTIFICATION */ -#define GESN_NO_EVENTS 0 -#define GESN_OPERATIONAL_CHANGE 1 -#define GESN_POWER_MANAGEMENT 2 -#define GESN_EXTERNAL_REQUEST 3 -#define GESN_MEDIA 4 -#define GESN_MULTIPLE_HOSTS 5 -#define GESN_DEVICE_BUSY 6 - -/* Event codes for MEDIA event status notification */ -#define MEC_NO_CHANGE 0 -#define MEC_EJECT_REQUESTED 1 -#define MEC_NEW_MEDIA 2 -#define MEC_MEDIA_REMOVAL 3 /* only for media changers */ -#define MEC_MEDIA_CHANGED 4 /* only for media changers */ -#define MEC_BG_FORMAT_COMPLETED 5 /* MRW or DVD+RW b/g format completed */ -#define MEC_BG_FORMAT_RESTARTED 6 /* MRW or DVD+RW b/g format restarted */ -#define MS_TRAY_OPEN 1 -#define MS_MEDIA_PRESENT 2 - -/* - * The MMC values are not IDE specific and might need to be moved - * to a common header if they are also needed for the SCSI emulation - */ - -/* Profile list from MMC-6 revision 1 table 91 */ -#define MMC_PROFILE_NONE 0x0000 -#define MMC_PROFILE_CD_ROM 0x0008 -#define MMC_PROFILE_CD_R 0x0009 -#define MMC_PROFILE_CD_RW 0x000A -#define MMC_PROFILE_DVD_ROM 0x0010 -#define MMC_PROFILE_DVD_R_SR 0x0011 -#define MMC_PROFILE_DVD_RAM 0x0012 -#define MMC_PROFILE_DVD_RW_RO 0x0013 -#define MMC_PROFILE_DVD_RW_SR 0x0014 -#define MMC_PROFILE_DVD_R_DL_SR 0x0015 -#define MMC_PROFILE_DVD_R_DL_JR 0x0016 -#define MMC_PROFILE_DVD_RW_DL 0x0017 -#define MMC_PROFILE_DVD_DDR 0x0018 -#define MMC_PROFILE_DVD_PLUS_RW 0x001A -#define MMC_PROFILE_DVD_PLUS_R 0x001B -#define MMC_PROFILE_DVD_PLUS_RW_DL 0x002A -#define MMC_PROFILE_DVD_PLUS_R_DL 0x002B -#define MMC_PROFILE_BD_ROM 0x0040 -#define MMC_PROFILE_BD_R_SRM 0x0041 -#define MMC_PROFILE_BD_R_RRM 0x0042 -#define MMC_PROFILE_BD_RE 0x0043 -#define MMC_PROFILE_HDDVD_ROM 0x0050 -#define MMC_PROFILE_HDDVD_R 0x0051 -#define MMC_PROFILE_HDDVD_RAM 0x0052 -#define MMC_PROFILE_HDDVD_RW 0x0053 -#define MMC_PROFILE_HDDVD_R_DL 0x0058 -#define MMC_PROFILE_HDDVD_RW_DL 0x005A -#define MMC_PROFILE_INVALID 0xFFFF - -#define SCSI_ONLY 32 -#define ATAPI_ONLY 16 -#define IMPLEMENTED 8 -#define NONDATA 4 -#define CHECK_READY 2 -#define ALLOW_UA 1 - - -extern uint8_t SCSICommandTable[0x100]; -extern uint8_t mode_sense_pages[0x40]; -extern int readcdmode; - -/* Mode sense/select stuff. */ -extern uint8_t mode_pages_in[256][256]; -extern uint8_t page_flags[256]; -extern uint8_t prefix_len; -extern uint8_t page_current; -#define PAGE_CHANGEABLE 1 -#define PAGE_CHANGED 2 - -struct _scsisense_ { - uint8_t SenseBuffer[18]; - uint8_t SenseLength; - uint8_t UnitAttention; - uint8_t SenseKey; - uint8_t Asc; - uint8_t Ascq; -} SCSISense; - -extern int cd_status; -extern int prev_status; - -enum { - SCSI_NONE = 0, - SCSI_DISK, - SCSI_CDROM, - SCSI_ZIP -}; - -#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f) - -#define MSG_COMMAND_COMPLETE 0x00 - -#define BUS_DBP 0x01 -#define BUS_SEL 0x02 -#define BUS_IO 0x04 -#define BUS_CD 0x08 -#define BUS_MSG 0x10 -#define BUS_REQ 0x20 -#define BUS_BSY 0x40 -#define BUS_RST 0x80 -#define BUS_ACK 0x200 -#define BUS_ATN 0x200 -#define BUS_ARB 0x8000 -#define BUS_SETDATA(val) ((uint32_t)val << 16) -#define BUS_GETDATA(val) ((val >> 16) & 0xff) -#define BUS_DATAMASK 0xff0000 - -#define BUS_IDLE (1 << 31) - -#define SCSI_PHASE_DATA_OUT 0 -#define SCSI_PHASE_DATA_IN BUS_IO -#define SCSI_PHASE_COMMAND BUS_CD -#define SCSI_PHASE_STATUS (BUS_CD | BUS_IO) -#define SCSI_PHASE_MESSAGE_OUT (BUS_MSG | BUS_CD) -#define SCSI_PHASE_MESSAGE_IN (BUS_MSG | BUS_CD | BUS_IO) - -typedef struct { - uint8_t *CmdBuffer; - int LunType; - int32_t BufferLength; - uint8_t Status; - uint8_t Phase; -} scsi_device_t; - - -extern scsi_device_t SCSIDevices[SCSI_ID_MAX]; - -extern void SCSIReset(uint8_t id); - -extern int cdrom_add_error_and_subchannel(uint8_t *b, int real_sector_type); -extern int cdrom_LBAtoMSF_accurate(void); - -extern int mode_select_init(uint8_t command, uint16_t pl_length, uint8_t do_save); -extern int mode_select_terminate(int force); -extern int mode_select_write(uint8_t val); - -extern int scsi_card_current; - -extern int scsi_card_available(int card); -extern char *scsi_card_getname(int card); -#ifdef EMU_DEVICE_H -extern const device_t *scsi_card_getdevice(int card); -#endif -extern int scsi_card_has_config(int card); -extern char *scsi_card_get_internal_name(int card); -extern int scsi_card_get_from_internal_name(char *s); -extern void scsi_mutex(uint8_t start); -extern void scsi_card_init(void); - - -#pragma pack(push,1) -typedef struct { - uint8_t hi; - uint8_t mid; - uint8_t lo; -} addr24; -#pragma pack(pop) - -#define ADDR_TO_U32(x) (((x).hi<<16)|((x).mid<<8)|((x).lo&0xFF)) -#define U32_TO_ADDR(a,x) do {(a).hi=(x)>>16;(a).mid=(x)>>8;(a).lo=(x)&0xFF;}while(0) - - -/* - * - * Scatter/Gather Segment List Definitions - * - * Adapter limits - */ -#define MAX_SG_DESCRIPTORS 32 /* Always make the array 32 elements long, if less are used, that's not an issue. */ - -#pragma pack(push,1) -typedef struct { - uint32_t Segment; - uint32_t SegmentPointer; -} SGE32; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - addr24 Segment; - addr24 SegmentPointer; -} SGE; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t pages[0x40][0x40]; -} mode_sense_pages_t; -#pragma pack(pop) - - -#define MODE_SELECT_PHASE_IDLE 0 -#define MODE_SELECT_PHASE_HEADER 1 -#define MODE_SELECT_PHASE_BLOCK_DESC 2 -#define MODE_SELECT_PHASE_PAGE_HEADER 3 -#define MODE_SELECT_PHASE_PAGE 4 - -#endif /*EMU_SCSI_H*/ - -extern void scsi_mutex_wait(uint8_t wait); diff --git a/src/scsi - Cópia/scsi_aha154x.c b/src/scsi - Cópia/scsi_aha154x.c deleted file mode 100644 index 59e48129c..000000000 --- a/src/scsi - Cópia/scsi_aha154x.c +++ /dev/null @@ -1,1145 +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 AHA-154x series of SCSI Host Adapters - * made by Adaptec, Inc. These controllers were designed for - * the ISA bus. - * - * Version: @(#)scsi_aha154x.c 1.0.42 2018/06/12 - * - * Authors: Fred N. van Kempen, - * Original Buslogic version by SA1988 and Miran Grca. - * - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mca.h" -#include "../mem.h" -#include "../mca.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../dma.h" -#include "../pic.h" -#include "../timer.h" -#include "../plat.h" -#include "../cpu/cpu.h" -#include "scsi.h" -#include "scsi_aha154x.h" -#include "scsi_x54x.h" - - -enum { - AHA_154xB, - AHA_154xC, - AHA_154xCF, - AHA_154xCP, - AHA_1640 -}; - - -#define CMD_WRITE_EEPROM 0x22 /* UNDOC: Write EEPROM */ -#define CMD_READ_EEPROM 0x23 /* UNDOC: Read EEPROM */ -#define CMD_SHADOW_RAM 0x24 /* UNDOC: BIOS shadow ram */ -#define CMD_BIOS_MBINIT 0x25 /* UNDOC: BIOS mailbox initialization */ -#define CMD_MEMORY_MAP_1 0x26 /* UNDOC: Memory Mapper */ -#define CMD_MEMORY_MAP_2 0x27 /* UNDOC: Memory Mapper */ -#define CMD_EXTBIOS 0x28 /* UNDOC: return extended BIOS info */ -#define CMD_MBENABLE 0x29 /* set mailbox interface enable */ -#define CMD_BIOS_SCSI 0x82 /* start ROM BIOS SCSI command */ - - -uint16_t aha_ports[] = { - 0x0330, 0x0334, 0x0230, 0x0234, - 0x0130, 0x0134, 0x0000, 0x0000 -}; - - -#pragma pack(push,1) -typedef struct { - uint8_t CustomerSignature[20]; - uint8_t uAutoRetry; - uint8_t uBoardSwitches; - uint8_t uChecksum; - uint8_t uUnknown; - addr24 BIOSMailboxAddress; -} aha_setup_t; -#pragma pack(pop) - - -#ifdef ENABLE_AHA154X_LOG -int aha_do_log = ENABLE_AHA154X_LOG; -#endif - - -static void -aha_log(const char *fmt, ...) -{ -#ifdef ENABLE_AHA154X_LOG - va_list ap; - - if (aha_do_log) { - pclog("In %s mode: ",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -/* - * Write data to the BIOS space. - * - * AHA-1542C's and up have a feature where they map a 128-byte - * RAM space into the ROM BIOS' address space, and then use it - * as working memory. This function implements the writing to - * that memory. - * - * We enable/disable this memory through AHA command 0x24. - */ -static void -aha_mem_write(uint32_t addr, uint8_t val, void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - - addr &= 0x3fff; - - if ((addr >= dev->rom_shram) && (dev->shram_mode & 1)) - dev->shadow_ram[addr & (dev->rom_shramsz - 1)] = val; -} - - -static uint8_t -aha_mem_read(uint32_t addr, void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - rom_t *rom = &dev->bios; - - addr &= 0x3fff; - - if ((addr >= dev->rom_shram) && (dev->shram_mode & 2)) - return dev->shadow_ram[addr & (dev->rom_shramsz - 1)]; - - return(rom->rom[addr]); -} - - -static uint8_t -aha154x_shram(x54x_t *dev, uint8_t cmd) -{ - /* If not supported, give up. */ - if (dev->rom_shram == 0x0000) return(0x04); - - /* Bit 0 = Shadow RAM write enable; - Bit 1 = Shadow RAM read enable. */ - dev->shram_mode = cmd; - - /* Firmware expects 04 status. */ - return(0x04); -} - - -static void -aha_eeprom_save(x54x_t *dev) -{ - FILE *f; - - f = nvr_fopen(dev->nvr_path, L"wb"); - if (f) - { - fwrite(dev->nvr, 1, NVR_SIZE, f); - fclose(f); - f = NULL; - } -} - - -static uint8_t -aha154x_eeprom(x54x_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp) -{ - uint8_t r = 0xff; - int c; - - aha_log("%s: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n", - dev->name, cmd, arg, len, off); - - /* Only if we can handle it.. */ - if (dev->nvr == NULL) return(r); - - if (cmd == 0x22) { - /* Write data to the EEPROM. */ - for (c = 0; c < len; c++) - dev->nvr[(off + c) & 0xff] = bufp[c]; - r = 0; - - aha_eeprom_save(dev); - } - - if (cmd == 0x23) { - /* Read data from the EEPROM. */ - for (c = 0; c < len; c++) - bufp[c] = dev->nvr[(off + c) & 0xff]; - r = len; - } - - return(r); -} - - -/* Map either the main or utility (Select) ROM into the memory space. */ -static uint8_t -aha154x_mmap(x54x_t *dev, uint8_t cmd) -{ - aha_log("%s: MEMORY cmd=%02x\n", dev->name, cmd); - - switch(cmd) { - case 0x26: - /* Disable the mapper, so, set ROM1 active. */ - dev->bios.rom = dev->rom1; - break; - - case 0x27: - /* Enable the mapper, so, set ROM2 active. */ - dev->bios.rom = dev->rom2; - break; - } - - return(0); -} - - -static uint8_t -aha_get_host_id(void *p) -{ - x54x_t *dev = (x54x_t *)p; - - return dev->nvr[0] & 0x07; -} - - -static uint8_t -aha_get_irq(void *p) -{ - x54x_t *dev = (x54x_t *)p; - - return (dev->nvr[1] & 0x07) + 9; -} - - -static uint8_t -aha_get_dma(void *p) -{ - x54x_t *dev = (x54x_t *)p; - - return (dev->nvr[1] >> 4) & 0x07; -} - - -static uint8_t -aha_cmd_is_fast(void *p) -{ - x54x_t *dev = (x54x_t *)p; - - if (dev->Command == CMD_BIOS_SCSI) - return 1; - else - return 0; -} - - -static uint8_t -aha_fast_cmds(void *p, uint8_t cmd) -{ - x54x_t *dev = (x54x_t *)p; - - if (cmd == CMD_BIOS_SCSI) { - dev->BIOSMailboxReq++; - return 1; - } - - return 0; -} - - -static uint8_t -aha_param_len(void *p) -{ - x54x_t *dev = (x54x_t *)p; - - switch (dev->Command) { - case CMD_BIOS_MBINIT: - /* Same as 0x01 for AHA. */ - return sizeof(MailboxInit_t); - break; - - case CMD_SHADOW_RAM: - return 1; - break; - - case CMD_WRITE_EEPROM: - return 3+32; - break; - - case CMD_READ_EEPROM: - return 3; - - case CMD_MBENABLE: - return 2; - - default: - return 0; - } -} - - -static uint8_t -aha_cmds(void *p) -{ - x54x_t *dev = (x54x_t *)p; - MailboxInit_t *mbi; - - if (! dev->CmdParamLeft) { - aha_log("Running Operation Code 0x%02X\n", dev->Command); - switch (dev->Command) { - case CMD_WRITE_EEPROM: /* write EEPROM */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_eeprom(dev, - dev->Command, - dev->CmdBuf[0], - dev->CmdBuf[1], - dev->CmdBuf[2], - &(dev->CmdBuf[3])); - if (dev->DataReplyLeft == 0xff) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - - case CMD_READ_EEPROM: /* read EEPROM */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_eeprom(dev, - dev->Command, - dev->CmdBuf[0], - dev->CmdBuf[1], - dev->CmdBuf[2], - dev->DataBuf); - if (dev->DataReplyLeft == 0xff) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - - case CMD_SHADOW_RAM: /* Shadow RAM */ - /* - * For AHA1542CF, this is the command - * to play with the Shadow RAM. BIOS - * gives us one argument (00,02,03) - * and expects a 0x04 back in the INTR - * register. --FvK - */ - /* dev->Interrupt = aha154x_shram(dev,val); */ - dev->Interrupt = aha154x_shram(dev, dev->CmdBuf[0]); - break; - - case CMD_BIOS_MBINIT: /* BIOS Mailbox Initialization */ - /* Sent by CF BIOS. */ - dev->Mbx24bit = 1; - - mbi = (MailboxInit_t *)dev->CmdBuf; - - dev->BIOSMailboxInit = 1; - dev->BIOSMailboxCount = mbi->Count; - dev->BIOSMailboxOutAddr = ADDR_TO_U32(mbi->Address); - - aha_log("Initialize BIOS Mailbox: MBO=0x%08lx, %d entries at 0x%08lx\n", - dev->BIOSMailboxOutAddr, - mbi->Count, - ADDR_TO_U32(mbi->Address)); - - dev->Status &= ~STAT_INIT; - dev->DataReplyLeft = 0; - break; - - case CMD_MEMORY_MAP_1: /* AHA memory mapper */ - case CMD_MEMORY_MAP_2: /* AHA memory mapper */ - /* Sent by CF BIOS. */ - dev->DataReplyLeft = - aha154x_mmap(dev, dev->Command); - break; - - case CMD_EXTBIOS: /* Return extended BIOS information */ - dev->DataBuf[0] = 0x08; - dev->DataBuf[1] = dev->Lock; - dev->DataReplyLeft = 2; - break; - - case CMD_MBENABLE: /* Mailbox interface enable Command */ - dev->DataReplyLeft = 0; - if (dev->CmdBuf[1] == dev->Lock) { - if (dev->CmdBuf[0] & 1) { - dev->Lock = 1; - } else { - dev->Lock = 0; - } - } - break; - - case 0x2C: /* AHA-1542CP sends this */ - dev->DataBuf[0] = 0x00; - dev->DataReplyLeft = 1; - break; - - case 0x33: /* AHA-1542CP sends this */ - dev->DataBuf[0] = 0x00; - dev->DataBuf[1] = 0x00; - dev->DataBuf[2] = 0x00; - dev->DataBuf[3] = 0x00; - dev->DataReplyLeft = 256; - break; - - default: - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - } - - return 0; -} - - -static void -aha_setup_data(void *p) -{ - x54x_t *dev = (x54x_t *)p; - ReplyInquireSetupInformation *ReplyISI; - aha_setup_t *aha_setup; - - ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; - aha_setup = (aha_setup_t *)ReplyISI->VendorSpecificData; - - ReplyISI->fSynchronousInitiationEnabled = dev->sync & 1; - ReplyISI->fParityCheckingEnabled = dev->parity & 1; - - U32_TO_ADDR(aha_setup->BIOSMailboxAddress, dev->BIOSMailboxOutAddr); - aha_setup->uChecksum = 0xA3; - aha_setup->uUnknown = 0xC2; -} - - -static void -aha_do_bios_mail(x54x_t *dev) -{ - dev->MailboxIsBIOS = 1; - - if (!dev->BIOSMailboxCount) { - aha_log("aha_do_bios_mail(): No BIOS Mailboxes\n"); - return; - } - - /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ - for (dev->BIOSMailboxOutPosCur = 0; dev->BIOSMailboxOutPosCur < dev->BIOSMailboxCount; dev->BIOSMailboxOutPosCur++) { - if (x54x_mbo_process(dev)) - break; - } -} - - -static void -aha_callback(void *p) -{ - x54x_t *dev = (x54x_t *)p; - - if (dev->BIOSMailboxInit && dev->BIOSMailboxReq) - aha_do_bios_mail(dev); -} - - -static uint8_t -aha_mca_read(int port, void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - - return(dev->pos_regs[port & 7]); -} - - -static void -aha_mca_write(int port, uint8_t val, void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - - /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; - - /* Save the MCA register value. */ - dev->pos_regs[port & 7] = val; - - /* This is always necessary so that the old handler doesn't remain. */ - x54x_io_remove(dev, dev->Base, 4); - - /* Get the new assigned I/O base address. */ - dev->Base = (dev->pos_regs[3] & 7) << 8; - dev->Base |= ((dev->pos_regs[3] & 0xc0) ? 0x34 : 0x30); - - /* Save the new IRQ and DMA channel values. */ - dev->Irq = (dev->pos_regs[4] & 0x07) + 8; - dev->DmaChannel = dev->pos_regs[5] & 0x0f; - - /* Extract the BIOS ROM address info. */ - if (! (dev->pos_regs[2] & 0x80)) switch(dev->pos_regs[3] & 0x38) { - case 0x38: /* [1]=xx11 1xxx */ - dev->rom_addr = 0xDC000; - break; - - case 0x30: /* [1]=xx11 0xxx */ - dev->rom_addr = 0xD8000; - break; - - case 0x28: /* [1]=xx10 1xxx */ - dev->rom_addr = 0xD4000; - break; - - case 0x20: /* [1]=xx10 0xxx */ - dev->rom_addr = 0xD0000; - break; - - case 0x18: /* [1]=xx01 1xxx */ - dev->rom_addr = 0xCC000; - break; - - case 0x10: /* [1]=xx01 0xxx */ - dev->rom_addr = 0xC8000; - break; - } else { - /* Disabled. */ - dev->rom_addr = 0x000000; - } - - /* - * Get misc SCSI config stuff. For now, we are only - * interested in the configured HA target ID: - * - * pos[2]=111xxxxx = 7 - * pos[2]=000xxxxx = 0 - */ - dev->HostID = (dev->pos_regs[4] >> 5) & 0x07; - - /* - * SYNC mode is pos[2]=xxxx1xxx. - * - * SCSI Parity is pos[2]=xxx1xxxx. - */ - dev->sync = (dev->pos_regs[4] >> 3) & 1; - dev->parity = (dev->pos_regs[4] >> 4) & 1; - - /* - * The PS/2 Model 80 BIOS always enables a card if it finds one, - * even if no resources were assigned yet (because we only added - * the card, but have not run AutoConfig yet...) - * - * So, remove current address, if any. - */ - mem_mapping_disable(&dev->bios.mapping); - - /* Initialize the device if fully configured. */ - if (dev->pos_regs[2] & 0x01) { - /* Card enabled; register (new) I/O handler. */ - x54x_io_set(dev, dev->Base, 4); - - /* Reset the device. */ - x54x_reset_ctrl(dev, CTRL_HRST); - - /* Enable or disable the BIOS ROM. */ - if (dev->rom_addr != 0x000000) { - mem_mapping_enable(&dev->bios.mapping); - mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); - } - - /* Say hello. */ - aha_log("AHA-1640: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", - dev->Base, dev->Irq, dev->DmaChannel, dev->rom_addr, dev->HostID); - } -} - - -/* Initialize the board's ROM BIOS. */ -static void -aha_setbios(x54x_t *dev) -{ - uint32_t size; - uint32_t mask; - uint32_t temp; - FILE *f; - int i; - - /* Only if this device has a BIOS ROM. */ - if (dev->bios_path == NULL) return; - - /* Open the BIOS image file and make sure it exists. */ - aha_log("%s: loading BIOS from '%ls'\n", dev->name, dev->bios_path); - if ((f = rom_fopen(dev->bios_path, L"rb")) == NULL) { - aha_log("%s: BIOS ROM not found!\n", dev->name); - return; - } - - /* - * Manually load and process the ROM image. - * - * We *could* use the system "rom_init" function here, but for - * this special case, we can't: we may need WRITE access to the - * memory later on. - */ - (void)fseek(f, 0L, SEEK_END); - temp = ftell(f); - (void)fseek(f, 0L, SEEK_SET); - - /* Load first chunk of BIOS (which is the main BIOS, aka ROM1.) */ - dev->rom1 = malloc(ROM_SIZE); - (void)fread(dev->rom1, ROM_SIZE, 1, f); - temp -= ROM_SIZE; - if (temp > 0) { - dev->rom2 = malloc(ROM_SIZE); - (void)fread(dev->rom2, ROM_SIZE, 1, f); - temp -= ROM_SIZE; - } else { - dev->rom2 = NULL; - } - if (temp != 0) { - aha_log("%s: BIOS ROM size invalid!\n", dev->name); - free(dev->rom1); - if (dev->rom2 != NULL) - free(dev->rom2); - (void)fclose(f); - return; - } - temp = ftell(f); - if (temp > ROM_SIZE) - temp = ROM_SIZE; - (void)fclose(f); - - /* Adjust BIOS size in chunks of 2K, as per BIOS spec. */ - size = 0x10000; - if (temp <= 0x8000) - size = 0x8000; - if (temp <= 0x4000) - size = 0x4000; - if (temp <= 0x2000) - size = 0x2000; - mask = (size - 1); - aha_log("%s: BIOS at 0x%06lX, size %lu, mask %08lx\n", - dev->name, dev->rom_addr, size, mask); - - /* Initialize the ROM entry for this BIOS. */ - memset(&dev->bios, 0x00, sizeof(rom_t)); - - /* Enable ROM1 into the memory map. */ - dev->bios.rom = dev->rom1; - - /* Set up an address mask for this memory. */ - dev->bios.mask = mask; - - /* Map this system into the memory map. */ - mem_mapping_add(&dev->bios.mapping, dev->rom_addr, size, - aha_mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */ - aha_mem_write, NULL, NULL, - dev->bios.rom, MEM_MAPPING_EXTERNAL, dev); - mem_mapping_disable(&dev->bios.mapping); - - /* - * Patch the ROM BIOS image for stuff Adaptec deliberately - * made hard to understand. Well, maybe not, maybe it was - * their way of handling issues like these at the time.. - * - * Patch 1: emulate the I/O ADDR SW setting by patching a - * byte in the BIOS that indicates the I/O ADDR - * switch setting on the board. - */ - if (dev->rom_ioaddr != 0x0000) { - /* Look up the I/O address in the table. */ - for (i=0; i<8; i++) - if (aha_ports[i] == dev->Base) break; - if (i == 8) { - aha_log("%s: invalid I/O address %04x selected!\n", - dev->name, dev->Base); - return; - } - dev->bios.rom[dev->rom_ioaddr] = (uint8_t)i; - /* Negation of the DIP switches to satify the checksum. */ - dev->bios.rom[dev->rom_ioaddr + 1] = (uint8_t)((i ^ 0xff) + 1); - } -} - - -static void -aha_initnvr(x54x_t *dev) -{ - /* Initialize the on-board EEPROM. */ - dev->nvr[0] = dev->HostID; /* SCSI ID 7 */ - dev->nvr[0] |= (0x10 | 0x20 | 0x40); - dev->nvr[1] = dev->Irq-9; /* IRQ15 */ - dev->nvr[1] |= (dev->DmaChannel<<4); /* DMA6 */ - dev->nvr[2] = (EE2_HABIOS | /* BIOS enabled */ - EE2_DYNSCAN | /* scan bus */ - EE2_EXT1G | EE2_RMVOK); /* Imm return on seek */ - dev->nvr[3] = SPEED_50; /* speed 5.0 MB/s */ - dev->nvr[6] = (EE6_TERM | /* host term enable */ - EE6_RSTBUS); /* reset SCSI bus on boot*/ -} - - -/* Initialize the board's EEPROM (NVR.) */ -static void -aha_setnvr(x54x_t *dev) -{ - FILE *f; - - /* Only if this device has an EEPROM. */ - if (dev->nvr_path == NULL) return; - - /* Allocate and initialize the EEPROM. */ - dev->nvr = (uint8_t *)malloc(NVR_SIZE); - memset(dev->nvr, 0x00, NVR_SIZE); - - f = nvr_fopen(dev->nvr_path, L"rb"); - if (f) - { - fread(dev->nvr, 1, NVR_SIZE, f); - fclose(f); - f = NULL; - } - else - { - aha_initnvr(dev); - } -} - - -/* General initialization routine for all boards. */ -static void * -aha_init(const device_t *info) -{ - x54x_t *dev; - - /* Call common initializer. */ - dev = x54x_init(info); - - /* - * Set up the (initial) I/O address, IRQ and DMA info. - * - * Note that on MCA, configuration is handled by the BIOS, - * and so any info we get here will be overwritten by the - * MCA-assigned values later on! - */ - dev->Base = device_get_config_hex16("base"); - dev->Irq = device_get_config_int("irq"); - dev->DmaChannel = device_get_config_int("dma"); - dev->rom_addr = device_get_config_hex20("bios_addr"); - dev->HostID = 7; /* default HA ID */ - dev->setup_info_len = sizeof(aha_setup_t); - dev->max_id = 7; - dev->int_geom_writable = 0; - dev->cdrom_boot = 0; - dev->bit32 = 0; - dev->lba_bios = 0; - - dev->ven_callback = aha_callback; - dev->ven_cmd_is_fast = aha_cmd_is_fast; - dev->ven_fast_cmds = aha_fast_cmds; - dev->get_ven_param_len = aha_param_len; - dev->ven_cmds = aha_cmds; - dev->get_ven_data = aha_setup_data; - - strcpy(dev->vendor, "Adaptec"); - - /* Perform per-board initialization. */ - switch(dev->type) { - case AHA_154xB: - strcpy(dev->name, "AHA-154xB"); - switch(dev->Base) { - case 0x0330: - dev->bios_path = - L"roms/scsi/adaptec/aha1540b320_330.bin"; - break; - - case 0x0334: - dev->bios_path = - L"roms/scsi/adaptec/aha1540b320_334.bin"; - break; - } - dev->fw_rev = "A005"; /* The 3.2 microcode says A012. */ - /* This is configurable from the configuration for the 154xB, the rest of the controllers read it from the EEPROM. */ - dev->HostID = device_get_config_int("hostid"); - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; - - case AHA_154xC: - strcpy(dev->name, "AHA-154xC"); - dev->bios_path = L"roms/scsi/adaptec/aha1542c102.bin"; - dev->nvr_path = L"aha1542c.nvr"; - dev->fw_rev = "D001"; - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ - dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */ - dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ - dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ - dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; - - case AHA_154xCF: - strcpy(dev->name, "AHA-154xCF"); - dev->bios_path = L"roms/scsi/adaptec/aha1542cf211.bin"; - dev->nvr_path = L"aha1542cf.nvr"; - dev->fw_rev = "E001"; - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ - dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */ - dev->cdrom_boot = 1; - dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ - dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ - dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ - dev->ha_bps = 10000000.0; /* fast SCSI */ - break; - - case AHA_154xCP: - strcpy(dev->name, "AHA-154xCP"); - dev->bios_path = L"roms/scsi/adaptec/aha1542cp102.bin"; - dev->nvr_path = L"aha1540cp.nvr"; - dev->fw_rev = "F001"; - dev->rom_shram = 0x3F80; /* shadow RAM address base */ - dev->rom_shramsz = 128; /* size of shadow RAM */ - dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */ - dev->rom_fwhigh = 0x0055; /* firmware version (hi/lo) */ - dev->ven_get_host_id = aha_get_host_id; /* function to return host ID from EEPROM */ - dev->ven_get_irq = aha_get_irq; /* function to return IRQ from EEPROM */ - dev->ven_get_dma = aha_get_dma; /* function to return DMA channel from EEPROM */ - dev->ha_bps = 10000000.0; /* fast SCSI */ - break; - - case AHA_1640: - strcpy(dev->name, "AHA-1640"); - dev->bios_path = L"roms/scsi/adaptec/aha1640.bin"; - dev->fw_rev = "BB01"; - - dev->lba_bios = 1; - - /* Enable MCA. */ - dev->pos_regs[0] = 0x1F; /* MCA board ID */ - dev->pos_regs[1] = 0x0F; - mca_add(aha_mca_read, aha_mca_write, dev); - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; - } - - /* Initialize ROM BIOS if needed. */ - aha_setbios(dev); - - /* Initialize EEPROM (NVR) if needed. */ - aha_setnvr(dev); - - if (dev->Base != 0) { - /* Initialize the device. */ - x54x_device_reset(dev); - - if (!(dev->bus & DEVICE_MCA)) { - /* Register our address space. */ - x54x_io_set(dev, dev->Base, 4); - - /* Enable the memory. */ - if (dev->rom_addr != 0x000000) { - mem_mapping_enable(&dev->bios.mapping); - mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, ROM_SIZE); - } - } - } - - return(dev); -} - - -static const device_config_t aha_154xb_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x334, - { - { - "None", 0 - }, - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 9, - { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - }, - }, - { - "hostid", "Host ID", CONFIG_SELECTION, "", 7, - { - { - "0", 0 - }, - { - "1", 1 - }, - { - "2", 2 - }, - { - "3", 3 - }, - { - "4", 4 - }, - { - "5", 5 - }, - { - "6", 6 - }, - { - "7", 7 - }, - { - "" - } - }, - }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; - - -static const device_config_t aha_154x_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x334, - { - { - "None", 0 - }, - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 9, - { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "" - } - }, - }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; - - -const device_t aha1540b_device = { - "Adaptec AHA-1540B", - DEVICE_ISA | DEVICE_AT, - AHA_154xB, - aha_init, x54x_close, NULL, - NULL, NULL, NULL, - aha_154xb_config -}; - -const device_t aha1542c_device = { - "Adaptec AHA-1542C", - DEVICE_ISA | DEVICE_AT, - AHA_154xC, - aha_init, x54x_close, NULL, - NULL, NULL, NULL, - aha_154x_config -}; - -const device_t aha1542cf_device = { - "Adaptec AHA-1542CF", - DEVICE_ISA | DEVICE_AT, - AHA_154xCF, - aha_init, x54x_close, NULL, - NULL, NULL, NULL, - aha_154x_config -}; - -const device_t aha1640_device = { - "Adaptec AHA-1640", - DEVICE_MCA, - AHA_1640, - aha_init, x54x_close, NULL, - NULL, NULL, NULL, - NULL -}; diff --git a/src/scsi - Cópia/scsi_aha154x.h b/src/scsi - Cópia/scsi_aha154x.h deleted file mode 100644 index 73eb10b89..000000000 --- a/src/scsi - Cópia/scsi_aha154x.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SCSI_AHA154X_H -# define SCSI_AHA154X_H - - -extern const device_t aha1540b_device; -extern const device_t aha1542c_device; -extern const device_t aha1542cf_device; -extern const device_t aha1640_device; - -extern void aha_device_reset(void *p); - - -#endif /*SCSI_AHA154X_H*/ diff --git a/src/scsi - Cópia/scsi_buslogic.c b/src/scsi - Cópia/scsi_buslogic.c deleted file mode 100644 index bc5eb421c..000000000 --- a/src/scsi - Cópia/scsi_buslogic.c +++ /dev/null @@ -1,1856 +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. - * - * Emulation of BusLogic ISA and PCI SCSI controllers. Boards - * supported: - * - * 0 - BT-542BH ISA; - * 1 - BT-545S ISA; - * 2 - BT-958D PCI - * - * Version: @(#)scsi_buslogic.c 1.0.39 2018/06/11 - * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../mca.h" -#include "../mem.h" -#include "../mca.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../dma.h" -#include "../pic.h" -#include "../pci.h" -#include "../timer.h" -#include "../plat.h" -#include "scsi.h" -#include "scsi_buslogic.h" -#include "scsi_device.h" -#include "scsi_x54x.h" - - -/* - * Auto SCSI structure which is located - * in host adapter RAM and contains several - * configuration parameters. - */ -#pragma pack(push,1) -typedef struct { - uint8_t aInternalSignature[2]; - uint8_t cbInformation; - uint8_t aHostAdaptertype[6]; - uint8_t uReserved1; - uint8_t fFloppyEnabled :1, - fFloppySecondary :1, - fLevelSensitiveInterrupt:1, - uReserved2 :2, - uSystemRAMAreForBIOS :3; - uint8_t uDMAChannel :7, - fDMAAutoConfiguration :1, - uIrqChannel :7, - fIrqAutoConfiguration :1; - uint8_t uDMATransferRate; - uint8_t uSCSIId; - uint8_t uSCSIConfiguration; - uint8_t uBusOnDelay; - uint8_t uBusOffDelay; - uint8_t uBIOSConfiguration; - uint16_t u16DeviceEnabledMask; - uint16_t u16WidePermittedMask; - uint16_t u16FastPermittedMask; - uint16_t u16SynchronousPermittedMask; - uint16_t u16DisconnectPermittedMask; - uint16_t u16SendStartUnitCommandMask; - uint16_t u16IgnoreInBIOSScanMask; - unsigned char uPCIInterruptPin : 2; - unsigned char uHostAdapterIoPortAddress : 2; - uint8_t fRoundRobinScheme : 1; - uint8_t fVesaBusSpeedGreaterThan33MHz : 1; - uint8_t fVesaBurstWrite : 1; - uint8_t fVesaBurstRead : 1; - uint16_t u16UltraPermittedMask; - uint32_t uReserved5; - uint8_t uReserved6; - uint8_t uAutoSCSIMaximumLUN; - uint8_t fReserved7 : 1; - uint8_t fSCAMDominant : 1; - uint8_t fSCAMenabled : 1; - uint8_t fSCAMLevel2 : 1; - unsigned char uReserved8 : 4; - uint8_t fInt13Extension : 1; - uint8_t fReserved9 : 1; - uint8_t fCDROMBoot : 1; - unsigned char uReserved10 : 2; - uint8_t fMultiBoot : 1; - unsigned char uReserved11 : 2; - unsigned char uBootTargetId : 4; - unsigned char uBootChannel : 4; - uint8_t fForceBusDeviceScanningOrder : 1; - unsigned char uReserved12 : 7; - uint16_t u16NonTaggedToAlternateLunPermittedMask; - uint16_t u16RenegotiateSyncAfterCheckConditionMask; - uint8_t aReserved14[10]; - uint8_t aManufacturingDiagnostic[2]; - uint16_t u16Checksum; -} AutoSCSIRam; -#pragma pack(pop) - -/* The local RAM. */ -#pragma pack(push,1) -typedef union { - uint8_t u8View[256]; /* byte view */ - struct { /* structured view */ - uint8_t u8Bios[64]; /* offset 0 - 63 is for BIOS */ - AutoSCSIRam autoSCSIData; /* Auto SCSI structure */ - } structured; -} HALocalRAM; -#pragma pack(pop) - -/** Structure for the INQUIRE_SETUP_INFORMATION reply. */ -#pragma pack(push,1) -typedef struct { - uint8_t uSignature; - uint8_t uCharacterD; - uint8_t uHostBusType; - uint8_t uWideTransferPermittedId0To7; - uint8_t uWideTransfersActiveId0To7; - ReplyInquireSetupInformationSynchronousValue SynchronousValuesId8To15[8]; - uint8_t uDisconnectPermittedId8To15; - uint8_t uReserved2; - uint8_t uWideTransferPermittedId8To15; - uint8_t uWideTransfersActiveId8To15; -} buslogic_setup_t; -#pragma pack(pop) - -/* Structure for the INQUIRE_EXTENDED_SETUP_INFORMATION. */ -#pragma pack(push,1) -typedef struct { - uint8_t uBusType; - uint8_t uBiosAddress; - uint16_t u16ScatterGatherLimit; - uint8_t cMailbox; - uint32_t uMailboxAddressBase; - uint8_t uReserved1 :2, - fFastEISA :1, - uReserved2 :3, - fLevelSensitiveInterrupt:1, - uReserved3 :1; - uint8_t aFirmwareRevision[3]; - uint8_t fHostWideSCSI :1, - fHostDifferentialSCSI :1, - fHostSupportsSCAM :1, - fHostUltraSCSI :1, - fHostSmartTermination :1, - uReserved4 :3; -} ReplyInquireExtendedSetupInformation; -#pragma pack(pop) - -/* Structure for the INQUIRE_PCI_HOST_ADAPTER_INFORMATION reply. */ -#pragma pack(push,1) -typedef struct { - uint8_t IsaIOPort; - uint8_t IRQ; - uint8_t LowByteTerminated :1, - HighByteTerminated :1, - uReserved :2, /* Reserved. */ - JP1 :1, /* Whatever that means. */ - JP2 :1, /* Whatever that means. */ - JP3 :1, /* Whatever that means. */ - InformationIsValid :1; - uint8_t uReserved2; /* Reserved. */ -} BuslogicPCIInformation_t; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct -{ - /** Data length. */ - uint32_t DataLength; - /** Data pointer. */ - uint32_t DataPointer; - /** The device the request is sent to. */ - uint8_t TargetId; - /** The LUN in the device. */ - uint8_t LogicalUnit; - /** Reserved */ - unsigned char Reserved1 : 3; - /** Data direction for the request. */ - unsigned char DataDirection : 2; - /** Reserved */ - unsigned char Reserved2 : 3; - /** Length of the SCSI CDB. */ - uint8_t CDBLength; - /** The SCSI CDB. (A CDB can be 12 bytes long.) */ - uint8_t CDB[12]; -} ESCMD; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Count; - uint32_t Address; -} MailboxInitExtended_t; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - rom_t bios; - int ExtendedLUNCCBFormat; - int fAggressiveRoundRobinMode; - HALocalRAM LocalRAM; - int PCIBase; - int MMIOBase; - int chip; - int has_bios; - uint32_t bios_addr, - bios_size, - bios_mask; - uint8_t AutoSCSIROM[32768]; - uint8_t SCAMData[65536]; -} buslogic_data_t; -#pragma pack(pop) - - -enum { - CHIP_BUSLOGIC_ISA_542, - CHIP_BUSLOGIC_ISA, - CHIP_BUSLOGIC_MCA, - CHIP_BUSLOGIC_EISA, - CHIP_BUSLOGIC_VLB, - CHIP_BUSLOGIC_PCI -}; - - -#ifdef ENABLE_BUSLOGIC_LOG -int buslogic_do_log = ENABLE_BUSLOGIC_LOG; -#endif - - -static void -buslogic_log(const char *fmt, ...) -{ -#ifdef ENABLE_BUSLOGIC_LOG - va_list ap; - - if (buslogic_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -static wchar_t * -BuslogicGetNVRFileName(buslogic_data_t *bl) -{ - switch(bl->chip) - { - case CHIP_BUSLOGIC_ISA_542: - return L"bt542bh.nvr"; - case CHIP_BUSLOGIC_ISA: - return L"bt545s.nvr"; - case CHIP_BUSLOGIC_MCA: - return L"bt640a.nvr"; - case CHIP_BUSLOGIC_VLB: - return L"bt445s.nvr"; - case CHIP_BUSLOGIC_PCI: - return L"bt958d.nvr"; - default: - fatal("Unrecognized BusLogic chip: %i\n", bl->chip); - return NULL; - } -} - - -static void -BuslogicAutoSCSIRamSetDefaults(x54x_t *dev, uint8_t safe) -{ - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - HALocalRAM *HALR = &bl->LocalRAM; - - memset(&(HALR->structured.autoSCSIData), 0, sizeof(AutoSCSIRam)); - - HALR->structured.autoSCSIData.aInternalSignature[0] = 'F'; - HALR->structured.autoSCSIData.aInternalSignature[1] = 'A'; - - HALR->structured.autoSCSIData.cbInformation = 64; - - HALR->structured.autoSCSIData.uReserved1 = 6; - - HALR->structured.autoSCSIData.aHostAdaptertype[0] = ' '; - HALR->structured.autoSCSIData.aHostAdaptertype[5] = ' '; - switch (bl->chip) { - case CHIP_BUSLOGIC_ISA_542: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "542BH", 5); - break; - case CHIP_BUSLOGIC_ISA: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "545S", 4); - break; - case CHIP_BUSLOGIC_MCA: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "640A", 4); - break; - case CHIP_BUSLOGIC_VLB: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "445S", 4); - break; - case CHIP_BUSLOGIC_PCI: - memcpy(&(HALR->structured.autoSCSIData.aHostAdaptertype[1]), "958D", 4); - break; - } - - HALR->structured.autoSCSIData.fLevelSensitiveInterrupt = (bl->chip == CHIP_BUSLOGIC_PCI) ? 1 : 0; - HALR->structured.autoSCSIData.uSystemRAMAreForBIOS = 6; - - if (bl->chip != CHIP_BUSLOGIC_PCI) { - switch(dev->DmaChannel) { - case 5: - HALR->structured.autoSCSIData.uDMAChannel = 1; - break; - case 6: - HALR->structured.autoSCSIData.uDMAChannel = 2; - break; - case 7: - HALR->structured.autoSCSIData.uDMAChannel = 3; - break; - default: - HALR->structured.autoSCSIData.uDMAChannel = 0; - break; - } - } - HALR->structured.autoSCSIData.fDMAAutoConfiguration = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 1; - - if (bl->chip != CHIP_BUSLOGIC_PCI) { - switch(dev->Irq) { - case 9: - HALR->structured.autoSCSIData.uIrqChannel = 1; - break; - case 10: - HALR->structured.autoSCSIData.uIrqChannel = 2; - break; - case 11: - HALR->structured.autoSCSIData.uIrqChannel = 3; - break; - case 12: - HALR->structured.autoSCSIData.uIrqChannel = 4; - break; - case 14: - HALR->structured.autoSCSIData.uIrqChannel = 5; - break; - case 15: - HALR->structured.autoSCSIData.uIrqChannel = 6; - break; - default: - HALR->structured.autoSCSIData.uIrqChannel = 0; - break; - } - } - HALR->structured.autoSCSIData.fIrqAutoConfiguration = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 1; - - HALR->structured.autoSCSIData.uDMATransferRate = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 1; - - HALR->structured.autoSCSIData.uSCSIId = 7; - HALR->structured.autoSCSIData.uSCSIConfiguration = 0x3F; - HALR->structured.autoSCSIData.uBusOnDelay = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 7; - HALR->structured.autoSCSIData.uBusOffDelay = (bl->chip == CHIP_BUSLOGIC_PCI) ? 0 : 4; - HALR->structured.autoSCSIData.uBIOSConfiguration = (bl->has_bios) ? 0x33 : 0x32; - if (!safe) - HALR->structured.autoSCSIData.uBIOSConfiguration |= 0x04; - - HALR->structured.autoSCSIData.u16DeviceEnabledMask = 0xffff; - HALR->structured.autoSCSIData.u16WidePermittedMask = 0xffff; - HALR->structured.autoSCSIData.u16FastPermittedMask = 0xffff; - HALR->structured.autoSCSIData.u16DisconnectPermittedMask = 0xffff; - - HALR->structured.autoSCSIData.uPCIInterruptPin = PCI_INTA; - HALR->structured.autoSCSIData.fVesaBusSpeedGreaterThan33MHz = 1; - - HALR->structured.autoSCSIData.uAutoSCSIMaximumLUN = 7; - - HALR->structured.autoSCSIData.fForceBusDeviceScanningOrder = 1; - HALR->structured.autoSCSIData.fInt13Extension = safe ? 0 : 1; - HALR->structured.autoSCSIData.fCDROMBoot = safe ? 0 : 1; - HALR->structured.autoSCSIData.fMultiBoot = safe ? 0 : 1; - HALR->structured.autoSCSIData.fRoundRobinScheme = safe ? 1 : 0; /* 1 = aggressive, 0 = strict */ - - HALR->structured.autoSCSIData.uHostAdapterIoPortAddress = 2; /* 0 = primary (330h), 1 = secondary (334h), 2 = disable, 3 = reserved */ -} - - -static void -BuslogicInitializeAutoSCSIRam(x54x_t *dev) -{ - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - HALocalRAM *HALR = &bl->LocalRAM; - - FILE *f; - - f = nvr_fopen(BuslogicGetNVRFileName(bl), L"rb"); - if (f) - { - fread(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f); - fclose(f); - f = NULL; - if (bl->chip == CHIP_BUSLOGIC_PCI) { - x54x_io_remove(dev, dev->Base, 4); - switch(HALR->structured.autoSCSIData.uHostAdapterIoPortAddress) { - case 0: - dev->Base = 0x330; - break; - case 1: - dev->Base = 0x334; - break; - default: - dev->Base = 0; - break; - } - x54x_io_set(dev, dev->Base, 4); - } - } - else - { - BuslogicAutoSCSIRamSetDefaults(dev, 0); - } -} - - -static void -buslogic_cmd_phase1(void *p) -{ - x54x_t *dev = (x54x_t *)p; - - if ((dev->CmdParam == 2) && (dev->Command == 0x90)) { - dev->CmdParamLeft = dev->CmdBuf[1]; - } - - if ((dev->CmdParam == 10) && ((dev->Command == 0x97) || (dev->Command == 0xA7))) { - dev->CmdParamLeft = dev->CmdBuf[6]; - dev->CmdParamLeft <<= 8; - dev->CmdParamLeft |= dev->CmdBuf[7]; - dev->CmdParamLeft <<= 8; - dev->CmdParamLeft |= dev->CmdBuf[8]; - } - - if ((dev->CmdParam == 4) && (dev->Command == 0xA9)) { - dev->CmdParamLeft = dev->CmdBuf[3]; - dev->CmdParamLeft <<= 8; - dev->CmdParamLeft |= dev->CmdBuf[2]; - } -} - - -static uint8_t -buslogic_get_host_id(void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - HALocalRAM *HALR = &bl->LocalRAM; - - if (bl->chip == CHIP_BUSLOGIC_ISA_542) - return dev->HostID; - else - return HALR->structured.autoSCSIData.uSCSIId; -} - - -static uint8_t -buslogic_get_irq(void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - uint8_t bl_irq[7] = { 0, 9, 10, 11, 12, 14, 15 }; - - HALocalRAM *HALR = &bl->LocalRAM; - - if ((bl->chip == CHIP_BUSLOGIC_ISA_542) || (bl->chip == CHIP_BUSLOGIC_PCI)) - return dev->Irq; - else - return bl_irq[HALR->structured.autoSCSIData.uIrqChannel]; -} - - -static uint8_t -buslogic_get_dma(void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - uint8_t bl_dma[4] = { 0, 5, 6, 7 }; - - HALocalRAM *HALR = &bl->LocalRAM; - - if (bl->chip == CHIP_BUSLOGIC_PCI) - return (dev->Base ? 7 : 0); - else if (bl->chip == CHIP_BUSLOGIC_ISA_542) - return dev->DmaChannel; - else - return bl_dma[HALR->structured.autoSCSIData.uDMAChannel]; -} - - -static uint8_t -buslogic_param_len(void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - switch (dev->Command) { - case 0x21: - return 5; - case 0x25: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8F: - case 0x92: - case 0x96: - return 1; - case 0x81: - return sizeof(MailboxInitExtended_t); - case 0x83: - return 12; - case 0x90: - case 0x91: - return 2; - case 0x94: - case 0xFB: - return 3; - case 0x93: /* Valid only for VLB */ - return (bl->chip == CHIP_BUSLOGIC_VLB) ? 1 : 0; - case 0x95: /* Valid only for PCI */ - return (bl->chip == CHIP_BUSLOGIC_PCI) ? 1 : 0; - case 0x97: /* Valid only for PCI */ - case 0xA7: /* Valid only for PCI */ - return (bl->chip == CHIP_BUSLOGIC_PCI) ? 10 : 0; - case 0xA8: /* Valid only for PCI */ - case 0xA9: /* Valid only for PCI */ - return (bl->chip == CHIP_BUSLOGIC_PCI) ? 4 : 0; - default: - return 0; - } -} - - -static void -BuslogicSCSIBIOSDMATransfer(ESCMD *ESCSICmd, uint8_t TargetID, int dir) -{ - uint32_t DataPointer = ESCSICmd->DataPointer; - int DataLength = ESCSICmd->DataLength; - uint32_t Address; - uint32_t TransferLength; - - if (ESCSICmd->DataDirection == 0x03) { - /* Non-data command. */ - buslogic_log("BuslogicSCSIBIOSDMATransfer(): Non-data control byte\n"); - return; - } - - buslogic_log("BuslogicSCSIBIOSDMATransfer(): BIOS Data Buffer read: length %d, pointer 0x%04X\n", DataLength, DataPointer); - - /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without - checking its length, so do this procedure for both read/write commands. */ - if ((DataLength > 0) && (SCSIDevices[TargetID].BufferLength > 0)) { - Address = DataPointer; - TransferLength = MIN(DataLength, SCSIDevices[TargetID].BufferLength); - - if (dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_OUT) || (ESCSICmd->DataDirection == 0x00))) { - buslogic_log("BusLogic BIOS DMA: Reading %i bytes from %08X\n", TransferLength, Address); - DMAPageRead(Address, (uint8_t *)SCSIDevices[TargetID].CmdBuffer, TransferLength); - } else if (!dir && ((ESCSICmd->DataDirection == CCB_DATA_XFER_IN) || (ESCSICmd->DataDirection == 0x00))) { - buslogic_log("BusLogic BIOS DMA: Writing %i bytes at %08X\n", TransferLength, Address); - DMAPageWrite(Address, (uint8_t *)SCSIDevices[TargetID].CmdBuffer, TransferLength); - } - } -} - - -static void -BuslogicSCSIBIOSRequestSetup(x54x_t *dev, uint8_t *CmdBuf, uint8_t *DataInBuf, uint8_t DataReply) -{ - ESCMD *ESCSICmd = (ESCMD *)CmdBuf; - uint32_t i; - uint8_t temp_cdb[12]; - int target_cdb_len = 12; - uint8_t target_id = 0; - int phase; - - DataInBuf[0] = DataInBuf[1] = 0; - - if ((ESCSICmd->TargetId > 15) || (ESCSICmd->LogicalUnit > 7)) { - DataInBuf[2] = CCB_INVALID_CCB; - DataInBuf[3] = SCSI_STATUS_OK; - return; - } - - buslogic_log("Scanning SCSI Target ID %i\n", ESCSICmd->TargetId); - - SCSIDevices[ESCSICmd->TargetId].Status = SCSI_STATUS_OK; - - if (!scsi_device_present(ESCSICmd->TargetId)) { - buslogic_log("SCSI Target ID %i has no device attached\n", ESCSICmd->TargetId); - DataInBuf[2] = CCB_SELECTION_TIMEOUT; - DataInBuf[3] = SCSI_STATUS_OK; - } else { - buslogic_log("SCSI Target ID %i detected and working\n", ESCSICmd->TargetId); - - buslogic_log("Transfer Control %02X\n", ESCSICmd->DataDirection); - buslogic_log("CDB Length %i\n", ESCSICmd->CDBLength); - if (ESCSICmd->DataDirection > 0x03) { - buslogic_log("Invalid control byte: %02X\n", - ESCSICmd->DataDirection); - } - } - - x54x_buf_alloc(ESCSICmd->TargetId, ESCSICmd->DataLength); - - target_cdb_len = 12; - - if (!scsi_device_valid(ESCSICmd->TargetId)) fatal("SCSI target on ID %02i has disappeared\n", ESCSICmd->TargetId); - - buslogic_log("SCSI target command being executed on: SCSI ID %i, SCSI LUN %i, Target %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, target_id); - - buslogic_log("SCSI Cdb[0]=0x%02X\n", ESCSICmd->CDB[0]); - for (i = 1; i < ESCSICmd->CDBLength; i++) { - buslogic_log("SCSI Cdb[%i]=%i\n", i, ESCSICmd->CDB[i]); - } - - memset(temp_cdb, 0, target_cdb_len); - if (ESCSICmd->CDBLength <= target_cdb_len) { - memcpy(temp_cdb, ESCSICmd->CDB, ESCSICmd->CDBLength); - } else { - memcpy(temp_cdb, ESCSICmd->CDB, target_cdb_len); - } - - SCSIDevices[ESCSICmd->TargetId].BufferLength = ESCSICmd->DataLength; - scsi_device_command_phase0(ESCSICmd->TargetId, temp_cdb); - - phase = SCSIDevices[ESCSICmd->TargetId].Phase; - if (phase != SCSI_PHASE_STATUS) { - if (phase == SCSI_PHASE_DATA_IN) - scsi_device_command_phase1(ESCSICmd->TargetId); - BuslogicSCSIBIOSDMATransfer(ESCSICmd, ESCSICmd->TargetId, (phase == SCSI_PHASE_DATA_OUT)); - if (phase == SCSI_PHASE_DATA_OUT) - scsi_device_command_phase1(ESCSICmd->TargetId); - } - - x54x_buf_free(ESCSICmd->TargetId); - - buslogic_log("BIOS Request complete\n"); - - if (SCSIDevices[ESCSICmd->TargetId].Status == SCSI_STATUS_OK) { - DataInBuf[2] = CCB_COMPLETE; - DataInBuf[3] = SCSI_STATUS_OK; - } else if (SCSIDevices[ESCSICmd->TargetId].Status == SCSI_STATUS_CHECK_CONDITION) { - DataInBuf[2] = CCB_COMPLETE; - DataInBuf[3] = SCSI_STATUS_CHECK_CONDITION; - } - - dev->DataReplyLeft = DataReply; -} - - -static uint8_t -buslogic_cmds(void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - HALocalRAM *HALR = &bl->LocalRAM; - - FILE *f; - uint16_t TargetsPresentMask = 0; - uint32_t Offset; - int i = 0; - MailboxInitExtended_t *MailboxInitE; - ReplyInquireExtendedSetupInformation *ReplyIESI; - BuslogicPCIInformation_t *ReplyPI; - int cCharsToTransfer; - - switch (dev->Command) { - case 0x20: - dev->DataReplyLeft = 0; - x54x_reset_ctrl(dev, 1); - break; - case 0x21: - if (dev->CmdParam == 1) - dev->CmdParamLeft = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - break; - case 0x23: - memset(dev->DataBuf, 0, 8); - for (i = 8; i < 15; i++) { - dev->DataBuf[i-8] = 0; - if (scsi_device_present(i) && (i != buslogic_get_host_id(dev))) - dev->DataBuf[i-8] |= 1; - } - dev->DataReplyLeft = 8; - break; - case 0x24: - for (i=0; i<15; i++) { - if (scsi_device_present(i) && (i != buslogic_get_host_id(dev))) - TargetsPresentMask |= (1 << i); - } - dev->DataBuf[0] = TargetsPresentMask & 0xFF; - dev->DataBuf[1] = TargetsPresentMask >> 8; - dev->DataReplyLeft = 2; - break; - case 0x25: - if (dev->CmdBuf[0] == 0) - dev->IrqEnabled = 0; - else - dev->IrqEnabled = 1; - return 1; - case 0x81: - dev->Mbx24bit = 0; - - MailboxInitE = (MailboxInitExtended_t *)dev->CmdBuf; - - dev->MailboxInit = 1; - dev->MailboxCount = MailboxInitE->Count; - dev->MailboxOutAddr = MailboxInitE->Address; - dev->MailboxInAddr = MailboxInitE->Address + (dev->MailboxCount * sizeof(Mailbox32_t)); - - buslogic_log("Buslogic Extended Initialize Mailbox Command\n"); - buslogic_log("Mailbox Out Address=0x%08X\n", dev->MailboxOutAddr); - buslogic_log("Mailbox In Address=0x%08X\n", dev->MailboxInAddr); - buslogic_log("Initialized Extended Mailbox, %d entries at 0x%08X\n", MailboxInitE->Count, MailboxInitE->Address); - - dev->Status &= ~STAT_INIT; - dev->DataReplyLeft = 0; - break; - case 0x83: - if (dev->CmdParam == 12) { - dev->CmdParamLeft = dev->CmdBuf[11]; - buslogic_log("Execute SCSI BIOS Command: %u more bytes follow\n", dev->CmdParamLeft); - } else { - buslogic_log("Execute SCSI BIOS Command: received %u bytes\n", dev->CmdBuf[0]); - BuslogicSCSIBIOSRequestSetup(dev, dev->CmdBuf, dev->DataBuf, 4); - } - break; - case 0x84: - dev->DataBuf[0] = dev->fw_rev[4]; - dev->DataReplyLeft = 1; - break; - case 0x85: - if (strlen(dev->fw_rev) == 6) - dev->DataBuf[0] = dev->fw_rev[5]; - else - dev->DataBuf[0] = ' '; - dev->DataReplyLeft = 1; - break; - case 0x86: - if (bl->chip == CHIP_BUSLOGIC_PCI) { - ReplyPI = (BuslogicPCIInformation_t *) dev->DataBuf; - memset(ReplyPI, 0, sizeof(BuslogicPCIInformation_t)); - ReplyPI->InformationIsValid = 0; - switch(dev->Base) { - case 0x330: - ReplyPI->IsaIOPort = 0; - break; - case 0x334: - ReplyPI->IsaIOPort = 1; - break; - case 0x230: - ReplyPI->IsaIOPort = 2; - break; - case 0x234: - ReplyPI->IsaIOPort = 3; - break; - case 0x130: - ReplyPI->IsaIOPort = 4; - break; - case 0x134: - ReplyPI->IsaIOPort = 5; - break; - default: - ReplyPI->IsaIOPort = 6; - break; - } - ReplyPI->IRQ = dev->Irq; - dev->DataReplyLeft = sizeof(BuslogicPCIInformation_t); - } else { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - case 0x8B: - /* The reply length is set by the guest and is found in the first byte of the command buffer. */ - dev->DataReplyLeft = dev->CmdBuf[0]; - memset(dev->DataBuf, 0, dev->DataReplyLeft); - if (bl->chip == CHIP_BUSLOGIC_ISA_542) - i = 5; - else - i = 4; - cCharsToTransfer = MIN(dev->DataReplyLeft, i); - - memcpy(dev->DataBuf, &(bl->LocalRAM.structured.autoSCSIData.aHostAdaptertype[1]), cCharsToTransfer); - break; - case 0x8C: - dev->DataReplyLeft = dev->CmdBuf[0]; - memset(dev->DataBuf, 0, dev->DataReplyLeft); - break; - case 0x8D: - dev->DataReplyLeft = dev->CmdBuf[0]; - ReplyIESI = (ReplyInquireExtendedSetupInformation *)dev->DataBuf; - memset(ReplyIESI, 0, sizeof(ReplyInquireExtendedSetupInformation)); - - switch (bl->chip) { - case CHIP_BUSLOGIC_ISA_542: - case CHIP_BUSLOGIC_ISA: - case CHIP_BUSLOGIC_VLB: - ReplyIESI->uBusType = 'A'; /* ISA style */ - break; - case CHIP_BUSLOGIC_MCA: - ReplyIESI->uBusType = 'M'; /* MCA style */ - break; - case CHIP_BUSLOGIC_PCI: - ReplyIESI->uBusType = 'E'; /* PCI style */ - break; - } - ReplyIESI->uBiosAddress = 0xd8; - ReplyIESI->u16ScatterGatherLimit = 8192; - ReplyIESI->cMailbox = dev->MailboxCount; - ReplyIESI->uMailboxAddressBase = dev->MailboxOutAddr; - ReplyIESI->fHostWideSCSI = 1; /* This should be set for the BT-542B as well. */ - if ((bl->chip != CHIP_BUSLOGIC_ISA_542) && (bl->chip != CHIP_BUSLOGIC_MCA)) - ReplyIESI->fLevelSensitiveInterrupt = bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; - if (bl->chip == CHIP_BUSLOGIC_PCI) - ReplyIESI->fHostUltraSCSI = 1; - memcpy(ReplyIESI->aFirmwareRevision, &(dev->fw_rev[strlen(dev->fw_rev) - 3]), sizeof(ReplyIESI->aFirmwareRevision)); - buslogic_log("Return Extended Setup Information: %d\n", dev->CmdBuf[0]); - break; - case 0x8F: - bl->fAggressiveRoundRobinMode = dev->CmdBuf[0] & 1; - - dev->DataReplyLeft = 0; - break; - case 0x90: - buslogic_log("Store Local RAM\n"); - Offset = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - memcpy(&(bl->LocalRAM.u8View[Offset]), &(dev->CmdBuf[2]), dev->CmdBuf[1]); - - dev->DataReply = 0; - break; - case 0x91: - buslogic_log("Fetch Local RAM\n"); - Offset = dev->CmdBuf[0]; - dev->DataReplyLeft = dev->CmdBuf[1]; - memcpy(dev->DataBuf, &(bl->LocalRAM.u8View[Offset]), dev->CmdBuf[1]); - - dev->DataReply = 0; - break; - case 0x93: - if (bl->chip != CHIP_BUSLOGIC_VLB) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - case 0x92: - if ((bl->chip == CHIP_BUSLOGIC_ISA_542) || (bl->chip == CHIP_BUSLOGIC_MCA)) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - - dev->DataReplyLeft = 0; - - switch (dev->CmdBuf[0]) { - case 0: - case 2: - BuslogicAutoSCSIRamSetDefaults(dev, 0); - break; - case 3: - BuslogicAutoSCSIRamSetDefaults(dev, 3); - break; - case 1: - f = nvr_fopen(BuslogicGetNVRFileName(bl), L"wb"); - if (f) { - fwrite(&(bl->LocalRAM.structured.autoSCSIData), 1, 64, f); - fclose(f); - f = NULL; - } - break; - default: - dev->Status |= STAT_INVCMD; - break; - } - - if ((bl->chip == CHIP_BUSLOGIC_PCI) && !(dev->Status & STAT_INVCMD)) { - x54x_io_remove(dev, dev->Base, 4); - switch(HALR->structured.autoSCSIData.uHostAdapterIoPortAddress) { - case 0: - dev->Base = 0x330; - break; - case 1: - dev->Base = 0x334; - break; - default: - dev->Base = 0; - break; - } - x54x_io_set(dev, dev->Base, 4); - } - break; - case 0x94: - if ((bl->chip == CHIP_BUSLOGIC_ISA_542) || (bl->chip == CHIP_BUSLOGIC_MCA)) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - - if (dev->CmdBuf[0]) { - buslogic_log("Invalid AutoSCSI command mode %x\n", dev->CmdBuf[0]); - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } else { - dev->DataReplyLeft = dev->CmdBuf[2]; - dev->DataReplyLeft <<= 8; - dev->DataReplyLeft |= dev->CmdBuf[1]; - memcpy(dev->DataBuf, bl->AutoSCSIROM, dev->DataReplyLeft); - buslogic_log("Returning AutoSCSI ROM (%04X %04X %04X %04X)\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2], dev->DataBuf[3]); - } - break; - case 0x95: - if (bl->chip == CHIP_BUSLOGIC_PCI) { - if (dev->Base != 0) - x54x_io_remove(dev, dev->Base, 4); - if (dev->CmdBuf[0] < 6) { - dev->Base = ((3 - (dev->CmdBuf[0] >> 1)) << 8) | ((dev->CmdBuf[0] & 1) ? 0x34 : 0x30); - x54x_io_set(dev, dev->Base, 4); - } else - dev->Base = 0; - dev->DataReplyLeft = 0; - return 1; - } else { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - case 0x96: - if (dev->CmdBuf[0] == 0) - bl->ExtendedLUNCCBFormat = 0; - else if (dev->CmdBuf[0] == 1) - bl->ExtendedLUNCCBFormat = 1; - - dev->DataReplyLeft = 0; - break; - case 0x97: - case 0xA7: - /* TODO: Actually correctly implement this whole SCSI BIOS Flash stuff. */ - dev->DataReplyLeft = 0; - break; - case 0xA8: - if (bl->chip != CHIP_BUSLOGIC_PCI) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - - Offset = dev->CmdBuf[1]; - Offset <<= 8; - Offset |= dev->CmdBuf[0]; - - dev->DataReplyLeft = dev->CmdBuf[3]; - dev->DataReplyLeft <<= 8; - dev->DataReplyLeft |= dev->CmdBuf[2]; - - memcpy(dev->DataBuf, &(bl->SCAMData[Offset]), dev->DataReplyLeft); - - dev->DataReply = 0; - break; - case 0xA9: - if (bl->chip != CHIP_BUSLOGIC_PCI) { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - - Offset = dev->CmdBuf[1]; - Offset <<= 8; - Offset |= dev->CmdBuf[0]; - - dev->DataReplyLeft = dev->CmdBuf[3]; - dev->DataReplyLeft <<= 8; - dev->DataReplyLeft |= dev->CmdBuf[2]; - - memcpy(&(bl->SCAMData[Offset]), &(dev->CmdBuf[4]), dev->DataReplyLeft); - dev->DataReplyLeft = 0; - - dev->DataReply = 0; - break; - case 0xFB: - dev->DataReplyLeft = dev->CmdBuf[2]; - break; - default: - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - break; - } - return 0; -} - - -static void -buslogic_setup_data(void *p) -{ - x54x_t *dev = (x54x_t *)p; - ReplyInquireSetupInformation *ReplyISI; - buslogic_setup_t *bl_setup; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - HALocalRAM *HALR = &bl->LocalRAM; - - ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; - bl_setup = (buslogic_setup_t *)ReplyISI->VendorSpecificData; - - ReplyISI->fSynchronousInitiationEnabled = HALR->structured.autoSCSIData.u16SynchronousPermittedMask ? 1 : 0; - ReplyISI->fParityCheckingEnabled = (HALR->structured.autoSCSIData.uSCSIConfiguration & 2) ? 1 : 0; - - bl_setup->uSignature = 'B'; - /* The 'D' signature prevents Buslogic's OS/2 drivers from getting too - * friendly with Adaptec hardware and upsetting the HBA state. - */ - bl_setup->uCharacterD = 'D'; /* BusLogic model. */ - switch(bl->chip) - { - case CHIP_BUSLOGIC_ISA_542: - case CHIP_BUSLOGIC_ISA: - bl_setup->uHostBusType = 'A'; - break; - case CHIP_BUSLOGIC_MCA: - bl_setup->uHostBusType = 'B'; - break; - case CHIP_BUSLOGIC_VLB: - bl_setup->uHostBusType = 'E'; - break; - case CHIP_BUSLOGIC_PCI: - bl_setup->uHostBusType = 'F'; - break; - } -} - - -static uint8_t -buslogic_is_aggressive_mode(void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - return bl->fAggressiveRoundRobinMode; -} - - -static uint8_t -buslogic_interrupt_type(void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - if ((bl->chip == CHIP_BUSLOGIC_ISA_542) || (bl->chip == CHIP_BUSLOGIC_MCA)) - return 0; - else - return !!bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt; -} - - -static void -buslogic_reset(void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - bl->ExtendedLUNCCBFormat = 0; -} - - -uint8_t buslogic_pci_regs[256]; -bar_t buslogic_pci_bar[3]; - - -static void -BuslogicBIOSUpdate(buslogic_data_t *bl) -{ - int bios_enabled = buslogic_pci_bar[2].addr_regs[0] & 0x01; - - if (!bl->has_bios) { - return; - } - - /* PCI BIOS stuff, just enable_disable. */ - if ((bl->bios_addr > 0) && bios_enabled) { - mem_mapping_enable(&bl->bios.mapping); - mem_mapping_set_addr(&bl->bios.mapping, - bl->bios_addr, bl->bios_size); - buslogic_log("BT-958D: BIOS now at: %06X\n", bl->bios_addr); - } else { - buslogic_log("BT-958D: BIOS disabled\n"); - mem_mapping_disable(&bl->bios.mapping); - } -} - -static uint8_t -BuslogicPCIRead(int func, int addr, void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - buslogic_log("BT-958D: Reading register %02X\n", addr & 0xff); - - switch (addr) { - case 0x00: - return 0x4b; - case 0x01: - return 0x10; - case 0x02: - return 0x40; - case 0x03: - return 0x10; - case 0x04: - return buslogic_pci_regs[0x04] & 0x03; /*Respond to IO and memory accesses*/ - case 0x05: - return 0; - case 0x07: - return 2; - case 0x08: - return 1; /*Revision ID*/ - case 0x09: - return 0; /*Programming interface*/ - case 0x0A: - return 0; /*Subclass*/ - case 0x0B: - return 1; /*Class code*/ - case 0x0E: - return 0; /*Header type */ - case 0x10: - return (buslogic_pci_bar[0].addr_regs[0] & 0xe0) | 1; /*I/O space*/ - case 0x11: - return buslogic_pci_bar[0].addr_regs[1]; - case 0x12: - return buslogic_pci_bar[0].addr_regs[2]; - case 0x13: - return buslogic_pci_bar[0].addr_regs[3]; - case 0x14: - return (buslogic_pci_bar[1].addr_regs[0] & 0xe0); /*Memory space*/ - case 0x15: - return buslogic_pci_bar[1].addr_regs[1]; - case 0x16: - return buslogic_pci_bar[1].addr_regs[2]; - case 0x17: - return buslogic_pci_bar[1].addr_regs[3]; - case 0x2C: - return 0x4b; - case 0x2D: - return 0x10; - case 0x2E: - return 0x40; - case 0x2F: - return 0x10; - case 0x30: /* PCI_ROMBAR */ - buslogic_log("BT-958D: BIOS BAR 00 = %02X\n", buslogic_pci_bar[2].addr_regs[0] & 0x01); - return buslogic_pci_bar[2].addr_regs[0] & 0x01; - case 0x31: /* PCI_ROMBAR 15:11 */ - buslogic_log("BT-958D: BIOS BAR 01 = %02X\n", (buslogic_pci_bar[2].addr_regs[1] & bl->bios_mask)); - return buslogic_pci_bar[2].addr_regs[1]; - break; - case 0x32: /* PCI_ROMBAR 23:16 */ - buslogic_log("BT-958D: BIOS BAR 02 = %02X\n", buslogic_pci_bar[2].addr_regs[2]); - return buslogic_pci_bar[2].addr_regs[2]; - break; - case 0x33: /* PCI_ROMBAR 31:24 */ - buslogic_log("BT-958D: BIOS BAR 03 = %02X\n", buslogic_pci_bar[2].addr_regs[3]); - return buslogic_pci_bar[2].addr_regs[3]; - break; - case 0x3C: - return dev->Irq; - case 0x3D: - return PCI_INTA; - } - - return(0); -} - - -static void -BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) -{ - x54x_t *dev = (x54x_t *)p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - uint8_t valxor; - - buslogic_log("BT-958D: Write value %02X to register %02X\n", val, addr & 0xff); - - switch (addr) { - case 0x04: - valxor = (val & 0x27) ^ buslogic_pci_regs[addr]; - if (valxor & PCI_COMMAND_IO) { - x54x_io_remove(dev, bl->PCIBase, 32); - if ((bl->PCIBase != 0) && (val & PCI_COMMAND_IO)) { - x54x_io_set(dev, bl->PCIBase, 32); - } - } - if (valxor & PCI_COMMAND_MEM) { - x54x_mem_disable(dev); - if ((bl->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) { - x54x_mem_set_addr(dev, bl->MMIOBase); - } - } - buslogic_pci_regs[addr] = val & 0x27; - break; - - case 0x10: - val &= 0xe0; - val |= 1; - - case 0x11: case 0x12: case 0x13: - /* I/O Base set. */ - /* First, remove the old I/O. */ - x54x_io_remove(dev, bl->PCIBase, 32); - /* Then let's set the PCI regs. */ - buslogic_pci_bar[0].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - bl->PCIBase = buslogic_pci_bar[0].addr & 0xffe0; - /* Log the new base. */ - buslogic_log("BusLogic PCI: New I/O base is %04X\n" , bl->PCIBase); - /* We're done, so get out of the here. */ - if (buslogic_pci_regs[4] & PCI_COMMAND_IO) { - if (bl->PCIBase != 0) { - x54x_io_set(dev, bl->PCIBase, 32); - } - } - return; - - case 0x14: - val &= 0xe0; - - case 0x15: case 0x16: case 0x17: - /* MMIO Base set. */ - /* First, remove the old I/O. */ - x54x_mem_disable(dev); - /* Then let's set the PCI regs. */ - buslogic_pci_bar[1].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - bl->MMIOBase = buslogic_pci_bar[1].addr & 0xffffffe0; - /* Log the new base. */ - buslogic_log("BusLogic PCI: New MMIO base is %04X\n" , bl->MMIOBase); - /* We're done, so get out of the here. */ - if (buslogic_pci_regs[4] & PCI_COMMAND_MEM) { - if (bl->MMIOBase != 0) { - x54x_mem_set_addr(dev, bl->MMIOBase); - } - } - return; - - case 0x30: /* PCI_ROMBAR */ - case 0x31: /* PCI_ROMBAR */ - case 0x32: /* PCI_ROMBAR */ - case 0x33: /* PCI_ROMBAR */ - buslogic_pci_bar[2].addr_regs[addr & 3] = val; - buslogic_pci_bar[2].addr &= 0xffffc001; - bl->bios_addr = buslogic_pci_bar[2].addr & 0xffffc000; - buslogic_log("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); - BuslogicBIOSUpdate(bl); - return; - - case 0x3C: - buslogic_pci_regs[addr] = val; - if (val != 0xFF) { - buslogic_log("BusLogic IRQ now: %i\n", val); - dev->Irq = val; - } else - dev->Irq = 0; - return; - } -} - - -static void -BuslogicInitializeLocalRAM(buslogic_data_t *bl) -{ - memset(bl->LocalRAM.u8View, 0, sizeof(HALocalRAM)); - if (bl->chip == CHIP_BUSLOGIC_PCI) { - bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; - } else { - bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 0; - } - - bl->LocalRAM.structured.autoSCSIData.u16DeviceEnabledMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16WidePermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16FastPermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16SynchronousPermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.u16DisconnectPermittedMask = ~0; - bl->LocalRAM.structured.autoSCSIData.fRoundRobinScheme = 0; - bl->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = ~0; -} - - -static uint8_t -buslogic_mca_read(int port, void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - - return(dev->pos_regs[port & 7]); -} - - -static void -buslogic_mca_write(int port, uint8_t val, void *priv) -{ - x54x_t *dev = (x54x_t *) priv; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - HALocalRAM *HALR = &bl->LocalRAM; - - /* MCA does not write registers below 0x0100. */ - if (port < 0x0102) return; - - /* Save the MCA register value. */ - dev->pos_regs[port & 7] = val; - - /* This is always necessary so that the old handler doesn't remain. */ - x54x_io_remove(dev, dev->Base, 4); - - /* Get the new assigned I/O base address. */ - if (dev->pos_regs[3]) { - dev->Base = dev->pos_regs[3] << 8; - dev->Base |= ((dev->pos_regs[2] & 0x10) ? 0x34 : 0x30); - } else { - dev->Base = 0x0000; - } - - /* Save the new IRQ and DMA channel values. */ - dev->Irq = ((dev->pos_regs[2] >> 1) & 0x07) + 8; - dev->DmaChannel = dev->pos_regs[5] & 0x0f; - - /* Extract the BIOS ROM address info. */ - if (dev->pos_regs[2] & 0xe0) switch(dev->pos_regs[2] & 0xe0) { - case 0xe0: /* [0]=111x xxxx */ - bl->bios_addr = 0xDC000; - break; - - case 0x00: /* [0]=000x xxxx */ - bl->bios_addr = 0; - break; - - case 0xc0: /* [0]=110x xxxx */ - bl->bios_addr = 0xD8000; - break; - - case 0xa0: /* [0]=101x xxxx */ - bl->bios_addr = 0xD4000; - break; - - case 0x80: /* [0]=100x xxxx */ - bl->bios_addr = 0xD0000; - break; - - case 0x60: /* [0]=011x xxxx */ - bl->bios_addr = 0xCC000; - break; - - case 0x40: /* [0]=010x xxxx */ - bl->bios_addr = 0xC8000; - break; - - case 0x20: /* [0]=001x xxxx */ - bl->bios_addr = 0xC4000; - break; - } else { - /* Disabled. */ - bl->bios_addr = 0x000000; - } - - /* - * Get misc SCSI config stuff. For now, we are only - * interested in the configured HA target ID: - * - * pos[2]=111xxxxx = 7 - * pos[2]=000xxxxx = 0 - */ - dev->HostID = (dev->pos_regs[4] >> 5) & 0x07; - HALR->structured.autoSCSIData.uSCSIId = dev->HostID; - - /* - * SYNC mode is pos[2]=xxxxxx1x. - * - * SCSI Parity is pos[2]=xxx1xxxx. - * - * DOS Disk Space > 1GBytes is pos[2] = xxxx1xxx. - */ - /* Parity. */ - HALR->structured.autoSCSIData.uSCSIConfiguration &= ~2; - HALR->structured.autoSCSIData.uSCSIConfiguration |= (dev->pos_regs[4] & 2); - - /* Sync. */ - HALR->structured.autoSCSIData.u16SynchronousPermittedMask = (dev->pos_regs[4] & 0x10) ? 0xffff : 0x0000; - - /* DOS Disk Space > 1GBytes */ - HALR->structured.autoSCSIData.uBIOSConfiguration &= ~4; - HALR->structured.autoSCSIData.uBIOSConfiguration |= (dev->pos_regs[4] & 8) ? 4 : 0; - - switch(dev->DmaChannel) { - case 5: - HALR->structured.autoSCSIData.uDMAChannel = 1; - break; - case 6: - HALR->structured.autoSCSIData.uDMAChannel = 2; - break; - case 7: - HALR->structured.autoSCSIData.uDMAChannel = 3; - break; - default: - HALR->structured.autoSCSIData.uDMAChannel = 0; - break; - } - - switch(dev->Irq) { - case 9: - HALR->structured.autoSCSIData.uIrqChannel = 1; - break; - case 10: - HALR->structured.autoSCSIData.uIrqChannel = 2; - break; - case 11: - HALR->structured.autoSCSIData.uIrqChannel = 3; - break; - case 12: - HALR->structured.autoSCSIData.uIrqChannel = 4; - break; - case 14: - HALR->structured.autoSCSIData.uIrqChannel = 5; - break; - case 15: - HALR->structured.autoSCSIData.uIrqChannel = 6; - break; - default: - HALR->structured.autoSCSIData.uIrqChannel = 0; - break; - } - - /* - * The PS/2 Model 80 BIOS always enables a card if it finds one, - * even if no resources were assigned yet (because we only added - * the card, but have not run AutoConfig yet...) - * - * So, remove current address, if any. - */ - mem_mapping_disable(&dev->bios.mapping); - - /* Initialize the device if fully configured. */ - if (dev->pos_regs[2] & 0x01) { - /* Card enabled; register (new) I/O handler. */ - x54x_io_set(dev, dev->Base, 4); - - /* Reset the device. */ - x54x_reset_ctrl(dev, CTRL_HRST); - - /* Enable or disable the BIOS ROM. */ - if (bl->has_bios && (bl->bios_addr != 0x000000)) { - mem_mapping_enable(&bl->bios.mapping); - mem_mapping_set_addr(&bl->bios.mapping, bl->bios_addr, ROM_SIZE); - } - - /* Say hello. */ - buslogic_log("BT-640A: I/O=%04x, IRQ=%d, DMA=%d, BIOS @%05X, HOST ID %i\n", - dev->Base, dev->Irq, dev->DmaChannel, bl->bios_addr, dev->HostID); - } -} - - -void -BuslogicDeviceReset(void *p) -{ - x54x_t *dev = (x54x_t *) p; - buslogic_data_t *bl = (buslogic_data_t *) dev->ven_data; - - x54x_device_reset(dev); - - BuslogicInitializeLocalRAM(bl); - BuslogicInitializeAutoSCSIRam(dev); -} - - -static void * -buslogic_init(const device_t *info) -{ - x54x_t *dev; - wchar_t *bios_rom_name; - uint16_t bios_rom_size; - uint16_t bios_rom_mask; - uint8_t has_autoscsi_rom; - wchar_t *autoscsi_rom_name; - uint16_t autoscsi_rom_size; - uint8_t has_scam_rom; - wchar_t *scam_rom_name; - uint16_t scam_rom_size; - FILE *f; - buslogic_data_t *bl; - uint32_t bios_rom_addr; - - /* Call common initializer. */ - dev = x54x_init(info); - - dev->ven_data = malloc(sizeof(buslogic_data_t)); - memset(dev->ven_data, 0x00, sizeof(buslogic_data_t)); - - bl = (buslogic_data_t *) dev->ven_data; - - dev->bus = info->flags; - if (!(info->flags & DEVICE_MCA) && !(info->flags & DEVICE_PCI)) { - dev->Base = device_get_config_hex16("base"); - dev->Irq = device_get_config_int("irq"); - dev->DmaChannel = device_get_config_int("dma"); - } - else if (info->flags & DEVICE_PCI) { - dev->Base = 0; - } - dev->HostID = 7; /* default HA ID */ - dev->setup_info_len = sizeof(buslogic_setup_t); - dev->max_id = 7; - dev->int_geom_writable = 1; - dev->cdrom_boot = 0; - dev->bit32 = 0; - dev->lba_bios = 0; - - bl->chip = info->local; - bl->PCIBase = 0; - bl->MMIOBase = 0; - if (info->flags & DEVICE_PCI) { - bios_rom_addr = 0xd8000; - bl->has_bios = device_get_config_int("bios"); - } else if (info->flags & DEVICE_MCA) { - bios_rom_addr = 0xd8000; - bl->has_bios = 1; - } else { - bios_rom_addr = device_get_config_hex20("bios_addr"); - bl->has_bios = !!bios_rom_addr; - } - - dev->ven_cmd_phase1 = buslogic_cmd_phase1; - dev->ven_get_host_id = buslogic_get_host_id; - dev->ven_get_irq = buslogic_get_irq; - dev->ven_get_dma = buslogic_get_dma; - dev->get_ven_param_len = buslogic_param_len; - dev->ven_cmds = buslogic_cmds; - dev->interrupt_type = buslogic_interrupt_type; - dev->is_aggressive_mode = buslogic_is_aggressive_mode; - dev->get_ven_data = buslogic_setup_data; - dev->ven_reset = buslogic_reset; - - strcpy(dev->vendor, "BusLogic"); - - bl->fAggressiveRoundRobinMode = 1; - - switch(bl->chip) - { - case CHIP_BUSLOGIC_ISA_542: - strcpy(dev->name, "BT-542BH"); - bios_rom_name = L"roms/scsi/buslogic/BT-542BH_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 0; - has_scam_rom = 0; - dev->fw_rev = "AA335"; - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; - case CHIP_BUSLOGIC_ISA: - default: - strcpy(dev->name, "BT-545S"); - bios_rom_name = L"roms/scsi/buslogic/BT-545S_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 1; - autoscsi_rom_name = L"roms/scsi/buslogic/BT-545S_AutoSCSI.rom"; - autoscsi_rom_size = 0x4000; - has_scam_rom = 0; - dev->fw_rev = "AA421E"; - dev->ha_bps = 10000000.0; /* fast SCSI */ - break; - case CHIP_BUSLOGIC_MCA: - strcpy(dev->name, "BT-640A"); - bios_rom_name = L"roms/scsi/buslogic/BT-640A_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 0; - has_scam_rom = 0; - dev->fw_rev = "BA150"; - dev->bit32 = 1; - dev->pos_regs[0] = 0x08; /* MCA board ID */ - dev->pos_regs[1] = 0x07; - mca_add(buslogic_mca_read, buslogic_mca_write, dev); - dev->ha_bps = 5000000.0; /* normal SCSI */ - break; - case CHIP_BUSLOGIC_VLB: - strcpy(dev->name, "BT-445S"); - bios_rom_name = L"roms/scsi/buslogic/BT-445S_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 1; - autoscsi_rom_name = L"roms/scsi/buslogic/BT-445S_AutoSCSI.rom"; - autoscsi_rom_size = 0x4000; - has_scam_rom = 0; - dev->fw_rev = "AA421E"; - dev->bit32 = 1; - dev->ha_bps = 10000000.0; /* fast SCSI */ - break; - case CHIP_BUSLOGIC_PCI: - strcpy(dev->name, "BT-958D"); - bios_rom_name = L"roms/scsi/buslogic/BT-958D_BIOS.rom"; - bios_rom_size = 0x4000; - bios_rom_mask = 0x3fff; - has_autoscsi_rom = 1; - autoscsi_rom_name = L"roms/scsi/buslogic/BT-958D_AutoSCSI.rom"; - autoscsi_rom_size = 0x8000; - has_scam_rom = 1; - scam_rom_name = L"roms/scsi/buslogic/BT-958D_SCAM.rom"; - scam_rom_size = 0x0200; - dev->fw_rev = "AA507B"; - dev->cdrom_boot = 1; - dev->bit32 = 1; - dev->ha_bps = 20000000.0; /* ultra SCSI */ - dev->max_id = 15; /* wide SCSI */ - break; - } - - if ((dev->Base != 0) && !(dev->bus & DEVICE_MCA) && !(dev->bus & DEVICE_PCI)) { - x54x_io_set(dev, dev->Base, 4); - } - - memset(bl->AutoSCSIROM, 0xff, 32768); - - memset(bl->SCAMData, 0x00, 65536); - - if (bl->has_bios) - { - bl->bios_size = bios_rom_size; - - bl->bios_mask = 0xffffc000; - - rom_init(&bl->bios, bios_rom_name, bios_rom_addr, bios_rom_size, bios_rom_mask, 0, MEM_MAPPING_EXTERNAL); - - if (has_autoscsi_rom) { - f = rom_fopen(autoscsi_rom_name, L"rb"); - if (f) { - fread(bl->AutoSCSIROM, 1, autoscsi_rom_size, f); - fclose(f); - f = NULL; - } - } - - if (has_scam_rom) { - f = rom_fopen(scam_rom_name, L"rb"); - if (f) { - fread(bl->SCAMData, 1, scam_rom_size, f); - fclose(f); - f = NULL; - } - } - } - else { - bl->bios_size = 0; - - bl->bios_mask = 0; - } - - if (bl->chip == CHIP_BUSLOGIC_PCI) { - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, BuslogicPCIRead, BuslogicPCIWrite, dev); - - buslogic_pci_bar[0].addr_regs[0] = 1; - buslogic_pci_bar[1].addr_regs[0] = 0; - buslogic_pci_regs[0x04] = 3; - - /* Enable our BIOS space in PCI, if needed. */ - if (bl->has_bios) { - buslogic_pci_bar[2].addr = 0xFFFFC000; - } else { - buslogic_pci_bar[2].addr = 0; - } - - x54x_mem_init(dev, 0xfffd0000); - x54x_mem_disable(dev); - } - - if ((bl->chip == CHIP_BUSLOGIC_MCA) || (bl->chip == CHIP_BUSLOGIC_PCI)) - mem_mapping_disable(&bl->bios.mapping); - - buslogic_log("Buslogic on port 0x%04X\n", dev->Base); - - x54x_device_reset(dev); - - if ((bl->chip != CHIP_BUSLOGIC_ISA_542) && (bl->chip != CHIP_BUSLOGIC_MCA)) { - BuslogicInitializeLocalRAM(bl); - BuslogicInitializeAutoSCSIRam(dev); - } - - return(dev); -} - - -static const device_config_t BT_ISA_Config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x334, - { - { - "0x330", 0x330 - }, - { - "0x334", 0x334 - }, - { - "0x230", 0x230 - }, - { - "0x234", 0x234 - }, - { - "0x130", 0x130 - }, - { - "0x134", 0x134 - }, - { - "", 0 - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 9, - { - { - "IRQ 9", 9 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "", 0 - } - }, - }, - { - "dma", "DMA channel", CONFIG_SELECTION, "", 6, - { - { - "DMA 5", 5 - }, - { - "DMA 6", 6 - }, - { - "DMA 7", 7 - }, - { - "", 0 - } - }, - }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "D000H", 0xd0000 - }, - { - "D800H", 0xd8000 - }, - { - "", 0 - } - }, - }, - { - "", "", -1 - } -}; - - -static const device_config_t BT958D_Config[] = { - { - "bios", "Enable BIOS", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 - } -}; - - -const device_t buslogic_device = { - "Buslogic BT-542BH ISA", - DEVICE_ISA | DEVICE_AT, - CHIP_BUSLOGIC_ISA_542, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, - BT_ISA_Config -}; - -const device_t buslogic_545s_device = { - "Buslogic BT-545S ISA", - DEVICE_ISA | DEVICE_AT, - CHIP_BUSLOGIC_ISA, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, - BT_ISA_Config -}; - -const device_t buslogic_640a_device = { - "Buslogic BT-640A MCA", - DEVICE_MCA, - CHIP_BUSLOGIC_MCA, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, - NULL -}; - -const device_t buslogic_445s_device = { - "Buslogic BT-445S VLB", - DEVICE_VLB, - CHIP_BUSLOGIC_VLB, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, - BT_ISA_Config -}; - -const device_t buslogic_pci_device = { - "Buslogic BT-958D PCI", - DEVICE_PCI, - CHIP_BUSLOGIC_PCI, - buslogic_init, x54x_close, NULL, - NULL, NULL, NULL, - BT958D_Config -}; diff --git a/src/scsi - Cópia/scsi_buslogic.h b/src/scsi - Cópia/scsi_buslogic.h deleted file mode 100644 index 83ce417d9..000000000 --- a/src/scsi - Cópia/scsi_buslogic.h +++ /dev/null @@ -1,32 +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. - * - * Emulation of BusLogic BT-542B ISA and BT-958D PCI SCSI - * controllers. - * - * Version: @(#)scsi_buslogic.h 1.0.3 2018/03/18 - * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ - -#ifndef SCSI_BUSLOGIC_H -# define SCSI_BUSLOGIC_H - - -extern const device_t buslogic_device; -extern const device_t buslogic_545s_device; -extern const device_t buslogic_640a_device; -extern const device_t buslogic_445s_device; -extern const device_t buslogic_pci_device; - -extern void BuslogicDeviceReset(void *p); - - -#endif /*SCSI_BUSLOGIC_H*/ diff --git a/src/scsi - Cópia/scsi_device.c b/src/scsi - Cópia/scsi_device.c deleted file mode 100644 index f5567cb74..000000000 --- a/src/scsi - Cópia/scsi_device.c +++ /dev/null @@ -1,349 +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. - * - * The generic SCSI device command handler. - * - * Version: @(#)scsi_device.c 1.0.17 2018/06/02 - * - * Authors: Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../device.h" -#include "../disk/hdd.h" -#include "scsi.h" -#include "scsi_device.h" -#include "../cdrom/cdrom.h" -#include "../disk/zip.h" -#include "scsi_disk.h" - - -uint8_t scsi_null_device_sense[18] = { 0x70,0,SENSE_ILLEGAL_REQUEST,0,0,0,0,0,0,0,0,0,ASC_INV_LUN,0,0,0,0,0 }; - - -static uint8_t -scsi_device_target_command(int lun_type, uint8_t id, uint8_t *cdb) -{ - switch(lun_type) { - case SCSI_DISK: - scsi_disk_command(scsi_disk[id], cdb); - return scsi_disk_err_stat_to_scsi(scsi_disk[id]); - case SCSI_CDROM: - cdrom_command(cdrom[id], cdb); - return cdrom_CDROM_PHASE_to_scsi(cdrom[id]); - case SCSI_ZIP: - zip_command(zip[id], cdb); - return zip_ZIP_PHASE_to_scsi(zip[id]); - default: - return SCSI_STATUS_CHECK_CONDITION; - } -} - - -static void scsi_device_target_phase_callback(int lun_type, uint8_t id) -{ - switch(lun_type) { - case SCSI_DISK: - scsi_disk_callback(scsi_disk[id]); - break; - case SCSI_CDROM: - cdrom_phase_callback(cdrom[id]); - break; - case SCSI_ZIP: - zip_phase_callback(zip[id]); - break; - } - return; -} - - -static int scsi_device_target_err_stat_to_scsi(int lun_type, uint8_t id) -{ - switch(lun_type) { - case SCSI_DISK: - return scsi_disk_err_stat_to_scsi(scsi_disk[id]); - case SCSI_CDROM: - return cdrom_CDROM_PHASE_to_scsi(cdrom[id]); - case SCSI_ZIP: - return zip_ZIP_PHASE_to_scsi(zip[id]); - default: - return SCSI_STATUS_CHECK_CONDITION; - } -} - - -int64_t scsi_device_get_callback(uint8_t scsi_id) -{ - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - uint8_t id = 0; - - switch (lun_type) - { - case SCSI_DISK: - id = scsi_disks[scsi_id]; - return scsi_disk[id]->callback; - break; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id]; - return cdrom[id]->callback; - break; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id]; - return zip[id]->callback; - break; - default: - return -1LL; - break; - } -} - - -uint8_t *scsi_device_sense(uint8_t scsi_id) -{ - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - uint8_t id = 0; - - switch (lun_type) - { - case SCSI_DISK: - id = scsi_disks[scsi_id]; - return scsi_disk[id]->sense; - break; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id]; - return cdrom[id]->sense; - break; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id]; - return zip[id]->sense; - break; - default: - return scsi_null_device_sense; - break; - } -} - - -void scsi_device_request_sense(uint8_t scsi_id, uint8_t *buffer, uint8_t alloc_length) -{ - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - uint8_t id = 0; - - switch (lun_type) - { - case SCSI_DISK: - id = scsi_disks[scsi_id]; - scsi_disk_request_sense_for_scsi(scsi_disk[id], buffer, alloc_length); - break; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id]; - cdrom_request_sense_for_scsi(cdrom[id], buffer, alloc_length); - break; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id]; - zip_request_sense_for_scsi(zip[id], buffer, alloc_length); - break; - default: - memcpy(buffer, scsi_null_device_sense, alloc_length); - break; - } -} - - -void scsi_device_reset(uint8_t scsi_id) -{ - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - uint8_t id = 0; - - switch (lun_type) - { - case SCSI_DISK: - id = scsi_disks[scsi_id]; - scsi_disk_reset(scsi_disk[id]); - break; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id]; - cdrom_reset(cdrom[id]); - break; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id]; - zip_reset(zip[id]); - break; - } -} - - -void scsi_device_type_data(uint8_t scsi_id, uint8_t *type, uint8_t *rmb) -{ - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - switch (lun_type) - { - case SCSI_DISK: - *type = *rmb = 0x00; - break; - case SCSI_CDROM: - *type = 0x05; - *rmb = 0x80; - break; - case SCSI_ZIP: - *type = 0x00; - *rmb = 0x80; - break; - default: - *type = *rmb = 0xff; - break; - } -} - - -int scsi_device_read_capacity(uint8_t scsi_id, uint8_t *cdb, uint8_t *buffer, uint32_t *len) -{ - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - uint8_t id = 0; - - switch (lun_type) - { - case SCSI_DISK: - id = scsi_disks[scsi_id]; - return scsi_disk_read_capacity(scsi_disk[id], cdb, buffer, len); - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id]; - return cdrom_read_capacity(cdrom[id], cdb, buffer, len); - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id]; - return zip_read_capacity(zip[id], cdb, buffer, len); - default: - return 0; - } -} - - -int scsi_device_present(uint8_t scsi_id) -{ - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - switch (lun_type) - { - case SCSI_NONE: - return 0; - default: - return 1; - } -} - - -int scsi_device_valid(uint8_t scsi_id) -{ - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - uint8_t id = 0; - - switch (lun_type) - { - case SCSI_DISK: - id = scsi_disks[scsi_id]; - break; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id]; - break; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id]; - break; - default: - id = 0; - break; - } - - return (id == 0xFF) ? 0 : 1; -} - - -int scsi_device_cdb_length(uint8_t scsi_id) -{ - /* Right now, it's 12 for all devices. */ - return 12; -} - - -void scsi_device_command_phase0(uint8_t scsi_id, uint8_t *cdb) -{ - uint8_t id = 0; - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id]; - break; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id]; - break; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id]; - break; - default: - id = 0; - SCSIDevices[scsi_id].Phase = SCSI_PHASE_STATUS; - SCSIDevices[scsi_id].Status = SCSI_STATUS_CHECK_CONDITION; - return; - } - - /* Finally, execute the SCSI command immediately and get the transfer length. */ - SCSIDevices[scsi_id].Phase = SCSI_PHASE_COMMAND; - SCSIDevices[scsi_id].Status = scsi_device_target_command(lun_type, id, cdb); - - if (SCSIDevices[scsi_id].Phase == SCSI_PHASE_STATUS) { - /* Command completed (either OK or error) - call the phase callback to complete the command. */ - scsi_device_target_phase_callback(lun_type, id); - } - /* If the phase is DATA IN or DATA OUT, finish this here. */ -} - -void scsi_device_command_phase1(uint8_t scsi_id) -{ - uint8_t id = 0; - uint8_t lun_type = SCSIDevices[scsi_id].LunType; - - switch (lun_type) { - case SCSI_DISK: - id = scsi_disks[scsi_id]; - break; - case SCSI_CDROM: - id = scsi_cdrom_drives[scsi_id]; - break; - case SCSI_ZIP: - id = scsi_zip_drives[scsi_id]; - break; - default: - id = 0; - return; - } - - /* Call the second phase. */ - scsi_device_target_phase_callback(lun_type, id); - SCSIDevices[scsi_id].Status = scsi_device_target_err_stat_to_scsi(lun_type, id); - /* Command second phase complete - call the callback to complete the command. */ - scsi_device_target_phase_callback(lun_type, id); -} - -int32_t *scsi_device_get_buf_len(uint8_t scsi_id) -{ - return &SCSIDevices[scsi_id].BufferLength; -} diff --git a/src/scsi - Cópia/scsi_device.h b/src/scsi - Cópia/scsi_device.h deleted file mode 100644 index d0da9a19b..000000000 --- a/src/scsi - Cópia/scsi_device.h +++ /dev/null @@ -1,55 +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. - * - * Definitions for the generic SCSI device command handler. - * - * Version: @(#)scsi_device.h 1.0.8 2018/06/12 - * - * Authors: Miran Grca, - * Fred N. van Kempen, - */ -#ifndef SCSI_DEVICE_H -# define SCSI_DEVICE_H - -typedef struct -{ - int state; - int new_state; - int clear_req; - uint32_t bus_in, bus_out; - int dev_id; - - int command_pos; - uint8_t command[20]; - int data_pos; - - int change_state_delay; - int new_req_delay; -} scsi_bus_t; - -extern uint8_t *scsi_device_sense(uint8_t id); -extern void scsi_device_type_data(uint8_t id, uint8_t *type, uint8_t *rmb); -extern int64_t scsi_device_get_callback(uint8_t scsi_id); -extern void scsi_device_request_sense(uint8_t scsi_id, uint8_t *buffer, - uint8_t alloc_length); -extern void scsi_device_reset(uint8_t scsi_id); -extern int scsi_device_read_capacity(uint8_t id, uint8_t *cdb, - uint8_t *buffer, uint32_t *len); -extern int scsi_device_present(uint8_t id); -extern int scsi_device_valid(uint8_t id); -extern int scsi_device_cdb_length(uint8_t id); -extern void scsi_device_command(uint8_t id, int cdb_len, uint8_t *cdb); -extern void scsi_device_command_phase0(uint8_t scsi_id, uint8_t *cdb); -extern void scsi_device_command_phase1(uint8_t scsi_id); -extern int32_t *scsi_device_get_buf_len(uint8_t scsi_id); - -extern int scsi_bus_update(scsi_bus_t *bus, int bus_assert); -extern int scsi_bus_read(scsi_bus_t *bus); -extern int scsi_bus_match(scsi_bus_t *bus, int bus_assert); - -#endif /*SCSI_DEVICE_H*/ diff --git a/src/scsi - Cópia/scsi_disk.c b/src/scsi - Cópia/scsi_disk.c deleted file mode 100644 index 31afaecf2..000000000 --- a/src/scsi - Cópia/scsi_disk.c +++ /dev/null @@ -1,1313 +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. - * - * Emulation of SCSI fixed disks. - * - * Version: @(#)scsi_disk.c 1.0.21 2018/09/12 - * - * Author: Miran Grca, - * - * Copyright 2017,2018 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../timer.h" -#include "../device.h" -#include "../nvr.h" -#include "../piix.h" -#include "../disk/hdd.h" -#include "../disk/hdc.h" -#include "../disk/hdc_ide.h" -#include "../plat.h" -#include "../ui.h" -#include "scsi.h" -#include "../cdrom/cdrom.h" -#include "scsi_disk.h" - - -/* Bits of 'status' */ -#define ERR_STAT 0x01 -#define DRQ_STAT 0x08 /* Data request */ -#define DSC_STAT 0x10 -#define SERVICE_STAT 0x10 -#define READY_STAT 0x40 -#define BUSY_STAT 0x80 - -/* Bits of 'error' */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* Media change request */ - -#define MAX_BLOCKS_AT_ONCE 340 - -#define scsi_disk_sense_error dev->sense[0] -#define scsi_disk_sense_key dev->sense[2] -#define scsi_disk_asc dev->sense[12] -#define scsi_disk_ascq dev->sense[13] - - -scsi_disk_t *scsi_disk[HDD_NUM]; - -uint8_t scsi_disks[16] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - - -/* Table of all SCSI commands and their flags, needed for the new disc change / not ready handler. */ -const uint8_t scsi_disk_command_flags[0x100] = { - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x00 */ - IMPLEMENTED | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x01 */ - 0, - IMPLEMENTED | ALLOW_UA, /* 0x03 */ - IMPLEMENTED | CHECK_READY | ALLOW_UA | NONDATA | SCSI_ONLY, /* 0x04 */ - 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x08 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x0A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x0B */ - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | ALLOW_UA, /* 0x12 */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x13 */ - 0, - IMPLEMENTED, /* 0x15 */ - IMPLEMENTED | SCSI_ONLY, /* 0x16 */ - IMPLEMENTED | SCSI_ONLY, /* 0x17 */ - 0, 0, - IMPLEMENTED, /* 0x1A */ - 0, 0, - IMPLEMENTED, /* 0x1D */ - IMPLEMENTED | CHECK_READY, /* 0x1E */ - 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x25 */ - 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x28 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0x2A */ - IMPLEMENTED | CHECK_READY | NONDATA, /* 0x2B */ - 0, 0, - IMPLEMENTED | CHECK_READY, /* 0x2E */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0x2F */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, - IMPLEMENTED | CHECK_READY, /* 0x41 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0x55 */ - 0, 0, 0, 0, - IMPLEMENTED, /* 0x5A */ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xA8 */ - 0, - IMPLEMENTED | CHECK_READY, /* 0xAA */ - 0, 0, 0, - IMPLEMENTED | CHECK_READY, /* 0xAE */ - IMPLEMENTED | CHECK_READY | NONDATA | SCSI_ONLY, /* 0xAF */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - IMPLEMENTED, /* 0xBD */ - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - - -uint64_t scsi_disk_mode_sense_page_flags = (GPMODEP_UNK_PAGE_03 | - GPMODEP_UNK_PAGE_04 | - GPMODEP_UNK_PAGE_30 | - GPMODEP_ALL_PAGES); - -/* This should be done in a better way but for time being, it's been done this way so it's not as huge and more readable. */ -static const mode_sense_pages_t scsi_disk_mode_sense_pages_default = -{ { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, - [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } -} }; - -static const mode_sense_pages_t scsi_disk_mode_sense_pages_changeable = -{ { [0x03] = { 0x03, 0x16, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - [0x04] = { 0x04, 0x16, 0, 0x10, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, 0, 0, 0 }, - [0x30] = { 0xB0, 0x16, '8', '6', 'B', 'o', 'x', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } -} }; - - -#ifdef ENABLE_SCSI_DISK_LOG -int scsi_disk_do_log = ENABLE_SCSI_DISK_LOG; -#endif - - -static void -scsi_disk_log(const char *fmt, ...) -{ -#ifdef ENABLE_SCSI_DISK_LOG - va_list ap; - - if (scsi_disk_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -/* Translates ATAPI status (ERR_STAT flag) to SCSI status. */ -int -scsi_disk_err_stat_to_scsi(scsi_disk_t *dev) -{ - if (dev->status & ERR_STAT) - return SCSI_STATUS_CHECK_CONDITION; - else - return SCSI_STATUS_OK; -} - - -int -find_hdd_for_scsi_id(uint8_t scsi_id) -{ - uint8_t i = 0; - - for (i = 0; i < HDD_NUM; i++) { - if (wcslen(hdd[i].fn) == 0) - continue; - if ((hdd[i].spt == 0) || (hdd[i].hpc == 0) || (hdd[i].tracks == 0)) - continue; - if ((hdd[i].bus == HDD_BUS_SCSI) && (hdd[i].scsi_id == scsi_id)) - return i; - } - return 0xff; -} - - -void -scsi_loadhd(int scsi_id, int id) -{ - if (! hdd_image_load(id)) - scsi_disks[scsi_id] = 0xff; -} - - -void -build_scsi_disk_map(void) -{ - uint8_t i = 0; - - memset(scsi_disks, 0xff, 16); - - for (i = 0; i < 16; i++) { - scsi_disks[i] = find_hdd_for_scsi_id(i); - if (scsi_disks[i] != 0xff) { - if (wcslen(hdd[scsi_disks[i]].fn) > 0) - scsi_loadhd(i, scsi_disks[i]); - } - } -} - - -void -scsi_disk_mode_sense_load(scsi_disk_t *dev) -{ - FILE *f; - wchar_t file_name[512]; - int i; - memset(&dev->ms_pages_saved, 0, sizeof(mode_sense_pages_t)); - for (i = 0; i < 0x3f; i++) { - if (scsi_disk_mode_sense_pages_default.pages[i][1] != 0) { - memcpy(dev->ms_pages_saved.pages[i], scsi_disk_mode_sense_pages_default.pages[i], - scsi_disk_mode_sense_pages_default.pages[i][1] + 2); - } - } - swprintf(file_name, 512, L"scsi_disk_%02i_mode_sense.bin", dev->id); - memset(file_name, 0, 512 * sizeof(wchar_t)); - f = plat_fopen(nvr_path(file_name), L"rb"); - if (f) { - fread(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); - fclose(f); - } -} - - -void -scsi_disk_mode_sense_save(scsi_disk_t *dev) -{ - FILE *f; - wchar_t file_name[512]; - memset(file_name, 0, 512 * sizeof(wchar_t)); - swprintf(file_name, 512, L"scsi_disk_%02i_mode_sense.bin", dev->id); - f = plat_fopen(nvr_path(file_name), L"wb"); - if (f) { - fwrite(dev->ms_pages_saved.pages[0x30], 1, 0x18, f); - fclose(f); - } -} - - -int -scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len) -{ - int size = 0; - - size = hdd_image_get_last_sector(dev->id); - memset(buffer, 0, 8); - buffer[0] = (size >> 24) & 0xff; - buffer[1] = (size >> 16) & 0xff; - buffer[2] = (size >> 8) & 0xff; - buffer[3] = size & 0xff; - buffer[6] = 2; /* 512 = 0x0200 */ - *len = 8; - - return 1; -} - - -/*SCSI Mode Sense 6/10*/ -uint8_t -scsi_disk_mode_sense_read(scsi_disk_t *dev, uint8_t page_control, uint8_t page, uint8_t pos) -{ - switch (page_control) { - case 0: - case 3: - return dev->ms_pages_saved.pages[page][pos]; - break; - case 1: - return scsi_disk_mode_sense_pages_changeable.pages[page][pos]; - break; - case 2: - return scsi_disk_mode_sense_pages_default.pages[page][pos]; - break; - } - - return 0; -} - - -uint32_t -scsi_disk_mode_sense(scsi_disk_t *dev, uint8_t *buf, uint32_t pos, uint8_t type, uint8_t block_descriptor_len) -{ - uint8_t msplen, page_control = (type >> 6) & 3; - - int i = 0, j = 0; - int size = 0; - - type &= 0x3f; - - size = hdd_image_get_last_sector(dev->id); - - if (block_descriptor_len) { - buf[pos++] = 1; /* Density code. */ - buf[pos++] = (size >> 16) & 0xff; /* Number of blocks (0 = all). */ - buf[pos++] = (size >> 8) & 0xff; - buf[pos++] = size & 0xff; - buf[pos++] = 0; /* Reserved. */ - buf[pos++] = 0; /* Block length (0x200 = 512 bytes). */ - buf[pos++] = 2; - buf[pos++] = 0; - } - - for (i = 0; i < 0x40; i++) { - if ((type == GPMODE_ALL_PAGES) || (type == i)) { - if (scsi_disk_mode_sense_page_flags & (1LL << dev->current_page_code)) { - buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 0); - msplen = scsi_disk_mode_sense_read(dev, page_control, i, 1); - buf[pos++] = msplen; - scsi_disk_log("SCSI HDD %i: MODE SENSE: Page [%02X] length %i\n", dev->id, i, msplen); - for (j = 0; j < msplen; j++) - buf[pos++] = scsi_disk_mode_sense_read(dev, page_control, i, 2 + j); - } - } - } - - return pos; -} - - -static void -scsi_disk_command_common(scsi_disk_t *dev) -{ - dev->status = BUSY_STAT; - dev->phase = 1; - if (dev->packet_status == CDROM_PHASE_COMPLETE) { - scsi_disk_callback(dev); - dev->callback = 0LL; - } else - dev->callback = -1LL; /* Speed depends on SCSI controller */ -} - - -static void -scsi_disk_command_complete(scsi_disk_t *dev) -{ - dev->packet_status = CDROM_PHASE_COMPLETE; - scsi_disk_command_common(dev); -} - - -static void -scsi_disk_command_read_dma(scsi_disk_t *dev) -{ - dev->packet_status = CDROM_PHASE_DATA_IN_DMA; - scsi_disk_command_common(dev); -} - - -static void -scsi_disk_command_write_dma(scsi_disk_t *dev) -{ - dev->packet_status = CDROM_PHASE_DATA_OUT_DMA; - scsi_disk_command_common(dev); -} - - -static void -scsi_disk_data_command_finish(scsi_disk_t *dev, int len, int block_len, int alloc_len, int direction) -{ - scsi_disk_log("SCSI HD %i: Finishing command (%02X): %i, %i, %i, %i, %i\n", dev->id, - dev->current_cdb[0], len, block_len, alloc_len, direction, dev->request_length); - if (alloc_len >= 0) { - if (alloc_len < len) - len = alloc_len; - } - if (len == 0) - scsi_disk_command_complete(dev); - else { - if (direction == 0) - scsi_disk_command_read_dma(dev); - else - scsi_disk_command_write_dma(dev); - } -} - - -static void -scsi_disk_sense_clear(scsi_disk_t *dev, int command) -{ - scsi_disk_sense_key = scsi_disk_asc = scsi_disk_ascq = 0; -} - - -static void -scsi_disk_set_phase(scsi_disk_t *dev, uint8_t phase) -{ - uint8_t scsi_id = dev->drv->scsi_id; - - if (dev->drv->bus != HDD_BUS_SCSI) - return; - - SCSIDevices[scsi_id].Phase = phase; -} - - -static void -scsi_disk_cmd_error(scsi_disk_t *dev) -{ - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - dev->error = ((scsi_disk_sense_key & 0xf) << 4) | ABRT_ERR; - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - dev->packet_status = 0x80; - dev->callback = 50 * SCSI_TIME; - scsi_disk_log("SCSI HD %i: ERROR: %02X/%02X/%02X\n", dev->id, scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); -} - - -static void -scsi_disk_invalid_lun(scsi_disk_t *dev) -{ - scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_INV_LUN; - scsi_disk_ascq = 0; - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_cmd_error(dev); -} - - -static void -scsi_disk_illegal_opcode(scsi_disk_t *dev) -{ - scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_ILLEGAL_OPCODE; - scsi_disk_ascq = 0; - scsi_disk_cmd_error(dev); -} - - -static void -scsi_disk_lba_out_of_range(scsi_disk_t *dev) -{ - scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_LBA_OUT_OF_RANGE; - scsi_disk_ascq = 0; - scsi_disk_cmd_error(dev); -} - - -static void -scsi_disk_invalid_field(scsi_disk_t *dev) -{ - scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_INV_FIELD_IN_CMD_PACKET; - scsi_disk_ascq = 0; - scsi_disk_cmd_error(dev); - dev->status = 0x53; -} - - -static void -scsi_disk_invalid_field_pl(scsi_disk_t *dev) -{ - scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_INV_FIELD_IN_PARAMETER_LIST; - scsi_disk_ascq = 0; - scsi_disk_cmd_error(dev); - dev->status = 0x53; -} - - -static void -scsi_disk_data_phase_error(scsi_disk_t *dev) -{ - scsi_disk_sense_key = SENSE_ILLEGAL_REQUEST; - scsi_disk_asc = ASC_DATA_PHASE_ERROR; - scsi_disk_ascq = 0; - scsi_disk_cmd_error(dev); -} - - -static int -scsi_disk_pre_execution_check(scsi_disk_t *dev, uint8_t *cdb) -{ - if ((cdb[0] != GPCMD_REQUEST_SENSE) && (cdb[1] & 0xe0)) { - scsi_disk_log("SCSI HD %i: Attempting to execute a unknown command targeted at SCSI LUN %i\n", - dev->id, ((dev->request_length >> 5) & 7)); - scsi_disk_invalid_lun(dev); - return 0; - } - - if (!(scsi_disk_command_flags[cdb[0]] & IMPLEMENTED)) { - scsi_disk_log("SCSI HD %i: Attempting to execute unknown command %02X\n", dev->id, cdb[0]); - scsi_disk_illegal_opcode(dev); - return 0; - } - - /* Unless the command is REQUEST SENSE, clear the sense. This will *NOT* - the UNIT ATTENTION condition if it's set. */ - if (cdb[0] != GPCMD_REQUEST_SENSE) - scsi_disk_sense_clear(dev, cdb[0]); - - scsi_disk_log("SCSI HD %i: Continuing with command\n", dev->id); - - return 1; -} - - -static void -scsi_disk_seek(scsi_disk_t *dev, uint32_t pos) -{ - /* scsi_disk_log("SCSI HD %i: Seek %08X\n", dev->id, pos); */ - hdd_image_seek(dev->id, pos); -} - - -static void -scsi_disk_rezero(scsi_disk_t *dev) -{ - if (dev->id == 0xff) - return; - - dev->sector_pos = dev->sector_len = 0; - scsi_disk_seek(dev, 0); -} - - -void -scsi_disk_reset(scsi_disk_t *dev) -{ - scsi_disk_rezero(dev); - dev->status = 0; - dev->callback = 0; - dev->packet_status = 0xff; -} - - -void -scsi_disk_request_sense(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length, int desc) -{ - /*Will return 18 bytes of 0*/ - if (alloc_length != 0) { - memset(buffer, 0, alloc_length); - if (!desc) - memcpy(buffer, dev->sense, alloc_length); - else { - buffer[1] = scsi_disk_sense_key; - buffer[2] = scsi_disk_asc; - buffer[3] = scsi_disk_ascq; - } - } else - return; - - buffer[0] = 0x70; - - scsi_disk_log("SCSI HD %i: Reporting sense: %02X %02X %02X\n", dev->id, buffer[2], buffer[12], buffer[13]); - - /* Clear the sense stuff as per the spec. */ - scsi_disk_sense_clear(dev, GPCMD_REQUEST_SENSE); -} - - -void -scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length) -{ - scsi_disk_request_sense(dev, buffer, alloc_length, 0); -} - - -static void -scsi_disk_set_buf_len(scsi_disk_t *dev, int32_t *BufLen, int32_t *src_len) -{ - if (*BufLen == -1) - *BufLen = *src_len; - else { - *BufLen = MIN(*src_len, *BufLen); - *src_len = *BufLen; - } - scsi_disk_log("SCSI HD %i: Actual transfer length: %i\n", dev->id, *BufLen); -} - - -void -scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb) -{ - uint8_t *hdbufferb; - int32_t *BufLen; - int32_t len, max_len, alloc_length; - int pos = 0; - int idx = 0; - unsigned size_idx, preamble_len; - uint32_t last_sector = 0; - char device_identify[9] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', 0 }; - char device_identify_ex[15] = { '8', '6', 'B', '_', 'H', 'D', '0', '0', ' ', 'v', '1', '.', '0', '0', 0 }; - int block_desc = 0; - - hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer; - BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength; - - last_sector = hdd_image_get_last_sector(dev->id); - - dev->status &= ~ERR_STAT; - dev->packet_len = 0; - - device_identify[6] = (dev->id / 10) + 0x30; - device_identify[7] = (dev->id % 10) + 0x30; - - device_identify_ex[6] = (dev->id / 10) + 0x30; - device_identify_ex[7] = (dev->id % 10) + 0x30; - device_identify_ex[10] = EMU_VERSION[0]; - device_identify_ex[12] = EMU_VERSION[2]; - device_identify_ex[13] = EMU_VERSION[3]; - - memcpy(dev->current_cdb, cdb, 12); - - if (cdb[0] != 0) { - scsi_disk_log("SCSI HD %i: Command 0x%02X, Sense Key %02X, Asc %02X, Ascq %02X\n", - dev->id, cdb[0], scsi_disk_sense_key, scsi_disk_asc, scsi_disk_ascq); - scsi_disk_log("SCSI HD %i: Request length: %04X\n", dev->id, dev->request_length); - - scsi_disk_log("SCSI HD %i: CDB: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", dev->id, - cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], - cdb[8], cdb[9], cdb[10], cdb[11]); - } - - dev->sector_len = 0; - - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - - /* This handles the Not Ready/Unit Attention check if it has to be handled at this point. */ - if (scsi_disk_pre_execution_check(dev, cdb) == 0) - return; - - switch (cdb[0]) { - case GPCMD_SEND_DIAGNOSTIC: - if (!(cdb[1] & (1 << 2))) { - scsi_disk_invalid_field(dev); - return; - } - case GPCMD_SCSI_RESERVE: - case GPCMD_SCSI_RELEASE: - case GPCMD_TEST_UNIT_READY: - case GPCMD_FORMAT_UNIT: - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_command_complete(dev); - break; - - case GPCMD_REZERO_UNIT: - dev->sector_pos = dev->sector_len = 0; - scsi_disk_seek(dev, 0); - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - break; - - case GPCMD_REQUEST_SENSE: - /* If there's a unit attention condition and there's a buffered not ready, a standalone REQUEST SENSE - should forget about the not ready, and report unit attention straight away. */ - len = cdb[4]; - scsi_disk_set_buf_len(dev, BufLen, &len); - - if (*BufLen < cdb[4]) - cdb[4] = *BufLen; - - len = (cdb[1] & 1) ? 8 : 18; - - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_disk_data_command_finish(dev, len, len, cdb[4], 0); - break; - - case GPCMD_MECHANISM_STATUS: - len = (cdb[7] << 16) | (cdb[8] << 8) | cdb[9]; - scsi_disk_set_buf_len(dev, BufLen, &len); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_disk_data_command_finish(dev, 8, 8, len, 0); - break; - - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - switch(cdb[0]) { - case GPCMD_READ_6: - dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - break; - case GPCMD_READ_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - break; - case GPCMD_READ_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if ((dev->sector_pos > last_sector) || ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { - scsi_disk_lba_out_of_range(dev); - return; - } - - if ((!dev->sector_len) || (*BufLen == 0)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev); - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->callback = 20 * SCSI_TIME; - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; - - alloc_length = dev->packet_len = max_len << 9; - - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - - if (dev->requested_blocks > 1) - scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 0); - else - scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 0); - return; - - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - if (!(cdb[1] & 2)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_command_complete(dev); - break; - } - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - switch(cdb[0]) - { - case GPCMD_VERIFY_6: - case GPCMD_WRITE_6: - dev->sector_len = cdb[4]; - dev->sector_pos = ((((uint32_t) cdb[1]) & 0x1f) << 16) | (((uint32_t) cdb[2]) << 8) | ((uint32_t) cdb[3]); - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_VERIFY_10: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - break; - case GPCMD_VERIFY_12: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - dev->sector_len = (((uint32_t) cdb[6]) << 24) | (((uint32_t) cdb[7]) << 16) | (((uint32_t) cdb[8]) << 8) | ((uint32_t) cdb[9]); - dev->sector_pos = (((uint32_t) cdb[2]) << 24) | (((uint32_t) cdb[3]) << 16) | (((uint32_t) cdb[4]) << 8) | ((uint32_t) cdb[5]); - break; - } - - if ((dev->sector_pos > last_sector) || - ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { - scsi_disk_lba_out_of_range(dev); - return; - } - - if ((!dev->sector_len) || (*BufLen == 0)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->callback = 20 * SCSI_TIME; - break; - } - - max_len = dev->sector_len; - dev->requested_blocks = max_len; - - alloc_length = dev->packet_len = max_len << 9; - - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - - if (dev->requested_blocks > 1) - scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1); - else - scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1); - return; - - case GPCMD_WRITE_SAME_10: - if ((cdb[1] & 6) == 6) { - scsi_disk_invalid_field(dev); - return; - } - - dev->sector_len = (cdb[7] << 8) | cdb[8]; - dev->sector_pos = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5]; - scsi_disk_log("SCSI HD %i: Length: %i, LBA: %i\n", dev->id, dev->sector_len, dev->sector_pos); - - if ((dev->sector_pos > last_sector) || - ((dev->sector_pos + dev->sector_len - 1) > last_sector)) { - scsi_disk_lba_out_of_range(dev); - return; - } - - if ((!dev->sector_len) || (*BufLen == 0)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->callback = 20 * SCSI_TIME; - break; - } - - max_len = 1; - dev->requested_blocks = max_len; - - alloc_length = dev->packet_len = max_len << 9; - - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - - if (dev->requested_blocks > 1) - scsi_disk_data_command_finish(dev, alloc_length, alloc_length / dev->requested_blocks, alloc_length, 1); - else - scsi_disk_data_command_finish(dev, alloc_length, alloc_length, alloc_length, 1); - return; - - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - - block_desc = ((cdb[1] >> 3) & 1) ? 0 : 1; - - if (cdb[0] == GPCMD_MODE_SENSE_6) - len = cdb[4]; - else - len = (cdb[8] | (cdb[7] << 8)); - - dev->current_page_code = cdb[2] & 0x3F; - - alloc_length = len; - - dev->temp_buffer = (uint8_t *) malloc(65536); - memset(dev->temp_buffer, 0, 65536); - - if (cdb[0] == GPCMD_MODE_SENSE_6) { - len = scsi_disk_mode_sense(dev, dev->temp_buffer, 4, cdb[2], block_desc); - if (len > alloc_length) - len = alloc_length; - dev->temp_buffer[0] = len - 1; - dev->temp_buffer[1] = 0; - if (block_desc) - dev->temp_buffer[3] = 8; - } else { - len = scsi_disk_mode_sense(dev, dev->temp_buffer, 8, cdb[2], block_desc); - if (len > alloc_length) - len = alloc_length; - dev->temp_buffer[0]=(len - 2) >> 8; - dev->temp_buffer[1]=(len - 2) & 255; - dev->temp_buffer[2] = 0; - if (block_desc) { - dev->temp_buffer[6] = 0; - dev->temp_buffer[7] = 8; - } - } - - if (len > alloc_length) - len = alloc_length; - else if (len < alloc_length) - alloc_length = len; - - scsi_disk_set_buf_len(dev, BufLen, &alloc_length); - scsi_disk_log("SCSI HDD %i: Reading mode page: %02X...\n", dev->id, cdb[2]); - - scsi_disk_data_command_finish(dev, len, len, alloc_length, 0); - return; - - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_OUT); - - if (cdb[0] == GPCMD_MODE_SELECT_6) - len = cdb[4]; - else - len = (cdb[7] << 8) | cdb[8]; - - scsi_disk_set_buf_len(dev, BufLen, &len); - dev->total_length = len; - dev->do_page_save = cdb[1] & 1; - scsi_disk_data_command_finish(dev, len, len, len, 1); - return; - - case GPCMD_INQUIRY: - max_len = cdb[3]; - max_len <<= 8; - max_len |= cdb[4]; - - if ((!max_len) || (*BufLen == 0)) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - /* scsi_disk_log("SCSI HD %i: All done - callback set\n", dev->id); */ - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->callback = 20 * SCSI_TIME; - break; - } - - dev->temp_buffer = malloc(1024); - - if (cdb[1] & 1) { - preamble_len = 4; - size_idx = 3; - - dev->temp_buffer[idx++] = 05; - dev->temp_buffer[idx++] = cdb[2]; - dev->temp_buffer[idx++] = 0; - - idx++; - - switch (cdb[2]) { - case 0x00: - dev->temp_buffer[idx++] = 0x00; - dev->temp_buffer[idx++] = 0x83; - break; - case 0x83: - if (idx + 24 > max_len) { - free(dev->temp_buffer); - dev->temp_buffer = NULL; - scsi_disk_data_phase_error(dev); - return; - } - - dev->temp_buffer[idx++] = 0x02; - dev->temp_buffer[idx++] = 0x00; - dev->temp_buffer[idx++] = 0x00; - dev->temp_buffer[idx++] = 20; - ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Serial */ - idx += 20; - - if (idx + 72 > cdb[4]) - goto atapi_out; - dev->temp_buffer[idx++] = 0x02; - dev->temp_buffer[idx++] = 0x01; - dev->temp_buffer[idx++] = 0x00; - dev->temp_buffer[idx++] = 68; - ide_padstr8(dev->temp_buffer + idx, 8, EMU_NAME); /* Vendor */ - idx += 8; - ide_padstr8(dev->temp_buffer + idx, 40, device_identify_ex); /* Product */ - idx += 40; - ide_padstr8(dev->temp_buffer + idx, 20, "53R141"); /* Product */ - idx += 20; - break; - default: - scsi_disk_log("INQUIRY: Invalid page: %02X\n", cdb[2]); - free(dev->temp_buffer); - dev->temp_buffer = NULL; - scsi_disk_invalid_field(dev); - return; - } - } else { - preamble_len = 5; - size_idx = 4; - - memset(dev->temp_buffer, 0, 8); - dev->temp_buffer[0] = 0; /*SCSI HD*/ - dev->temp_buffer[1] = 0; /*Fixed*/ - dev->temp_buffer[2] = 0x02; /*SCSI-2 compliant*/ - dev->temp_buffer[3] = 0x02; - dev->temp_buffer[4] = 31; - dev->temp_buffer[6] = 1; /* 16-bit transfers supported */ - dev->temp_buffer[7] = 0x20; /* Wide bus supported */ - - ide_padstr8(dev->temp_buffer + 8, 8, EMU_NAME); /* Vendor */ - ide_padstr8(dev->temp_buffer + 16, 16, device_identify); /* Product */ - ide_padstr8(dev->temp_buffer + 32, 4, EMU_VERSION); /* Revision */ - idx = 36; - - if (max_len == 96) { - dev->temp_buffer[4] = 91; - idx = 96; - } - } - -atapi_out: - dev->temp_buffer[size_idx] = idx - preamble_len; - len=idx; - - scsi_disk_log("scsi_disk_command(): Inquiry (%08X, %08X)\n", hdbufferb, dev->temp_buffer); - - if (len > max_len) - len = max_len; - - scsi_disk_set_buf_len(dev, BufLen, &len); - - if (len > *BufLen) - len = *BufLen; - - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_disk_data_command_finish(dev, len, len, max_len, 0); - break; - - case GPCMD_PREVENT_REMOVAL: - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_command_complete(dev); - break; - - case GPCMD_SEEK_6: - case GPCMD_SEEK_10: - switch(cdb[0]) { - case GPCMD_SEEK_6: - pos = (cdb[2] << 8) | cdb[3]; - break; - case GPCMD_SEEK_10: - pos = (cdb[2] << 24) | (cdb[3]<<16) | (cdb[4]<<8) | cdb[5]; - break; - } - scsi_disk_seek(dev, pos); - - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - scsi_disk_command_complete(dev); - break; - - case GPCMD_READ_CDROM_CAPACITY: - dev->temp_buffer = (uint8_t *) malloc(8); - - if (scsi_disk_read_capacity(dev, dev->current_cdb, dev->temp_buffer, (uint32_t *) &len) == 0) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - return; - } - - scsi_disk_set_buf_len(dev, BufLen, &len); - - scsi_disk_set_phase(dev, SCSI_PHASE_DATA_IN); - scsi_disk_data_command_finish(dev, len, len, len, 0); - break; - - default: - scsi_disk_illegal_opcode(dev); - break; - } - - /* scsi_disk_log("SCSI HD %i: Phase: %02X, request length: %i\n", dev->id, dev->phase, dev->request_length); */ -} - - -static void -scsi_disk_phase_data_in(scsi_disk_t *dev) -{ - uint8_t *hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer; - int32_t *BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength; - - if (!*BufLen) { - scsi_disk_log("scsi_disk_phase_data_in(): Buffer length is 0\n"); - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - - return; - } - - switch (dev->current_cdb[0]) { - case GPCMD_REQUEST_SENSE: - scsi_disk_log("SCSI HDD %i: %08X, %08X\n", dev->id, hdbufferb, *BufLen); - scsi_disk_request_sense(dev, hdbufferb, *BufLen, dev->current_cdb[1] & 1); - break; - case GPCMD_MECHANISM_STATUS: - memset(hdbufferb, 0, *BufLen); - hdbufferb[5] = 1; - break; - case GPCMD_READ_6: - case GPCMD_READ_10: - case GPCMD_READ_12: - if ((dev->requested_blocks > 0) && (*BufLen > 0)) { - if (dev->packet_len > (uint32_t) *BufLen) - hdd_image_read(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb); - else - hdd_image_read(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb); - } - break; - case GPCMD_MODE_SENSE_6: - case GPCMD_MODE_SENSE_10: - case GPCMD_INQUIRY: - case GPCMD_READ_CDROM_CAPACITY: - scsi_disk_log("scsi_disk_phase_data_in(): Filling buffer (%08X, %08X)\n", hdbufferb, dev->temp_buffer); - memcpy(hdbufferb, dev->temp_buffer, *BufLen); - free(dev->temp_buffer); - dev->temp_buffer = NULL; - scsi_disk_log("%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", - hdbufferb[0], hdbufferb[1], hdbufferb[2], hdbufferb[3], hdbufferb[4], hdbufferb[5], hdbufferb[6], hdbufferb[7], - hdbufferb[8], hdbufferb[9], hdbufferb[10], hdbufferb[11], hdbufferb[12], hdbufferb[13], hdbufferb[14], hdbufferb[15]); - break; - default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); - break; - } - - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); -} - - -static void -scsi_disk_phase_data_out(scsi_disk_t *dev) -{ - uint8_t *hdbufferb = SCSIDevices[dev->drv->scsi_id].CmdBuffer; - int i; - int32_t *BufLen = &SCSIDevices[dev->drv->scsi_id].BufferLength; - uint32_t last_sector = hdd_image_get_last_sector(dev->id); - uint32_t c, h, s, last_to_write = 0; - uint16_t block_desc_len, pos; - uint8_t hdr_len, val, old_val, ch, error = 0; - uint8_t page, page_len; - - if (!*BufLen) { - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); - - return; - } - - switch (dev->current_cdb[0]) { - case GPCMD_VERIFY_6: - case GPCMD_VERIFY_10: - case GPCMD_VERIFY_12: - break; - case GPCMD_WRITE_6: - case GPCMD_WRITE_10: - case GPCMD_WRITE_AND_VERIFY_10: - case GPCMD_WRITE_12: - case GPCMD_WRITE_AND_VERIFY_12: - if ((dev->requested_blocks > 0) && (*BufLen > 0)) { - if (dev->packet_len > (uint32_t) *BufLen) - hdd_image_write(dev->id, dev->sector_pos, *BufLen >> 9, hdbufferb); - else - hdd_image_write(dev->id, dev->sector_pos, dev->requested_blocks, hdbufferb); - } - break; - case GPCMD_WRITE_SAME_10: - if (!dev->current_cdb[7] && !dev->current_cdb[8]) - last_to_write = last_sector; - else - last_to_write = dev->sector_pos + dev->sector_len - 1; - - for (i = dev->sector_pos; i <= (int) last_to_write; i++) { - if (dev->current_cdb[1] & 2) { - hdbufferb[0] = (i >> 24) & 0xff; - hdbufferb[1] = (i >> 16) & 0xff; - hdbufferb[2] = (i >> 8) & 0xff; - hdbufferb[3] = i & 0xff; - } else if (dev->current_cdb[1] & 4) { - s = (i % dev->drv->spt); - h = ((i - s) / dev->drv->spt) % dev->drv->hpc; - c = ((i - s) / dev->drv->spt) / dev->drv->hpc; - hdbufferb[0] = (c >> 16) & 0xff; - hdbufferb[1] = (c >> 8) & 0xff; - hdbufferb[2] = c & 0xff; - hdbufferb[3] = h & 0xff; - hdbufferb[4] = (s >> 24) & 0xff; - hdbufferb[5] = (s >> 16) & 0xff; - hdbufferb[6] = (s >> 8) & 0xff; - hdbufferb[7] = s & 0xff; - } - hdd_image_write(dev->id, i, 1, hdbufferb); - } - break; - case GPCMD_MODE_SELECT_6: - case GPCMD_MODE_SELECT_10: - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_10) - hdr_len = 8; - else - hdr_len = 4; - - if (dev->current_cdb[0] == GPCMD_MODE_SELECT_6) { - block_desc_len = hdbufferb[2]; - block_desc_len <<= 8; - block_desc_len |= hdbufferb[3]; - } else { - block_desc_len = hdbufferb[6]; - block_desc_len <<= 8; - block_desc_len |= hdbufferb[7]; - } - - pos = hdr_len + block_desc_len; - - while(1) { - page = hdbufferb[pos] & 0x3F; - page_len = hdbufferb[pos + 1]; - - pos += 2; - - if (!(scsi_disk_mode_sense_page_flags & (1LL << ((uint64_t) page)))) - error |= 1; - else { - for (i = 0; i < page_len; i++) { - ch = scsi_disk_mode_sense_pages_changeable.pages[page][i + 2]; - val = hdbufferb[pos + i]; - old_val = dev->ms_pages_saved.pages[page][i + 2]; - if (val != old_val) { - if (ch) - dev->ms_pages_saved.pages[page][i + 2] = val; - else - error |= 1; - } - } - } - - pos += page_len; - - val = scsi_disk_mode_sense_pages_default.pages[page][0] & 0x80; - if (dev->do_page_save && val) - scsi_disk_mode_sense_save(dev); - - if (pos >= dev->total_length) - break; - } - - if (error) - scsi_disk_invalid_field_pl(dev); - break; - default: - fatal("SCSI HDD %i: Bad Command for phase 2 (%02X)\n", dev->id, dev->current_cdb[0]); - break; - } - - scsi_disk_set_phase(dev, SCSI_PHASE_STATUS); -} - - -/* If the result is 1, issue an IRQ, otherwise not. */ -void -scsi_disk_callback(scsi_disk_t *dev) -{ - switch(dev->packet_status) { - case CDROM_PHASE_IDLE: - scsi_disk_log("SCSI HD %i: PHASE_IDLE\n", dev->id); - dev->phase = 1; - dev->status = READY_STAT | DRQ_STAT | (dev->status & ERR_STAT); - return; - case CDROM_PHASE_COMPLETE: - scsi_disk_log("SCSI HD %i: PHASE_COMPLETE\n", dev->id); - dev->status = READY_STAT; - dev->phase = 3; - dev->packet_status = 0xFF; - return; - case CDROM_PHASE_DATA_OUT_DMA: - scsi_disk_log("SCSI HD %i: PHASE_DATA_OUT_DMA\n", dev->id); - scsi_disk_phase_data_out(dev); - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->status = READY_STAT; - dev->phase = 3; - return; - case CDROM_PHASE_DATA_IN_DMA: - scsi_disk_log("SCSI HD %i: PHASE_DATA_IN_DMA\n", dev->id); - scsi_disk_phase_data_in(dev); - dev->packet_status = CDROM_PHASE_COMPLETE; - dev->status = READY_STAT; - dev->phase = 3; - return; - case CDROM_PHASE_ERROR: - scsi_disk_log("SCSI HD %i: PHASE_ERROR\n", dev->id); - dev->status = READY_STAT | ERR_STAT; - dev->phase = 3; - return; - } -} - - -/* Peform a master init on the entire module. */ -void -scsi_disk_global_init(void) -{ - /* Clear the global data. */ - memset(scsi_disk, 0x00, sizeof(scsi_disk)); -} - - -void -scsi_disk_hard_reset(void) -{ - int c; - - for (c = 0; c < HDD_NUM; c++) { - if (hdd[c].bus == HDD_BUS_SCSI) { - scsi_disk_log("SCSI disk hard_reset drive=%d\n", c); - - if (!scsi_disk[c]) { - scsi_disk[c] = (scsi_disk_t *) malloc(sizeof(scsi_disk_t)); - memset(scsi_disk[c], 0, sizeof(scsi_disk_t)); - } - - scsi_disk[c]->id = c; - scsi_disk[c]->drv = &hdd[c]; - - scsi_disk_mode_sense_load(scsi_disk[c]); - } - } -} - - -void -scsi_disk_close(void) -{ - scsi_disk_t *dev; - int c; - - for (c = 0; c < HDD_NUM; c++) { - dev = scsi_disk[c]; - - if (dev) { - hdd_image_close(c); - - free(scsi_disk[c]); - scsi_disk[c] = NULL; - } - } -} diff --git a/src/scsi - Cópia/scsi_disk.h b/src/scsi - Cópia/scsi_disk.h deleted file mode 100644 index 36898f266..000000000 --- a/src/scsi - Cópia/scsi_disk.h +++ /dev/null @@ -1,60 +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. - * - * Emulation of SCSI fixed and removable disks. - * - * Version: @(#)scsi_disk.h 1.0.5 2018/06/02 - * - * Author: Miran Grca, - * Copyright 2017,2018 Miran Grca. - */ - - -typedef struct { - mode_sense_pages_t ms_pages_saved; - - hard_disk_t *drv; - - /* Stuff for SCSI hard disks. */ - uint8_t status, phase, - error, id, - current_cdb[16], - sense[256]; - - uint16_t request_length; - - int requested_blocks, block_total, - packet_status, callback, - block_descriptor_len, - total_length, do_page_save; - - uint32_t sector_pos, sector_len, - packet_len; - - uint64_t current_page_code; - - uint8_t *temp_buffer; -} scsi_disk_t; - - -extern scsi_disk_t *scsi_disk[HDD_NUM]; -extern uint8_t scsi_disks[16]; - - -extern void scsi_loadhd(int scsi_id, int id); -extern void scsi_disk_global_init(void); -extern void scsi_disk_hard_reset(void); -extern void scsi_disk_close(void); - -extern int scsi_disk_read_capacity(scsi_disk_t *dev, uint8_t *cdb, uint8_t *buffer, uint32_t *len); -extern int scsi_disk_err_stat_to_scsi(scsi_disk_t *dev); -extern int scsi_disk_phase_to_scsi(scsi_disk_t *dev); -extern int find_hdd_for_scsi_id(uint8_t scsi_id); -extern void build_scsi_disk_map(void); -extern void scsi_disk_reset(scsi_disk_t *dev); -extern void scsi_disk_request_sense_for_scsi(scsi_disk_t *dev, uint8_t *buffer, uint8_t alloc_length); -extern void scsi_disk_command(scsi_disk_t *dev, uint8_t *cdb); -extern void scsi_disk_callback(scsi_disk_t *dev); diff --git a/src/scsi - Cópia/scsi_ncr5380.c b/src/scsi - Cópia/scsi_ncr5380.c deleted file mode 100644 index a5107bfb6..000000000 --- a/src/scsi - Cópia/scsi_ncr5380.c +++ /dev/null @@ -1,1756 +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 NCR 5380 series of SCSI Host Adapters - * made by NCR. These controllers were designed for the ISA bus. - * - * Version: @(#)scsi_ncr5380.c 1.0.16 2018/07/19 - * - * Authors: Sarah Walker, - * TheCollector1995, - * Fred N. van Kempen, - * - * Copyright 2017,2018 Sarah Walker. - * Copyright 2017,2018 TheCollector1995. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../mca.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../timer.h" -#include "../plat.h" -#include "scsi.h" -#include "scsi_device.h" -#include "scsi_ncr5380.h" - - -#define LCS6821N_ROM L"roms/scsi/ncr5380/Longshine LCS-6821N - BIOS version 1.04.bin" -#define RT1000B_ROM L"roms/scsi/ncr5380/Rancho_RT1000_RTBios_version_8.10R.bin" -#define T130B_ROM L"roms/scsi/ncr5380/trantor_t130b_bios_v2.14.bin" -#define SCSIAT_ROM L"roms/scsi/ncr5380/sumo_scsiat_bios_v6.3.bin" - - -#define NCR_CURDATA 0 /* current SCSI data (read only) */ -#define NCR_OUTDATA 0 /* output data (write only) */ -#define NCR_INITCOMMAND 1 /* initiator command (read/write) */ -#define NCR_MODE 2 /* mode (read/write) */ -#define NCR_TARGETCMD 3 /* target command (read/write) */ -#define NCR_SELENABLE 4 /* select enable (write only) */ -#define NCR_BUSSTATUS 4 /* bus status (read only) */ -#define NCR_STARTDMA 5 /* start DMA send (write only) */ -#define NCR_BUSANDSTAT 5 /* bus and status (read only) */ -#define NCR_DMATARGET 6 /* DMA target (write only) */ -#define NCR_INPUTDATA 6 /* input data (read only) */ -#define NCR_DMAINIRECV 7 /* DMA initiator receive (write only) */ -#define NCR_RESETPARITY 7 /* reset parity/interrupt (read only) */ - -#define ICR_DBP 0x01 -#define ICR_ATN 0x02 -#define ICR_SEL 0x04 -#define ICR_BSY 0x08 -#define ICR_ACK 0x10 -#define ICR_ARB_LOST 0x20 -#define ICR_ARB_IN_PROGRESS 0x40 - -#define MODE_ARBITRATE 0x01 -#define MODE_DMA 0x02 -#define MODE_MONITOR_BUSY 0x04 -#define MODE_ENA_EOP_INT 0x08 - -#define STATUS_ACK 0x01 -#define STATUS_BUSY_ERROR 0x04 -#define STATUS_PHASE_MATCH 0x08 -#define STATUS_INT 0x10 -#define STATUS_DRQ 0x40 -#define STATUS_END_OF_DMA 0x80 - -#define TCR_IO 0x01 -#define TCR_CD 0x02 -#define TCR_MSG 0x04 -#define TCR_REQ 0x08 -#define TCR_LAST_BYTE_SENT 0x80 - -#define CTRL_DATA_DIR 0x40 -#define STATUS_BUFFER_NOT_READY 0x04 -#define STATUS_53C80_ACCESSIBLE 0x80 - -typedef struct { - uint8_t icr; - uint8_t mode; - uint8_t tcr; - uint8_t ser; - uint8_t isr; - uint8_t output_data; - - uint8_t target_id; - - int dma_mode; - - int bus_host, cur_bus, bus_in; - int new_phase; - int state; - - int clear_req, wait_data, wait_complete; - - int command_pos; - uint8_t command[20]; - int data_pos; - uint8_t tx_data; - - uint8_t unk_08, unk_08_ret; -} ncr_t; - -typedef struct { - const char *name; - uint32_t rom_addr; - uint16_t base; - int8_t irq; - int8_t type; - - rom_t bios_rom; - mem_mapping_t mapping; - - uint8_t block_count; - int block_count_loaded; - - uint8_t status_ctrl; - - uint8_t buffer[128]; - int buffer_pos; - int buffer_host_pos; - - uint8_t int_ram[0x40]; - uint8_t ext_ram[0x600]; - - ncr_t ncr; - - int dma_enabled; - - int64_t timer_period; - int64_t timer_enabled; - - int64_t media_period; - int64_t temp_period; - - int ncr_busy; - - double period; - - int is_non_data_mode; -} ncr5380_t; - -#define STATE_IDLE 0 -#define STATE_COMMAND 1 -#define STATE_DATAIN 2 -#define STATE_DATAOUT 3 -#define STATE_STATUS 4 -#define STATE_MESSAGEIN 5 -#define STATE_SELECT 6 - -#define DMA_IDLE 0 -#define DMA_SEND 1 -#define DMA_INITIATOR_RECEIVE 2 - -#ifdef ENABLE_NCR5380_LOG -int ncr5380_do_log = ENABLE_NCR5380_LOG; -#endif - - -static void -ncr_log(const char *fmt, ...) -{ -#ifdef ENABLE_NCR5380_LOG - va_list ap; - - if (ncr5380_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - -#define SET_BUS_STATE(ncr, state) ncr->cur_bus = (ncr->cur_bus & ~(SCSI_PHASE_MESSAGE_IN)) | (state & (SCSI_PHASE_MESSAGE_IN)) - -static void -ncr_callback(void *priv); - -static int -get_dev_id(uint8_t data) -{ - int c; - - for (c = 0; c < SCSI_ID_MAX; c++) { - if (data & (1 << c)) return(c); - } - - return(-1); -} - -/* get the length of a SCSI command based on its command byte type */ -static int -get_cmd_len(int cbyte) -{ - int len; - int group; - - group = (cbyte>>5) & 7; - - if (group == 0) len = 6; - if (group == 1 || group == 2) len = 10; - - return(len); -} - -static void -ncr_reset(ncr_t *ncr) -{ - memset(ncr, 0x00, sizeof(ncr_t)); - ncr_log("NCR reset\n"); -} - -static uint32_t -get_bus_host(ncr_t *ncr) -{ - uint32_t bus_host = 0; - - if (ncr->icr & ICR_DBP) - { - ncr_log("Data bus phase\n"); - bus_host |= BUS_DBP; - } - if (ncr->icr & ICR_SEL) - { - ncr_log("Selection phase\n"); - bus_host |= BUS_SEL; - } - if (ncr->tcr & TCR_IO) - { - ncr_log("Data phase\n"); - bus_host |= BUS_IO; - } - if (ncr->tcr & TCR_CD) - { - ncr_log("Command phase\n"); - bus_host |= BUS_CD; - } - if (ncr->tcr & TCR_MSG) - { - ncr_log("Message phase\n"); - bus_host |= BUS_MSG; - } - if (ncr->tcr & TCR_REQ) - { - ncr_log("Request phase\n"); - bus_host |= BUS_REQ; - } - if (ncr->icr & ICR_BSY) - { - ncr_log("Busy phase\n"); - bus_host |= BUS_BSY; - } - if (ncr->icr & ICR_ATN) - { - bus_host |= BUS_ATN; - } - if (ncr->icr & ICR_ACK) - { - ncr_log("ACK phase\n"); - bus_host |= BUS_ACK; - } - if (ncr->mode & MODE_ARBITRATE) - { - bus_host |= BUS_ARB; - } - - return(bus_host | BUS_SETDATA(ncr->output_data)); -} - -static void -ncr_wait_process(ncr5380_t *ncr_dev) -{ - ncr_t *ncr = &ncr_dev->ncr; - - /*Wait processes to handle bus requests*/ - ncr_log("Clear REQ=%d\n", ncr->clear_req); - if (ncr->clear_req) - { - ncr->clear_req--; - if (!ncr->clear_req) - { - ncr_log("Prelude to command data\n"); - SET_BUS_STATE(ncr, ncr->new_phase); - ncr->cur_bus |= BUS_REQ; - } - } - - if (ncr->wait_data) - { - ncr->wait_data--; - if (!ncr->wait_data) - { - scsi_device_t *dev; - - dev = &SCSIDevices[ncr->target_id]; - SET_BUS_STATE(ncr, ncr->new_phase); - - if (ncr->new_phase == SCSI_PHASE_DATA_IN) - { - ncr_log("Data In bus phase\n"); - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; - ncr->state = STATE_DATAIN; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP; - } - else if (ncr->new_phase == SCSI_PHASE_STATUS) - { - ncr_log("Status bus phase\n"); - ncr->cur_bus |= BUS_REQ; - ncr->state = STATE_STATUS; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(dev->Status) | BUS_DBP; - } - else if (ncr->new_phase == SCSI_PHASE_MESSAGE_IN) - { - ncr_log("Message In bus phase\n"); - ncr->state = STATE_MESSAGEIN; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(0) | BUS_DBP; - } - else - { - if (ncr->new_phase & BUS_IDLE) { - ncr_log("Bus Idle phase\n"); - ncr->state = STATE_IDLE; - ncr->cur_bus &= ~BUS_BSY; - ncr_dev->media_period = 0LL; - ncr_dev->temp_period = 0LL; - } else { - ncr->state = STATE_DATAOUT; - ncr_log("Data Out bus phase\n"); - } - } - } - } - - if (ncr->wait_complete) - { - ncr->wait_complete--; - if (!ncr->wait_complete) - { - ncr->cur_bus |= BUS_REQ; - } - } - - ncr->bus_host = ncr->cur_bus; -} - -static void -ncr_write(uint16_t port, uint8_t val, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - - ncr_log("NCR5380 write(%04x,%02x) @%04X:%04X\n",port & 7,val,CS,cpu_state.pc); - - switch (port & 7) { - case 0: /* Output data register */ - ncr_log("Write: Output data register\n"); - ncr->output_data = val; - break; - - case 1: /* Initiator Command Register */ - ncr_log("Write: Initiator command register\n"); - ncr->icr = val; - - ncr_dev->timer_enabled = 1; - break; - - case 2: /* Mode register */ - ncr_log("Write: Mode register, val=%02x\n", val & MODE_DMA); - if ((val & MODE_ARBITRATE) && !(ncr->mode & MODE_ARBITRATE)) { - ncr->icr &= ~ICR_ARB_LOST; - ncr->icr |= ICR_ARB_IN_PROGRESS; - } - - ncr->mode = val; - - /*If it's not DMA mode, don't do anything*/ - if (!(ncr->mode & MODE_DMA)) { - ncr_log("No DMA mode\n"); - ncr->tcr &= ~TCR_LAST_BYTE_SENT; - ncr->isr &= ~STATUS_END_OF_DMA; - ncr->dma_mode = DMA_IDLE; - } - break; - - case 3: /* Target Command Register */ - ncr_log("Write: Target Command register\n"); - ncr->tcr = val; - break; - - case 4: /* Select Enable Register */ - ncr_log("Write: Select Enable register\n"); - break; - - case 5: /* start DMA Send */ - ncr_log("Write: start DMA send register\n"); - ncr_log("Write 6 or 10, block count loaded=%d\n", ncr_dev->block_count_loaded); - /*a Write 6/10 has occurred, start the timer when the block count is loaded*/ - ncr->dma_mode = DMA_SEND; - break; - - case 7: /* start DMA Initiator Receive */ - ncr_log("Write: start DMA initiator receive register\n"); - ncr_log("Read 6 or 10, block count loaded=%d\n", ncr_dev->block_count_loaded); - /*a Read 6/10 has occurred, start the timer when the block count is loaded*/ - ncr->dma_mode = DMA_INITIATOR_RECEIVE; - break; - - default: - ncr_log("NCR5380: bad write %04x %02x\n", port, val); - break; - } -} - -static uint8_t -ncr_read(uint16_t port, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - uint8_t ret = 0xff; - - switch (port & 7) { - case 0: /* Current SCSI data */ - ncr_log("Read: Current SCSI data register\n"); - if (ncr->icr & ICR_DBP) { - /*Return the data from the output register if on data bus phase from ICR*/ - ncr_log("Data Bus Phase\n"); - ret = ncr->output_data; - } else { - /*Return the data from the SCSI bus*/ - ncr_wait_process(ncr_dev); - ncr_log("NCR GetData=%02x\n", BUS_GETDATA(ncr->bus_host)); - ret = BUS_GETDATA(ncr->bus_host); - } - break; - - case 1: /* Initiator Command Register */ - ncr_log("Read: Initiator Command register\n"); - ncr_log("NCR ICR Read=%02x\n", ncr->icr); - - ret = ncr->icr; - break; - - case 2: /* Mode register */ - ncr_log("Read: Mode register\n"); - ret = ncr->mode; - break; - - case 3: /* Target Command Register */ - ncr_log("Read: Target Command register\n"); - ncr_log("NCR target stat=%02x\n", ncr->tcr); - ret = ncr->tcr; - break; - - case 4: /* Current SCSI Bus status */ - ncr_log("Read: SCSI bus status register\n"); - ret = 0; - ncr_wait_process(ncr_dev); - ncr_log("NCR cur bus stat=%02x\n", ncr->bus_host & 0xff); - ret |= (ncr->bus_host & 0xff); - break; - - case 5: /* Bus and Status register */ - ncr_log("Read: Bus and Status register\n"); - ret = 0; - - ncr->bus_host = get_bus_host(ncr); - ncr_log("Get host from Interrupt\n"); - - /*Check if the phase in process matches with TCR's*/ - if ((ncr->bus_host & SCSI_PHASE_MESSAGE_IN) == - (ncr->cur_bus & SCSI_PHASE_MESSAGE_IN)) - { - ncr_log("Phase match\n"); - ret |= STATUS_PHASE_MATCH; - } - else - picint(1 << ncr_dev->irq); - - ncr_wait_process(ncr_dev); - - if (ncr->bus_host & BUS_ACK) - ret |= STATUS_ACK; - - if ((ncr->bus_host & BUS_REQ) && (ncr->mode & MODE_DMA)) { - ncr_log("Entering DMA mode\n"); - ret |= STATUS_DRQ; - - int bus = 0; - - if (ncr->bus_host & BUS_IO) - bus |= TCR_IO; - if (ncr->bus_host & BUS_CD) - bus |= TCR_CD; - if (ncr->bus_host & BUS_MSG) - bus |= TCR_MSG; - if ((ncr->tcr & 7) != bus) - { - ncr->isr |= STATUS_INT; - } - } - if (!(ncr->bus_host & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) - { - ncr_log("Busy error\n"); - ret |= STATUS_BUSY_ERROR; - } - ret |= (ncr->isr & (STATUS_INT | STATUS_END_OF_DMA)); - break; - - case 7: /* reset Parity/Interrupt */ - ncr->isr &= ~STATUS_INT; - picintc(1 << ncr_dev->irq); - ncr_log("Reset IRQ\n"); - break; - - default: - ncr_log("NCR5380: bad read %04x\n", port); - break; - } - - ncr_log("NCR5380 read(%04x)=%02x @%04X:%04X\n", port & 7, ret, CS,cpu_state.pc); - - return(ret); -} - -/* Memory-mapped I/O READ handler. */ -static uint8_t -memio_read(uint32_t addr, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - uint8_t ret = 0xff; - - addr &= 0x3fff; -#if ENABLE_NCR5380_LOG - ncr_log("memio_read %08x\n", addr); -#endif - - if (addr < 0x2000) - ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; - else if (addr < 0x3800) - ret = 0xff; - else if (addr >= 0x3a00) - ret = ncr_dev->ext_ram[addr - 0x3a00]; - else switch (addr & 0x3f80) { - case 0x3800: -#if ENABLE_NCR5380_LOG - ncr_log("Read intRAM %02x %02x\n", addr & 0x3f, ncr_dev->int_ram[addr & 0x3f]); -#endif - ret = ncr_dev->int_ram[addr & 0x3f]; - break; - - case 0x3880: -#if ENABLE_NCR5380_LOG - ncr_log("Read 53c80 %04x\n", addr); -#endif - ret = ncr_read(addr, ncr_dev); - break; - - case 0x3900: - ncr_log("Read 3900 host pos %i status ctrl %02x\n", ncr_dev->buffer_host_pos, ncr_dev->status_ctrl); - ncr_log("Read port 0x3900-0x397f\n"); - - if (ncr_dev->buffer_host_pos >= 128 || !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) - ret = 0xff; - else { - ret = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; - - ncr_log("Read host buffer=%d\n", ncr_dev->buffer_host_pos); - - if (ncr_dev->buffer_host_pos == 128) - { - ncr_log("Not ready\n"); - ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; - } - } - break; - - case 0x3980: - switch (addr) { - case 0x3980: /* status */ - ret = ncr_dev->status_ctrl;// | 0x80; - ncr_log("NCR status ctrl read=%02x\n", ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY); - if (!ncr_dev->ncr_busy) - { - ret |= STATUS_53C80_ACCESSIBLE; - } - break; - - case 0x3981: /* block counter register*/ - ret = ncr_dev->block_count; - break; - - case 0x3982: /* switch register read */ - ret = 0xff; - break; - - case 0x3983: - ret = 0xff; - break; - } - break; - } - -#if ENABLE_NCR5380_LOG - if (addr >= 0x3880) - ncr_log("memio_read(%08x)=%02x\n", addr, ret); -#endif - - return(ret); -} - - -/* Memory-mapped I/O WRITE handler. */ -static void -memio_write(uint32_t addr, uint8_t val, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - - addr &= 0x3fff; - - ncr_log("memio_write(%08x,%02x) @%04X:%04X %i %02x\n", addr, val, CS,cpu_state.pc, ncr_dev->buffer_host_pos, ncr_dev->status_ctrl); - - if (addr >= 0x3a00) - ncr_dev->ext_ram[addr - 0x3a00] = val; - else switch (addr & 0x3f80) { - case 0x3800: -#if 0 - ncr_log("Write intram %02x %02x\n", addr & 0x3f, val); -#endif - ncr_dev->int_ram[addr & 0x3f] = val; - break; - - case 0x3880: -#if ENABLE_NCR5380_LOG - ncr_log("Write 53c80 %04x %02x\n", addr, val); -#endif - ncr_write(addr, val, ncr_dev); - break; - - case 0x3900: - if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR) && ncr_dev->buffer_host_pos < 128) { - ncr_dev->buffer[ncr_dev->buffer_host_pos++] = val; - - if (ncr_dev->buffer_host_pos == 128) - { - ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; - ncr_dev->ncr_busy = 1; - } - } - break; - - case 0x3980: - switch (addr) { - case 0x3980: /* Control */ - ncr_log("Write 0x3980: val=%02x CS=%04x, pc=%04x\n", val, CS,cpu_state.pc); - if (val & 0x80) - { - ncr_log("Resetting the 53c400\n"); - picint(1 << ncr_dev->irq); - } - - if ((val & CTRL_DATA_DIR) && !(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_log("Pos 128\n"); - ncr_dev->buffer_host_pos = 128; - ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; - } - else if (!(val & CTRL_DATA_DIR) && (ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_log("Pos 0\n"); - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - } - ncr_dev->status_ctrl = (ncr_dev->status_ctrl & 0x87) | (val & 0x78); - break; - - case 0x3981: /* block counter register */ - ncr_log("Write 0x3981: val=%d\n", val); - ncr_dev->block_count = val; - ncr_dev->block_count_loaded = 1; - - ncr_log("Timer for transfers=%02x\n", ncr_dev->timer_enabled); - - if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { - ncr_log("Data Read\n"); - ncr_dev->buffer_host_pos = 128; - ncr_dev->status_ctrl |= STATUS_BUFFER_NOT_READY; - } else { - ncr_log("Data Write\n"); - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - } - break; - } - break; - } -} - - -/* Memory-mapped I/O READ handler for the Trantor T130B. */ -static uint8_t -t130b_read(uint32_t addr, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - uint8_t ret = 0xff; - - addr &= 0x3fff; - if (addr < 0x1800) - ret = ncr_dev->bios_rom.rom[addr & 0x1fff]; - else - if (addr < 0x1880) - ret = ncr_dev->ext_ram[addr & 0x7f]; - - return(ret); -} - - -/* Memory-mapped I/O WRITE handler for the Trantor T130B. */ -static void -t130b_write(uint32_t addr, uint8_t val, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - - addr &= 0x3fff; - if (addr >= 0x1800 && addr < 0x1880) - ncr_dev->ext_ram[addr & 0x7f] = val; -} - - -static uint8_t -t130b_in(uint16_t port, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - uint8_t ret = 0xff; - - switch (port & 0x0f) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - ret = memio_read((port & 7) | 0x3980, ncr_dev); - break; - - case 0x04: - case 0x05: - ret = memio_read(0x3900, ncr_dev); - break; - - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - ret = ncr_read(port, ncr_dev); - break; - } - - return(ret); -} - - -static void -t130b_out(uint16_t port, uint8_t val, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - - switch (port & 0x0f) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - memio_write((port & 7) | 0x3980, val, ncr_dev); - break; - - case 0x04: - case 0x05: - memio_write(0x3900, val, ncr_dev); - break; - - case 0x08: - case 0x09: - case 0x0a: - case 0x0b: - case 0x0c: - case 0x0d: - case 0x0e: - case 0x0f: - ncr_write(port, val, ncr_dev); - break; - } -} - -static uint8_t -scsiat_in(uint16_t port, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - uint8_t ret = 0xff; - - switch (port & 0x0f) { - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - ret = ncr_read(port, ncr_dev); - break; - } - - pclog("SCSI AT read=0x%03x, ret=%02x, CS:%08x, PC:%08x\n", port, ret, CS,cpu_state.pc); - - return(ret); -} - - -static void -scsiat_out(uint16_t port, uint8_t val, void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &SCSIDevices[ncr->target_id]; - - pclog("SCSI AT write=0x%03x, val=%02x, CS:%08x, PC:%08x\n", port, val, CS,cpu_state.pc); - switch (port & 0x0f) { - case 0x08: - ncr->unk_08 = val; - - if (ncr->unk_08 & 0x08) - { - if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) - { - while (ncr_dev->buffer_host_pos < 128) - { - uint8_t temp; - - temp = ncr_dev->buffer[ncr_dev->buffer_host_pos++]; - - pclog("Read Buffer host=%d\n", ncr_dev->buffer_host_pos); - - ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; - ncr->bus_host |= BUS_SETDATA(temp); - - if (ncr_dev->buffer_host_pos == 128) - break; - } - } - else if (ncr->dma_mode == DMA_SEND) - { - while (ncr_dev->buffer_host_pos < 128) - { - /* Data ready. */ - uint8_t temp; - - ncr_wait_process(ncr_dev); - temp = BUS_GETDATA(ncr->bus_host); - ncr->bus_host = get_bus_host(ncr); - - ncr_dev->buffer[ncr_dev->buffer_host_pos++] = temp; - - pclog("Write Buffer host=%d\n", ncr_dev->buffer_host_pos); - - if (ncr_dev->buffer_host_pos == 128) - { - - break; - } - } - } - } - - if (ncr->unk_08 & 0x01) - { - ncr_dev->block_count_loaded = 1; - ncr_dev->block_count = dev->BufferLength / 128; - } - break; - - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - ncr_write(port, val, ncr_dev); - break; - } -} - -static void -ncr_callback(void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - ncr_t *ncr = &ncr_dev->ncr; - scsi_device_t *dev = &SCSIDevices[ncr->target_id]; - int c = 0; - - ncr_log("DMA mode=%d\n", ncr->dma_mode); - - if (!ncr_dev->timer_enabled) - { - if (ncr->dma_mode == DMA_IDLE) - { - ncr_dev->timer_period = 10LL * TIMER_USEC; - return; - } - else - { - ncr_dev->timer_period += 10LL * TIMER_USEC; - } - } - else - { - ncr_dev->timer_enabled = 0; - } - - if (ncr->dma_mode == DMA_IDLE) - { - ncr->bus_host = get_bus_host(ncr); - - /*Start the SCSI command layer, which will also make the timings*/ - if (ncr->bus_host & BUS_ARB) - { - ncr_log("Arbitration\n"); - ncr->state = STATE_IDLE; - } - - if (ncr->state == STATE_IDLE) - { - ncr->clear_req = ncr->wait_data = ncr->wait_complete = 0; - if ((ncr->bus_host & BUS_SEL) && !(ncr->bus_host & BUS_BSY)) - { - ncr_log("Selection phase\n"); - uint8_t sel_data = BUS_GETDATA(ncr->bus_host); - - ncr->target_id = get_dev_id(sel_data); - - ncr_log("Select - target ID = %i\n", ncr->target_id); - - /*Once the device has been found and selected, mark it as busy*/ - if ((ncr->target_id != -1) && scsi_device_present(ncr->target_id)) { - ncr->cur_bus |= BUS_BSY; - ncr_log("Device found at ID %i\n", ncr->target_id); - ncr_log("Current Bus BSY=%02x\n", ncr->cur_bus); - ncr->state = STATE_COMMAND; - ncr->cur_bus = BUS_BSY | BUS_REQ; - ncr_log("CurBus BSY|REQ=%02x\n", ncr->cur_bus); - ncr->command_pos = 0; - SET_BUS_STATE(ncr, SCSI_PHASE_COMMAND); - picint(1 << ncr_dev->irq); - } - else - { - ncr->state = STATE_IDLE; - ncr->cur_bus = 0; - } - } - } - else if (ncr->state == STATE_COMMAND) - { - int64_t p; - - /*Command phase, make sure the ICR ACK bit is set to keep on, - because the device must be acknowledged by ICR*/ - ncr_log("NCR ICR for Command=%02x\n", ncr->bus_host & BUS_ACK); - if (ncr->bus_host & BUS_ACK) - { - /*Write command byte to the output data register*/ - ncr->command[ncr->command_pos++] = BUS_GETDATA(ncr->bus_host); - - ncr->new_phase = ncr->cur_bus & SCSI_PHASE_MESSAGE_IN; - ncr->clear_req = 3; - ncr_log("Current bus for command request=%02x\n", ncr->cur_bus & BUS_REQ); - ncr->cur_bus &= ~BUS_REQ; - - ncr_log("Command pos=%i, output data=%02x\n", ncr->command_pos, BUS_GETDATA(ncr->bus_host)); - if (get_cmd_len(ncr->command[0]) == ncr->command_pos) - { - /*Reset data position to default*/ - ncr->data_pos = 0; - - dev = &SCSIDevices[ncr->target_id]; - - ncr_log("SCSI Command 0x%02X for ID %d, status code=%02x\n", ncr->command[0], ncr->target_id, dev->Status); - - dev->BufferLength = -1; - - /*Now, execute the given SCSI command*/ - scsi_device_command_phase0(ncr->target_id, ncr->command); - - ncr_log("SCSI ID %i: Command %02X: Buffer Length %i, SCSI Phase %02X\n", ncr->target_id, ncr->command[0], dev->BufferLength, dev->Phase); - - if (dev->Status != SCSI_STATUS_OK) - ncr_dev->is_non_data_mode = 1; - - if (ncr_dev->is_non_data_mode) - { - ncr_dev->is_non_data_mode = 0; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - return; - } - - /*If the SCSI phase is Data In or Data Out, allocate the SCSI buffer based on the transfer length of the command*/ - if (dev->BufferLength && (dev->Phase == SCSI_PHASE_DATA_IN || dev->Phase == SCSI_PHASE_DATA_OUT)) { - dev->CmdBuffer = (uint8_t *) malloc(dev->BufferLength); - - p = scsi_device_get_callback(ncr->target_id); - if (p <= 0LL) { - ncr_dev->temp_period += (int64_t)(dev->BufferLength); - } else { - ncr_dev->media_period += p; - } - } - - if (dev->Phase == SCSI_PHASE_DATA_OUT) { - /* Write direction commands have delayed execution - only execute them after the bus has gotten all the data from the host. */ - ncr_log("Next state is data out\n"); - ncr->new_phase = SCSI_PHASE_DATA_OUT; - ncr->wait_data = 4; - ncr->clear_req = 4; - } else { - /* Other command - execute immediately. */ - ncr->new_phase = dev->Phase; - - if (ncr->new_phase == SCSI_PHASE_DATA_IN) - { - scsi_device_command_phase1(ncr->target_id); - } - - ncr->wait_data = 4; - } - } - } - } - else if (ncr->state == STATE_DATAIN) - { - dev = &SCSIDevices[ncr->target_id]; - ncr_log("Data In ACK=%02x\n", ncr->bus_host & BUS_ACK); - if (ncr->bus_host & BUS_ACK) - { - if (ncr->data_pos >= dev->BufferLength) { - - if (dev->CmdBuffer != NULL) - { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - } - } - else if (ncr->state == STATE_DATAOUT) - { - dev = &SCSIDevices[ncr->target_id]; - - ncr_log("Data Out ACK=%02x\n", ncr->bus_host & BUS_ACK); - if (ncr->bus_host & BUS_ACK) - { - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id); - - if (dev->CmdBuffer != NULL) - { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } - else - { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - } - } - else if (ncr->state == STATE_STATUS) - { - if (ncr->bus_host & BUS_ACK) - { - /*All transfers done, wait until next transfer*/ - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_MESSAGE_IN; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } - } - else if (ncr->state == STATE_MESSAGEIN) - { - if (ncr->bus_host & BUS_ACK) - { - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = BUS_IDLE; - ncr->wait_data = 4; - } - } - } - - if (ncr_dev->type < 3) - { - if (((ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY) && - (ncr->dma_mode == DMA_SEND || ncr->dma_mode == DMA_INITIATOR_RECEIVE))) - { - ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) ncr_dev->temp_period); - ncr_dev->timer_period = (ncr_dev->media_period + ((int64_t) ncr_dev->period) + (40LL * TIMER_USEC)) / 450; - ncr_log("Temporary period: %" PRId64 " us (%" PRIi64 " periods), media periods = %" PRId64 " \n", ncr_dev->timer_period, ncr_dev->temp_period, ncr_dev->media_period); - } - - if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) - { - if (!(ncr_dev->status_ctrl & CTRL_DATA_DIR)) { - ncr_log("DMA_INITIATOR_RECEIVE with DMA direction set wrong\n"); - return; - } - - ncr_log("Status for reading=%02x\n", ncr_dev->status_ctrl); - - if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) return; - - if (!ncr_dev->block_count_loaded) return; - - while (c < 64) - { - /* Data ready. */ - uint8_t temp; - - ncr_wait_process(ncr_dev); - temp = BUS_GETDATA(ncr->bus_host); - ncr->bus_host = get_bus_host(ncr); - - if (ncr->data_pos >= dev->BufferLength) { - - if (dev->CmdBuffer != NULL) - { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - ncr_log("Buffer pos for reading=%d\n", ncr_dev->buffer_pos); - - c++; - - if (ncr_dev->buffer_pos == 128) - { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - ncr_log("Remaining blocks to be read=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - ncr_log("IO End of read transfer\n"); - - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) - { - ncr_log("NCR read irq\n"); - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } - else if (ncr->dma_mode == DMA_SEND) - { - if (ncr_dev->status_ctrl & CTRL_DATA_DIR) { - ncr_log("DMA_SEND with DMA direction set wrong\n"); - return; - } - - ncr_log("Status for writing=%02x\n", ncr_dev->status_ctrl); - - if (!(ncr_dev->status_ctrl & STATUS_BUFFER_NOT_READY)) - { - ncr_log("Buffer ready\n"); - return; - } - - if (!ncr_dev->block_count_loaded) return; - - while (c < 64) - { - /* Data ready. */ - uint8_t data; - - data = ncr_dev->buffer[ncr_dev->buffer_pos]; - ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; - ncr->bus_host |= BUS_SETDATA(data); - - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id); - - if (dev->CmdBuffer != NULL) - { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } - else - { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - - c++; - - if (++ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->status_ctrl &= ~STATUS_BUFFER_NOT_READY; - ncr_dev->ncr_busy = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - ncr_log("Remaining blocks to be written=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - ncr_log("IO End of write transfer\n"); - - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) - { - ncr_log("NCR write irq\n"); - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } - } - else - { - if (((ncr->unk_08 & 0x01) && - (ncr->dma_mode == DMA_SEND || ncr->dma_mode == DMA_INITIATOR_RECEIVE))) - { - ncr_dev->period = 0.2 * ((double) TIMER_USEC) * ((double) ncr_dev->temp_period); - ncr_dev->timer_period = (ncr_dev->media_period + ((int64_t) ncr_dev->period) + (40LL * TIMER_USEC)) / 450; - ncr_log("Temporary period: %" PRId64 " us (%" PRIi64 " periods), media periods = %" PRId64 " \n", ncr_dev->timer_period, ncr_dev->temp_period, ncr_dev->media_period); - } - - if (ncr->dma_mode == DMA_INITIATOR_RECEIVE) - { - if (!(ncr_dev->block_count_loaded)) - return; - - while (c < 64) - { - /* Data ready. */ - uint8_t temp; - - ncr_wait_process(ncr_dev); - temp = BUS_GETDATA(ncr->bus_host); - ncr->bus_host = get_bus_host(ncr); - - if (ncr->data_pos >= dev->BufferLength) { - - if (dev->CmdBuffer != NULL) - { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } else { - ncr->tx_data = dev->CmdBuffer[ncr->data_pos++]; - ncr->cur_bus = (ncr->cur_bus & ~BUS_DATAMASK) | BUS_SETDATA(ncr->tx_data) | BUS_DBP | BUS_REQ; - ncr->clear_req = 3; - ncr->cur_bus &= ~BUS_REQ; - ncr->new_phase = SCSI_PHASE_DATA_IN; - } - - ncr_dev->buffer[ncr_dev->buffer_pos++] = temp; - pclog("Buffer pos for reading=%d\n", ncr_dev->buffer_pos); - - c++; - - if (ncr_dev->buffer_pos == 128) - { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - pclog("Remaining blocks to be read=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - ncr_log("IO End of read transfer\n"); - - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) - { - ncr_log("NCR read irq\n"); - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } - else if (ncr->dma_mode == DMA_SEND) - { - if (!ncr_dev->block_count_loaded) return; - - while (c < 64) - { - /* Data ready. */ - uint8_t data; - - data = ncr_dev->buffer[ncr_dev->buffer_pos]; - ncr->bus_host = get_bus_host(ncr) & ~BUS_DATAMASK; - ncr->bus_host |= BUS_SETDATA(data); - - dev->CmdBuffer[ncr->data_pos++] = BUS_GETDATA(ncr->bus_host); - - if (ncr->data_pos >= dev->BufferLength) { - scsi_device_command_phase1(ncr->target_id); - - if (dev->CmdBuffer != NULL) - { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - ncr->cur_bus &= ~BUS_REQ; - ncr_log("CurBus ~REQ_DataOutDone=%02x\n", ncr->cur_bus); - ncr->new_phase = SCSI_PHASE_STATUS; - ncr->wait_data = 4; - ncr->wait_complete = 8; - } - else - { - /*More data is to be transferred, place a request*/ - ncr->cur_bus |= BUS_REQ; - ncr_log("CurBus ~REQ_DataOut=%02x\n", ncr->cur_bus); - } - - c++; - - if (++ncr_dev->buffer_pos == 128) { - ncr_dev->buffer_pos = 0; - ncr_dev->buffer_host_pos = 0; - ncr_dev->block_count = (ncr_dev->block_count - 1) & 255; - pclog("Remaining blocks to be written=%d\n", ncr_dev->block_count); - if (!ncr_dev->block_count) { - ncr_dev->block_count_loaded = 0; - ncr_log("IO End of write transfer\n"); - - ncr->tcr |= TCR_LAST_BYTE_SENT; - ncr->isr |= STATUS_END_OF_DMA; - if (ncr->mode & MODE_ENA_EOP_INT) - { - ncr_log("NCR write irq\n"); - ncr->isr |= STATUS_INT; - picint(1 << ncr_dev->irq); - } - } - break; - } - } - } - } - - ncr_wait_process(ncr_dev); - if (!(ncr->bus_host & BUS_BSY) && (ncr->mode & MODE_MONITOR_BUSY)) { - pclog("Updating DMA\n"); - ncr->mode &= ~MODE_DMA; - ncr->dma_mode = DMA_IDLE; - } -} - - -static void * -ncr_init(const device_t *info) -{ - char temp[128]; - ncr5380_t *ncr_dev; - - ncr_dev = malloc(sizeof(ncr5380_t)); - memset(ncr_dev, 0x00, sizeof(ncr5380_t)); - ncr_dev->name = info->name; - ncr_dev->type = info->local; - - switch(ncr_dev->type) { - case 0: /* Longshine LCS6821N */ - ncr_dev->rom_addr = 0xDC000; - rom_init(&ncr_dev->bios_rom, LCS6821N_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - mem_mapping_disable(&ncr_dev->bios_rom.mapping); - - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - memio_read, NULL, NULL, - memio_write, NULL, NULL, - ncr_dev->bios_rom.rom, 0, ncr_dev); - break; - - case 1: /* Rancho RT1000B */ - ncr_dev->rom_addr = 0xDC000; - rom_init(&ncr_dev->bios_rom, RT1000B_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - mem_mapping_disable(&ncr_dev->bios_rom.mapping); - - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - memio_read, NULL, NULL, - memio_write, NULL, NULL, - ncr_dev->bios_rom.rom, 0, ncr_dev); - break; - - case 2: /* Trantor T130B */ - ncr_dev->rom_addr = 0xDC000; - ncr_dev->base = device_get_config_hex16("base"); - ncr_dev->irq = device_get_config_int("irq"); - rom_init(&ncr_dev->bios_rom, T130B_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - t130b_read, NULL, NULL, - t130b_write, NULL, NULL, - ncr_dev->bios_rom.rom, 0, ncr_dev); - - io_sethandler(ncr_dev->base, 16, - t130b_in,NULL,NULL, t130b_out,NULL,NULL, ncr_dev); - break; - - case 3: /* Sumo SCSI-AT */ - ncr_dev->base = device_get_config_hex16("base"); - ncr_dev->irq = device_get_config_int("irq"); - ncr_dev->rom_addr = device_get_config_hex20("bios_addr"); - rom_init(&ncr_dev->bios_rom, SCSIAT_ROM, - ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - mem_mapping_disable(&ncr_dev->bios_rom.mapping); - - mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000, - t130b_read, NULL, NULL, - t130b_write, NULL, NULL, - ncr_dev->bios_rom.rom, 0, ncr_dev); - - io_sethandler(ncr_dev->base, 16, - scsiat_in,NULL,NULL, scsiat_out,NULL,NULL, ncr_dev); - break; - } - - sprintf(temp, "%s: BIOS=%05X", ncr_dev->name, ncr_dev->rom_addr); - if (ncr_dev->base != 0) - sprintf(&temp[strlen(temp)], " I/O=%04x", ncr_dev->base); - if (ncr_dev->irq != 0) - sprintf(&temp[strlen(temp)], " IRQ=%d", ncr_dev->irq); - ncr_log("%s\n", temp); - - ncr_reset(&ncr_dev->ncr); - ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY; - ncr_dev->buffer_host_pos = 128; - - ncr_dev->timer_period = 10LL * TIMER_USEC; - timer_add(ncr_callback, &ncr_dev->timer_period, TIMER_ALWAYS_ENABLED, ncr_dev); - - return(ncr_dev); -} - - -static void -ncr_close(void *priv) -{ - ncr5380_t *ncr_dev = (ncr5380_t *)priv; - - if (ncr_dev) - { - /* Tell the timer to terminate. */ - ncr_dev->timer_period = 0LL; - ncr_dev->timer_enabled = 0LL; - - free(ncr_dev); - ncr_dev = NULL; - } -} - - -static int -lcs6821n_available(void) -{ - return(rom_present(LCS6821N_ROM)); -} - - -static int -rt1000b_available(void) -{ - return(rom_present(RT1000B_ROM)); -} - - -static int -t130b_available(void) -{ - return(rom_present(T130B_ROM)); -} - - -static int -scsiat_available(void) -{ - return(rom_present(SCSIAT_ROM)); -} - -static const device_config_t t130b_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x0350, - { - { - "240H", 0x0240 - }, - { - "250H", 0x0250 - }, - { - "340H", 0x0340 - }, - { - "350H", 0x0350 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, - { - { - "IRQ 3", 3 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 7", 7 - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; - -static const device_config_t scsiat_config[] = { - { - "base", "Address", CONFIG_HEX16, "", 0x0310, - { - { - "None", 0 - }, - { - "300H", 0x0300 - }, - { - "310H", 0x0310 - }, - { - "320H", 0x0320 - }, - { - "330H", 0x0330 - }, - { - "340H", 0x0340 - }, - { - "350H", 0x0350 - }, - { - "360H", 0x0360 - }, - { - "370H", 0x0370 - }, - { - "" - } - }, - }, - { - "irq", "IRQ", CONFIG_SELECTION, "", 5, - { - { - "IRQ 3", 3 - }, - { - "IRQ 4", 4 - }, - { - "IRQ 5", 5 - }, - { - "IRQ 10", 10 - }, - { - "IRQ 11", 11 - }, - { - "IRQ 12", 12 - }, - { - "IRQ 14", 14 - }, - { - "IRQ 15", 15 - }, - { - "" - } - }, - }, - { - "bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, - { - { - "Disabled", 0 - }, - { - "C800H", 0xc8000 - }, - { - "CC00H", 0xcc000 - }, - { - "D800H", 0xd8000 - }, - { - "DC00H", 0xdc000 - }, - { - "" - } - }, - }, - { - "", "", -1 - } -}; - - -const device_t scsi_lcs6821n_device = -{ - "Longshine LCS-6821N", - DEVICE_ISA, - 0, - ncr_init, ncr_close, NULL, - lcs6821n_available, - NULL, NULL, - NULL -}; - -const device_t scsi_rt1000b_device = -{ - "Rancho RT1000B", - DEVICE_ISA, - 1, - ncr_init, ncr_close, NULL, - rt1000b_available, - NULL, NULL, - NULL -}; - -const device_t scsi_t130b_device = -{ - "Trantor T130B", - DEVICE_ISA, - 2, - ncr_init, ncr_close, NULL, - t130b_available, - NULL, NULL, - t130b_config -}; - -const device_t scsi_scsiat_device = -{ - "Sumo SCSI-AT", - DEVICE_ISA, - 3, - ncr_init, ncr_close, NULL, - scsiat_available, - NULL, NULL, - scsiat_config -}; diff --git a/src/scsi - Cópia/scsi_ncr5380.h b/src/scsi - Cópia/scsi_ncr5380.h deleted file mode 100644 index 55b16f654..000000000 --- a/src/scsi - Cópia/scsi_ncr5380.h +++ /dev/null @@ -1,33 +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 NCR 5380 series of SCSI Host Adapters - * made by NCR. These controllers were designed for - * the ISA bus. - * - * Version: @(#)scsi_ncr5380.c 1.0.2 2018/03/18 - * - * Authors: Sarah Walker, - * TheCollector1995, - * Fred N. van Kempen, - * - * Copyright 2017-2018 Sarah Walker. - * Copyright 2017-2018 TheCollector1995. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#ifndef SCSI_NCR5380_H -# define SCSI_NCR5380_H - - -extern const device_t scsi_lcs6821n_device; -extern const device_t scsi_rt1000b_device; -extern const device_t scsi_t130b_device; -extern const device_t scsi_scsiat_device; - - -#endif /*SCSI_NCR5380_H*/ diff --git a/src/scsi - Cópia/scsi_ncr53c810.c b/src/scsi - Cópia/scsi_ncr53c810.c deleted file mode 100644 index 459ca28fd..000000000 --- a/src/scsi - Cópia/scsi_ncr53c810.c +++ /dev/null @@ -1,2213 +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 NCR 53C810 SCSI Host Adapter made by - * NCR and later Symbios and LSI. This controller was designed - * for the PCI bus. - * - * Version: @(#)scsi_ncr53c810.c 1.0.14 2018/05/28 - * - * Authors: Paul Brook (QEMU) - * Artyom Tarasenko (QEMU) - * TheCollector1995, - * Miran Grca, - * - * Copyright 2006-2018 Paul Brook. - * Copyright 2009-2018 Artyom Tarasenko. - * Copyright 2017,2018 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include -#include "../86box.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../mem.h" -#include "../rom.h" -#include "../pci.h" -#include "../device.h" -#include "../nvr.h" -#include "../timer.h" -#include "../plat.h" -#include "scsi.h" -#include "scsi_device.h" -#include "scsi_ncr53c810.h" - -#define NCR53C810_ROM L"roms/scsi/ncr53c810/NCR307.BIN" - -#define NCR_SCNTL0_TRG 0x01 -#define NCR_SCNTL0_AAP 0x02 -#define NCR_SCNTL0_EPC 0x08 -#define NCR_SCNTL0_WATN 0x10 -#define NCR_SCNTL0_START 0x20 - -#define NCR_SCNTL1_SST 0x01 -#define NCR_SCNTL1_IARB 0x02 -#define NCR_SCNTL1_AESP 0x04 -#define NCR_SCNTL1_RST 0x08 -#define NCR_SCNTL1_CON 0x10 -#define NCR_SCNTL1_DHP 0x20 -#define NCR_SCNTL1_ADB 0x40 -#define NCR_SCNTL1_EXC 0x80 - -#define NCR_SCNTL2_WSR 0x01 -#define NCR_SCNTL2_VUE0 0x02 -#define NCR_SCNTL2_VUE1 0x04 -#define NCR_SCNTL2_WSS 0x08 -#define NCR_SCNTL2_SLPHBEN 0x10 -#define NCR_SCNTL2_SLPMD 0x20 -#define NCR_SCNTL2_CHM 0x40 -#define NCR_SCNTL2_SDU 0x80 - -#define NCR_ISTAT_DIP 0x01 -#define NCR_ISTAT_SIP 0x02 -#define NCR_ISTAT_INTF 0x04 -#define NCR_ISTAT_CON 0x08 -#define NCR_ISTAT_SEM 0x10 -#define NCR_ISTAT_SIGP 0x20 -#define NCR_ISTAT_SRST 0x40 -#define NCR_ISTAT_ABRT 0x80 - -#define NCR_SSTAT0_SDP0 0x01 -#define NCR_SSTAT0_RST 0x02 -#define NCR_SSTAT0_WOA 0x04 -#define NCR_SSTAT0_LOA 0x08 -#define NCR_SSTAT0_AIP 0x10 -#define NCR_SSTAT0_OLF 0x20 -#define NCR_SSTAT0_ORF 0x40 -#define NCR_SSTAT0_ILF 0x80 - -#define NCR_SIST0_PAR 0x01 -#define NCR_SIST0_RST 0x02 -#define NCR_SIST0_UDC 0x04 -#define NCR_SIST0_SGE 0x08 -#define NCR_SIST0_RSL 0x10 -#define NCR_SIST0_SEL 0x20 -#define NCR_SIST0_CMP 0x40 -#define NCR_SIST0_MA 0x80 - -#define NCR_SIST1_HTH 0x01 -#define NCR_SIST1_GEN 0x02 -#define NCR_SIST1_STO 0x04 -#define NCR_SIST1_SBMC 0x10 - -#define NCR_SOCL_IO 0x01 -#define NCR_SOCL_CD 0x02 -#define NCR_SOCL_MSG 0x04 -#define NCR_SOCL_ATN 0x08 -#define NCR_SOCL_SEL 0x10 -#define NCR_SOCL_BSY 0x20 -#define NCR_SOCL_ACK 0x40 -#define NCR_SOCL_REQ 0x80 - -#define NCR_DSTAT_IID 0x01 -#define NCR_DSTAT_SIR 0x04 -#define NCR_DSTAT_SSI 0x08 -#define NCR_DSTAT_ABRT 0x10 -#define NCR_DSTAT_BF 0x20 -#define NCR_DSTAT_MDPE 0x40 -#define NCR_DSTAT_DFE 0x80 - -#define NCR_DCNTL_COM 0x01 -#define NCR_DCNTL_IRQD 0x02 -#define NCR_DCNTL_STD 0x04 -#define NCR_DCNTL_IRQM 0x08 -#define NCR_DCNTL_SSM 0x10 -#define NCR_DCNTL_PFEN 0x20 -#define NCR_DCNTL_PFF 0x40 -#define NCR_DCNTL_CLSE 0x80 - -#define NCR_DMODE_MAN 0x01 -#define NCR_DMODE_BOF 0x02 -#define NCR_DMODE_ERMP 0x04 -#define NCR_DMODE_ERL 0x08 -#define NCR_DMODE_DIOM 0x10 -#define NCR_DMODE_SIOM 0x20 - -#define NCR_CTEST2_DACK 0x01 -#define NCR_CTEST2_DREQ 0x02 -#define NCR_CTEST2_TEOP 0x04 -#define NCR_CTEST2_PCICIE 0x08 -#define NCR_CTEST2_CM 0x10 -#define NCR_CTEST2_CIO 0x20 -#define NCR_CTEST2_SIGP 0x40 -#define NCR_CTEST2_DDIR 0x80 - -#define NCR_CTEST5_BL2 0x04 -#define NCR_CTEST5_DDIR 0x08 -#define NCR_CTEST5_MASR 0x10 -#define NCR_CTEST5_DFSN 0x20 -#define NCR_CTEST5_BBCK 0x40 -#define NCR_CTEST5_ADCK 0x80 - -/* Enable Response to Reselection */ -#define NCR_SCID_RRE 0x60 - -#define PHASE_DO 0 -#define PHASE_DI 1 -#define PHASE_CMD 2 -#define PHASE_ST 3 -#define PHASE_MO 6 -#define PHASE_MI 7 -#define PHASE_MASK 7 - -/* Maximum length of MSG IN data. */ -#define NCR_MAX_MSGIN_LEN 8 - -/* Flag set if this is a tagged command. */ -#define NCR_TAG_VALID (1 << 16) - -#define NCR_BUF_SIZE 4096 - -typedef struct ncr53c810_request { - uint32_t tag; - uint32_t dma_len; - uint8_t *dma_buf; - uint32_t pending; - int out; -} ncr53c810_request; - -typedef enum -{ - SCSI_STATE_SEND_COMMAND, - SCSI_STATE_READ_DATA, - SCSI_STATE_WRITE_DATA, - SCSI_STATE_READ_STATUS, - SCSI_STATE_READ_MESSAGE, - SCSI_STATE_WRITE_MESSAGE -} scsi_state_t; - -typedef struct { - uint8_t pci_slot; - int has_bios; - rom_t bios; - int PCIBase; - int MMIOBase; - mem_mapping_t mmio_mapping; - int RAMBase; - mem_mapping_t ram_mapping; - - int carry; /* ??? Should this be an a visible register somewhere? */ - int status; - /* Action to take at the end of a MSG IN phase. - 0 = COMMAND, 1 = disconnect, 2 = DATA OUT, 3 = DATA IN. */ - int msg_action; - int msg_len; - uint8_t msg[NCR_MAX_MSGIN_LEN]; - /* 0 if SCRIPTS are running or stopped. - * 1 if a Wait Reselect instruction has been issued. - * 2 if processing DMA from ncr53c810_execute_script. - * 3 if a DMA operation is in progress. */ - int waiting; - - uint8_t current_lun; - uint8_t select_id; - int command_complete; - ncr53c810_request *current; - - int irq; - - uint32_t dsa; - uint32_t temp; - uint32_t dnad; - uint32_t dbc; - uint8_t istat; - uint8_t dcmd; - uint8_t dstat; - uint8_t dien; - uint8_t sist0; - uint8_t sist1; - uint8_t sien0; - uint8_t sien1; - uint8_t mbox0; - uint8_t mbox1; - uint8_t dfifo; - uint8_t ctest2; - uint8_t ctest3; - uint8_t ctest4; - uint8_t ctest5; - uint32_t dsp; - uint32_t dsps; - uint8_t dmode; - uint8_t dcntl; - uint8_t scntl0; - uint8_t scntl1; - uint8_t scntl2; - uint8_t scntl3; - uint8_t sstat0; - uint8_t sstat1; - uint8_t scid; - uint8_t sxfer; - uint8_t socl; - uint8_t sdid; - uint8_t ssid; - uint8_t sfbr; - uint8_t stest1; - uint8_t stest2; - uint8_t stest3; - uint8_t sidl; - uint8_t stime0; - uint8_t respid; - uint32_t scratcha; - uint32_t scratchb; - uint8_t sbr; - uint8_t chip_rev; - int last_level; - void *hba_private; - uint8_t gpreg0; - uint32_t buffer_pos; - int32_t temp_buf_len; - uint8_t last_command; - - uint8_t sstop; - - uint8_t regop; - uint32_t adder; - - int64_t timer_period; - int64_t timer_enabled; -} ncr53c810_t; - - -#ifdef ENABLE_NCR53C810_LOG -int ncr53c810_do_log = ENABLE_NCR53C810_LOG; -#endif - - -static void -ncr53c810_log(const char *fmt, ...) -{ -#ifdef ENABLE_NCR53C810_LOG - va_list ap; - - if (ncr53c810_do_log) { - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -static uint8_t ncr53c810_reg_readb(ncr53c810_t *dev, uint32_t offset); -static void ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val); - - -static __inline__ int32_t -sextract32(uint32_t value, int start, int length) -{ - /* Note that this implementation relies on right shift of signed - * integers being an arithmetic shift. - */ - return ((int32_t)(value << (32 - length - start))) >> (32 - length); -} - - -static __inline__ uint32_t -deposit32(uint32_t value, int start, int length, - uint32_t fieldval) -{ - uint32_t mask; - mask = (~0U >> (32 - length)) << start; - return (value & ~mask) | ((fieldval << start) & mask); -} - - -static __inline__ int -ncr53c810_irq_on_rsl(ncr53c810_t *dev) -{ - return (dev->sien0 & NCR_SIST0_RSL) && (dev->scid & NCR_SCID_RRE); -} - - -static void -ncr53c810_soft_reset(ncr53c810_t *dev) -{ - int i; - - ncr53c810_log("LSI Reset\n"); - dev->timer_period = dev->timer_enabled = 0; - - dev->carry = 0; - - dev->msg_action = 0; - dev->msg_len = 0; - dev->waiting = 0; - dev->dsa = 0; - dev->dnad = 0; - dev->dbc = 0; - dev->temp = 0; - dev->scratcha = 0; - dev->scratchb = 0; - dev->istat = 0; - dev->dcmd = 0x40; - dev->dstat = NCR_DSTAT_DFE; - dev->dien = 0; - dev->sist0 = 0; - dev->sist1 = 0; - dev->sien0 = 0; - dev->sien1 = 0; - dev->mbox0 = 0; - dev->mbox1 = 0; - dev->dfifo = 0; - dev->ctest2 = NCR_CTEST2_DACK; - dev->ctest3 = 0; - dev->ctest4 = 0; - dev->ctest5 = 0; - dev->dsp = 0; - dev->dsps = 0; - dev->dmode = 0; - dev->dcntl = 0; - dev->scntl0 = 0xc0; - dev->scntl1 = 0; - dev->scntl2 = 0; - dev->scntl3 = 0; - dev->sstat0 = 0; - dev->sstat1 = 0; - dev->scid = 7; - dev->sxfer = 0; - dev->socl = 0; - dev->sdid = 0; - dev->ssid = 0; - dev->stest1 = 0; - dev->stest2 = 0; - dev->stest3 = 0; - dev->sidl = 0; - dev->stime0 = 0; - dev->respid = 0x80; - dev->sbr = 0; - dev->last_level = 0; - dev->gpreg0 = 0; - dev->sstop = 1; - - for (i = 0; i < 16; i++) - scsi_device_reset(i); -} - - -static void -ncr53c810_read(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) -{ - uint32_t i = 0; - - ncr53c810_log("ncr53c810_read(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); - - if (dev->dmode & NCR_DMODE_SIOM) { - ncr53c810_log("NCR 810: Reading from I/O address %04X\n", (uint16_t) addr); - for (i = 0; i < len; i++) - buf[i] = inb((uint16_t) (addr + i)); - } else { - ncr53c810_log("NCR 810: Reading from memory address %08X\n", addr); - DMAPageRead(addr, buf, len); - } -} - - -static void -ncr53c810_write(ncr53c810_t *dev, uint32_t addr, uint8_t *buf, uint32_t len) -{ - uint32_t i = 0; - - ncr53c810_log("ncr53c810_write(): %08X-%08X, length %i\n", addr, (addr + len - 1), len); - - if (dev->dmode & NCR_DMODE_DIOM) { - ncr53c810_log("NCR 810: Writing to I/O address %04X\n", (uint16_t) addr); - for (i = 0; i < len; i++) - outb((uint16_t) (addr + i), buf[i]); - } else { - ncr53c810_log("NCR 810: Writing to memory address %08X\n", addr); - DMAPageWrite(addr, buf, len); - } -} - - -static __inline__ uint32_t -read_dword(ncr53c810_t *dev, uint32_t addr) -{ - uint32_t buf; - ncr53c810_log("Reading the next DWORD from memory (%08X)...\n", addr); - DMAPageRead(addr, (uint8_t *)&buf, 4); - return buf; -} - - -static -void do_irq(ncr53c810_t *dev, int level) -{ - if (level) { - pci_set_irq(dev->pci_slot, PCI_INTA); - ncr53c810_log("Raising IRQ...\n"); - } else { - pci_clear_irq(dev->pci_slot, PCI_INTA); - ncr53c810_log("Lowering IRQ...\n"); - } -} - - -static void -ncr53c810_update_irq(ncr53c810_t *dev) -{ - int level; - - /* It's unclear whether the DIP/SIP bits should be cleared when the - Interrupt Status Registers are cleared or when istat is read. - We currently do the formwer, which seems to work. */ - level = 0; - if (dev->dstat & 0x7f) { - if ((dev->dstat & dev->dien) & 0x7f) - level = 1; - dev->istat |= NCR_ISTAT_DIP; - } else { - dev->istat &= ~NCR_ISTAT_DIP; - } - - if (dev->sist0 || dev->sist1) { - if ((dev->sist0 & dev->sien0) || (dev->sist1 & dev->sien1)) - level = 1; - dev->istat |= NCR_ISTAT_SIP; - } else { - dev->istat &= ~NCR_ISTAT_SIP; - } - if (dev->istat & NCR_ISTAT_INTF) { - level = 1; - } - - if (level != dev->last_level) { - ncr53c810_log("Update IRQ level %d dstat %02x sist %02x%02x\n", - level, dev->dstat, dev->sist1, dev->sist0); - dev->last_level = level; - do_irq(dev, level); /* Only do something with the IRQ if the new level differs from the previous one. */ - } -} - - -/* Stop SCRIPTS execution and raise a SCSI interrupt. */ -static void -ncr53c810_script_scsi_interrupt(ncr53c810_t *dev, int stat0, int stat1) -{ - uint32_t mask0; - uint32_t mask1; - - ncr53c810_log("SCSI Interrupt 0x%02x%02x prev 0x%02x%02x\n", - stat1, stat0, dev->sist1, dev->sist0); - dev->sist0 |= stat0; - dev->sist1 |= stat1; - /* Stop processor on fatal or unmasked interrupt. As a special hack - we don't stop processing when raising STO. Instead continue - execution and stop at the next insn that accesses the SCSI bus. */ - mask0 = dev->sien0 | ~(NCR_SIST0_CMP | NCR_SIST0_SEL | NCR_SIST0_RSL); - mask1 = dev->sien1 | ~(NCR_SIST1_GEN | NCR_SIST1_HTH); - mask1 &= ~NCR_SIST1_STO; - if ((dev->sist0 & mask0) || (dev->sist1 & mask1)) { - ncr53c810_log("NCR 810: IRQ-mandated stop\n"); - dev->sstop = 1; - dev->timer_period = dev->timer_enabled = 0; - } - ncr53c810_update_irq(dev); -} - - -/* Stop SCRIPTS execution and raise a DMA interrupt. */ -static void -ncr53c810_script_dma_interrupt(ncr53c810_t *dev, int stat) -{ - ncr53c810_log("DMA Interrupt 0x%x prev 0x%x\n", stat, dev->dstat); - dev->dstat |= stat; - ncr53c810_update_irq(dev); - dev->sstop = 1; - dev->timer_period = dev->timer_enabled = 0; -} - - -static __inline__ void -ncr53c810_set_phase(ncr53c810_t *dev, int phase) -{ - dev->sstat1 = (dev->sstat1 & ~PHASE_MASK) | phase; -} - - -static void -ncr53c810_bad_phase(ncr53c810_t *dev, int out, int new_phase) -{ - /* Trigger a phase mismatch. */ - ncr53c810_log("Phase mismatch interrupt\n"); - ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0); - dev->sstop = 1; - dev->timer_period = dev->timer_enabled = 0; - ncr53c810_set_phase(dev, new_phase); -} - - -static void -ncr53c810_disconnect(ncr53c810_t *dev) -{ - dev->scntl1 &= ~NCR_SCNTL1_CON; - dev->sstat1 &= ~PHASE_MASK; - if (dev->dcmd & 0x01) /* Select with ATN */ - dev->sstat1 |= 0x07; -} - - -static void -ncr53c810_bad_selection(ncr53c810_t *dev, uint32_t id) -{ - ncr53c810_log("Selected absent target %d\n", id); - ncr53c810_script_scsi_interrupt(dev, 0, NCR_SIST1_STO); - ncr53c810_disconnect(dev); -} - - -/* Callback to indicate that the SCSI layer has completed a command. */ -static void -ncr53c810_command_complete(void *priv, uint32_t status) -{ - ncr53c810_t *dev = (ncr53c810_t *)priv; - int out; - - out = (dev->sstat1 & PHASE_MASK) == PHASE_DO; - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Command complete status=%d\n", dev->current->tag, dev->current_lun, dev->last_command, (int)status); - dev->status = status; - dev->command_complete = 2; - if (dev->waiting && dev->dbc != 0) { - /* Raise phase mismatch for short transfers. */ - ncr53c810_bad_phase(dev, out, PHASE_ST); - } else - ncr53c810_set_phase(dev, PHASE_ST); - - dev->sstop = 0; -} - - -static void -ncr53c810_do_dma(ncr53c810_t *dev, int out, uint8_t id) -{ - uint32_t addr, tdbc; - int count; - - scsi_device_t *sd; - - sd = &SCSIDevices[id]; - - if ((!scsi_device_present(id))) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Device not present when attempting to do DMA\n", id, dev->current_lun, dev->last_command); - return; - } - - if (!dev->current->dma_len) { - /* Wait until data is available. */ - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA no data available\n", id, dev->current_lun, dev->last_command); - return; - } - - /* Make sure count is never bigger than BufferLength. */ - count = tdbc = dev->dbc; - if (count > dev->temp_buf_len) - count = dev->temp_buf_len; - - addr = dev->dnad; - - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DMA addr=0x%08x len=%d cur_len=%d dev->dbc=%d\n", id, dev->current_lun, dev->last_command, dev->dnad, dev->temp_buf_len, count, tdbc); - dev->dnad += count; - dev->dbc -= count; - - if (out) - ncr53c810_read(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); - else { - if (!dev->buffer_pos) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DI\n", id, dev->current_lun, dev->last_command); - scsi_device_command_phase1(dev->current->tag); - } - ncr53c810_write(dev, addr, sd->CmdBuffer+dev->buffer_pos, count); - } - - dev->temp_buf_len -= count; - dev->buffer_pos += count; - - if (dev->temp_buf_len <= 0) { - if (out) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: SCSI Command Phase 1 on PHASE_DO\n", id, dev->current_lun, dev->last_command); - scsi_device_command_phase1(id); - } - if (sd->CmdBuffer != NULL) { - free(sd->CmdBuffer); - sd->CmdBuffer = NULL; - } - ncr53c810_command_complete(dev, sd->Status); - } else { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Resume SCRIPTS\n", id, dev->current_lun, dev->last_command); - dev->sstop = 0; - } -} - - -/* Queue a byte for a MSG IN phase. */ -static void -ncr53c810_add_msg_byte(ncr53c810_t *dev, uint8_t data) -{ - if (dev->msg_len >= NCR_MAX_MSGIN_LEN) - ncr53c810_log("MSG IN data too long\n"); - else { - ncr53c810_log("MSG IN 0x%02x\n", data); - dev->msg[dev->msg_len++] = data; - } -} - - -static int -ncr53c810_do_command(ncr53c810_t *dev, uint8_t id) -{ - scsi_device_t *sd; - uint8_t buf[12]; - - int64_t p; - - double period; - - memset(buf, 0, 12); - DMAPageRead(dev->dnad, buf, MIN(12, dev->dbc)); - if (dev->dbc > 12) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: CDB length %i too big\n", id, dev->current_lun, buf[0], dev->dbc); - dev->dbc = 12; - } - dev->sfbr = buf[0]; - dev->command_complete = 0; - - sd = &SCSIDevices[id]; - if (!scsi_device_present(id)) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: Bad Selection\n", id, dev->current_lun, buf[0]); - ncr53c810_bad_selection(dev, id); - return 0; - } - - dev->current = (ncr53c810_request*)malloc(sizeof(ncr53c810_request)); - dev->current->tag = id; - - sd->BufferLength = -1; - - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: DBC=%i\n", id, dev->current_lun, buf[0], dev->dbc); - dev->last_command = buf[0]; - - scsi_device_command_phase0(dev->current->tag, buf); - dev->hba_private = (void *)dev->current; - - dev->waiting = 0; - dev->buffer_pos = 0; - - dev->temp_buf_len = sd->BufferLength; - - if (sd->BufferLength > 0) { - sd->CmdBuffer = (uint8_t *)malloc(sd->BufferLength); - dev->current->dma_len = sd->BufferLength; - } - - if ((sd->Phase == SCSI_PHASE_DATA_IN) && (sd->BufferLength > 0)) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DI\n", id, dev->current_lun, buf[0]); - ncr53c810_set_phase(dev, PHASE_DI); - p = scsi_device_get_callback(dev->current->tag); - if (p <= 0LL) { - period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ - dev->timer_period += (int64_t) period; - } else - dev->timer_period += p; - return 1; - } else if ((sd->Phase == SCSI_PHASE_DATA_OUT) && (sd->BufferLength > 0)) { - ncr53c810_log("(ID=%02i LUN=%02i) SCSI Command 0x%02x: PHASE_DO\n", id, buf[0]); - ncr53c810_set_phase(dev, PHASE_DO); - p = scsi_device_get_callback(dev->current->tag); - if (p <= 0LL) { - period = ((double) sd->BufferLength) * 0.1 * ((double) TIMER_USEC); /* Fast SCSI: 10000000 bytes per second */ - dev->timer_period += (int64_t) period; - } else - dev->timer_period += p; - return 1; - } else { - ncr53c810_command_complete(dev, sd->Status); - return 0; - } -} - - -static void -ncr53c810_do_status(ncr53c810_t *dev) -{ - uint8_t status; - ncr53c810_log("Get status len=%d status=%d\n", dev->dbc, dev->status); - if (dev->dbc != 1) - ncr53c810_log("Bad Status move\n"); - dev->dbc = 1; - status = dev->status; - dev->sfbr = status; - ncr53c810_write(dev, dev->dnad, &status, 1); - ncr53c810_set_phase(dev, PHASE_MI); - dev->msg_action = 1; - ncr53c810_add_msg_byte(dev, 0); /* COMMAND COMPLETE */ -} - - -static void -ncr53c810_do_msgin(ncr53c810_t *dev) -{ - uint32_t len; - ncr53c810_log("Message in len=%d/%d\n", dev->dbc, dev->msg_len); - dev->sfbr = dev->msg[0]; - len = dev->msg_len; - if (len > dev->dbc) - len = dev->dbc; - ncr53c810_write(dev, dev->dnad, dev->msg, len); - /* Linux drivers rely on the last byte being in the SIDL. */ - dev->sidl = dev->msg[len - 1]; - dev->msg_len -= len; - if (dev->msg_len) - memmove(dev->msg, dev->msg + len, dev->msg_len); - else { - /* ??? Check if ATN (not yet implemented) is asserted and maybe - switch to PHASE_MO. */ - switch (dev->msg_action) { - case 0: - ncr53c810_set_phase(dev, PHASE_CMD); - break; - case 1: - ncr53c810_disconnect(dev); - break; - case 2: - ncr53c810_set_phase(dev, PHASE_DO); - break; - case 3: - ncr53c810_set_phase(dev, PHASE_DI); - break; - default: - abort(); - } - } -} - - -/* Read the next byte during a MSGOUT phase. */ -static uint8_t -ncr53c810_get_msgbyte(ncr53c810_t *dev) -{ - uint8_t data; - DMAPageRead(dev->dnad, &data, 1); - dev->dnad++; - dev->dbc--; - return data; -} - - -/* Skip the next n bytes during a MSGOUT phase. */ -static void -ncr53c810_skip_msgbytes(ncr53c810_t *dev, unsigned int n) -{ - dev->dnad += n; - dev->dbc -= n; -} - - -static void -ncr53c810_bad_message(ncr53c810_t *dev, uint8_t msg) -{ - ncr53c810_log("Unimplemented message 0x%02x\n", msg); - ncr53c810_set_phase(dev, PHASE_MI); - ncr53c810_add_msg_byte(dev, 7); /* MESSAGE REJECT */ - dev->msg_action = 0; -} - - -static void -ncr53c810_do_msgout(ncr53c810_t *dev, uint8_t id) -{ - uint8_t msg; - int len; - uint32_t current_tag; - scsi_device_t *sd; - - sd = &SCSIDevices[id]; - - current_tag = id; - - ncr53c810_log("MSG out len=%d\n", dev->dbc); - while (dev->dbc) { - msg = ncr53c810_get_msgbyte(dev); - dev->sfbr = msg; - - switch (msg) { - case 0x04: - ncr53c810_log("MSG: Disconnect\n"); - ncr53c810_disconnect(dev); - break; - case 0x08: - ncr53c810_log("MSG: No Operation\n"); - ncr53c810_set_phase(dev, PHASE_CMD); - break; - case 0x01: - len = ncr53c810_get_msgbyte(dev); - msg = ncr53c810_get_msgbyte(dev); - (void) len; /* avoid a warning about unused variable*/ - ncr53c810_log("Extended message 0x%x (len %d)\n", msg, len); - switch (msg) { - case 1: - ncr53c810_log("SDTR (ignored)\n"); - ncr53c810_skip_msgbytes(dev, 2); - break; - case 3: - ncr53c810_log("WDTR (ignored)\n"); - ncr53c810_skip_msgbytes(dev, 1); - break; - default: - ncr53c810_bad_message(dev, msg); - return; - } - break; - case 0x20: /* SIMPLE queue */ - id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; - ncr53c810_log("SIMPLE queue tag=0x%x\n", id & 0xff); - break; - case 0x21: /* HEAD of queue */ - ncr53c810_log("HEAD queue not implemented\n"); - id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; - break; - case 0x22: /* ORDERED queue */ - ncr53c810_log("ORDERED queue not implemented\n"); - id |= ncr53c810_get_msgbyte(dev) | NCR_TAG_VALID; - break; - case 0x0d: - /* The ABORT TAG message clears the current I/O process only. */ - ncr53c810_log("MSG: ABORT TAG tag=0x%x\n", current_tag); - if (sd->CmdBuffer) { - free(sd->CmdBuffer); - sd->CmdBuffer = NULL; - } - ncr53c810_disconnect(dev); - break; - case 0x06: - case 0x0e: - case 0x0c: - /* The ABORT message clears all I/O processes for the selecting - initiator on the specified logical unit of the target. */ - if (msg == 0x06) - ncr53c810_log("MSG: ABORT tag=0x%x\n", current_tag); - /* The CLEAR QUEUE message clears all I/O processes for all - initiators on the specified logical unit of the target. */ - if (msg == 0x0e) - ncr53c810_log("MSG: CLEAR QUEUE tag=0x%x\n", current_tag); - /* The BUS DEVICE RESET message clears all I/O processes for all - initiators on all logical units of the target. */ - if (msg == 0x0c) - ncr53c810_log("MSG: BUS DEVICE RESET tag=0x%x\n", current_tag); - - /* clear the current I/O process */ - if (sd->CmdBuffer) { - free(sd->CmdBuffer); - sd->CmdBuffer = NULL; - } - ncr53c810_disconnect(dev); - break; - default: - if ((msg & 0x80) == 0) { - ncr53c810_bad_message(dev, msg); - return; - } else { - dev->current_lun = msg & 7; - ncr53c810_log("Select LUN %d\n", dev->current_lun); - ncr53c810_set_phase(dev, PHASE_CMD); - } - break; - } - } -} - - -static void -ncr53c810_memcpy(ncr53c810_t *dev, uint32_t dest, uint32_t src, int count) -{ - int n; - uint8_t buf[NCR_BUF_SIZE]; - - ncr53c810_log("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); - while (count) { - n = (count > NCR_BUF_SIZE) ? NCR_BUF_SIZE : count; - ncr53c810_read(dev, src, buf, n); - ncr53c810_write(dev, dest, buf, n); - src += n; - dest += n; - count -= n; - } -} - - -static void -ncr53c810_process_script(ncr53c810_t *dev) -{ - uint32_t insn, addr, id, buf[2], dest; - int opcode, insn_processed = 0, reg, operator, cond, jmp, n, i, c; - int32_t offset; - uint8_t op0, op1, data8, mask, data[7], *pp; - - dev->sstop = 0; -again: - insn_processed++; - insn = read_dword(dev, dev->dsp); - if (!insn) { - /* If we receive an empty opcode increment the DSP by 4 bytes - instead of 8 and execute the next opcode at that location */ - dev->dsp += 4; - dev->timer_period += (10LL * TIMER_USEC); - if (insn_processed < 100) - goto again; - else - return; - } - addr = read_dword(dev, dev->dsp + 4); - ncr53c810_log("SCRIPTS dsp=%08x opcode %08x arg %08x\n", dev->dsp, insn, addr); - dev->dsps = addr; - dev->dcmd = insn >> 24; - dev->dsp += 8; - - switch (insn >> 30) { - case 0: /* Block move. */ - ncr53c810_log("00: Block move\n"); - if (dev->sist1 & NCR_SIST1_STO) { - ncr53c810_log("Delayed select timeout\n"); - dev->sstop = 1; - break; - } - ncr53c810_log("Block Move DBC=%d\n", dev->dbc); - dev->dbc = insn & 0xffffff; - ncr53c810_log("Block Move DBC=%d now\n", dev->dbc); - /* ??? Set ESA. */ - if (insn & (1 << 29)) { - /* Indirect addressing. */ - /* Should this respect SIOM? */ - addr = read_dword(dev, addr); - ncr53c810_log("Indirect Block Move address: %08X\n", addr); - } else if (insn & (1 << 28)) { - /* Table indirect addressing. */ - - /* 32-bit Table indirect */ - offset = sextract32(addr, 0, 24); - DMAPageRead(dev->dsa + offset, (uint8_t *)buf, 8); - /* byte count is stored in bits 0:23 only */ - dev->dbc = buf[0] & 0xffffff; - addr = buf[1]; - - /* 40-bit DMA, upper addr bits [39:32] stored in first DWORD of - * table, bits [31:24] */ - } - if ((dev->sstat1 & PHASE_MASK) != ((insn >> 24) & 7)) { - ncr53c810_log("Wrong phase got %d expected %d\n", - dev->sstat1 & PHASE_MASK, (insn >> 24) & 7); - ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_MA, 0); - break; - } - dev->dnad = addr; - switch (dev->sstat1 & 0x7) { - case PHASE_DO: - ncr53c810_log("Data Out Phase\n"); - dev->waiting = 0; - ncr53c810_do_dma(dev, 1, dev->sdid); - break; - case PHASE_DI: - ncr53c810_log("Data In Phase\n"); - dev->waiting = 0; - ncr53c810_do_dma(dev, 0, dev->sdid); - break; - case PHASE_CMD: - ncr53c810_log("Command Phase\n"); - c = ncr53c810_do_command(dev, dev->sdid); - - if (!c || dev->sstop || dev->waiting || ((dev->sstat1 & 0x7) == PHASE_ST)) - break; - - dev->dfifo = dev->dbc & 0xff; - dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); - - dev->timer_period += (40LL * TIMER_USEC); - - if (dev->dcntl & NCR_DCNTL_SSM) - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SSI); - return; - case PHASE_ST: - ncr53c810_log("Status Phase\n"); - ncr53c810_do_status(dev); - break; - case PHASE_MO: - ncr53c810_log("MSG Out Phase\n"); - ncr53c810_do_msgout(dev, dev->sdid); - break; - case PHASE_MI: - ncr53c810_log("MSG In Phase\n"); - ncr53c810_do_msgin(dev); - break; - default: - ncr53c810_log("Unimplemented phase %d\n", dev->sstat1 & PHASE_MASK); - } - dev->dfifo = dev->dbc & 0xff; - dev->ctest5 = (dev->ctest5 & 0xfc) | ((dev->dbc >> 8) & 3); - break; - - case 1: /* IO or Read/Write instruction. */ - ncr53c810_log("01: I/O or Read/Write instruction\n"); - opcode = (insn >> 27) & 7; - if (opcode < 5) { - if (insn & (1 << 25)) - id = read_dword(dev, dev->dsa + sextract32(insn, 0, 24)); - else - id = insn; - id = (id >> 16) & 0xf; - if (insn & (1 << 26)) - addr = dev->dsp + sextract32(addr, 0, 24); - dev->dnad = addr; - switch (opcode) { - case 0: /* Select */ - dev->sdid = id; - if (dev->scntl1 & NCR_SCNTL1_CON) { - ncr53c810_log("Already reselected, jumping to alternative address\n"); - dev->dsp = dev->dnad; - break; - } - dev->sstat0 |= NCR_SSTAT0_WOA; - dev->scntl1 &= ~NCR_SCNTL1_IARB; - if (!scsi_device_present(id)) { - ncr53c810_bad_selection(dev, id); - break; - } - ncr53c810_log("Selected target %d%s\n", - id, insn & (1 << 24) ? " ATN" : ""); - dev->select_id = id << 8; - dev->scntl1 |= NCR_SCNTL1_CON; - if (insn & (1 << 24)) - dev->socl |= NCR_SOCL_ATN; - ncr53c810_set_phase(dev, PHASE_MO); - dev->waiting = 0; - break; - case 1: /* Disconnect */ - ncr53c810_log("Wait Disconnect\n"); - dev->scntl1 &= ~NCR_SCNTL1_CON; - break; - case 2: /* Wait Reselect */ - ncr53c810_log("Wait Reselect\n"); - if (dev->istat & NCR_ISTAT_SIGP) - dev->dsp = dev->dnad; /* If SIGP is set, this command causes an immediate jump to DNAD. */ - else { - if (!ncr53c810_irq_on_rsl(dev)) - dev->waiting = 1; - } - break; - case 3: /* Set */ - ncr53c810_log("Set%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", - insn & (1 << 6) ? " ACK" : "", - insn & (1 << 9) ? " TM" : "", - insn & (1 << 10) ? " CC" : ""); - if (insn & (1 << 3)) { - dev->socl |= NCR_SOCL_ATN; - ncr53c810_set_phase(dev, PHASE_MO); - } - if (insn & (1 << 9)) - ncr53c810_log("Target mode not implemented\n"); - if (insn & (1 << 10)) - dev->carry = 1; - break; - case 4: /* Clear */ - ncr53c810_log("Clear%s%s%s%s\n", insn & (1 << 3) ? " ATN" : "", - insn & (1 << 6) ? " ACK" : "", - insn & (1 << 9) ? " TM" : "", - insn & (1 << 10) ? " CC" : ""); - if (insn & (1 << 3)) - dev->socl &= ~NCR_SOCL_ATN; - if (insn & (1 << 10)) - dev->carry = 0; - break; - } - } else { - reg = ((insn >> 16) & 0x7f) | (insn & 0x80); - data8 = (insn >> 8) & 0xff; - opcode = (insn >> 27) & 7; - operator = (insn >> 24) & 7; - op0 = op1 = 0; - switch (opcode) { - case 5: /* From SFBR */ - op0 = dev->sfbr; - op1 = data8; - break; - case 6: /* To SFBR */ - if (operator) - op0 = ncr53c810_reg_readb(dev, reg); - op1 = data8; - break; - case 7: /* Read-modify-write */ - if (operator) - op0 = ncr53c810_reg_readb(dev, reg); - if (insn & (1 << 23)) - op1 = dev->sfbr; - else - op1 = data8; - break; - } - - switch (operator) { - case 0: /* move */ - op0 = op1; - break; - case 1: /* Shift left */ - op1 = op0 >> 7; - op0 = (op0 << 1) | dev->carry; - dev->carry = op1; - break; - case 2: /* OR */ - op0 |= op1; - break; - case 3: /* XOR */ - op0 ^= op1; - break; - case 4: /* AND */ - op0 &= op1; - break; - case 5: /* SHR */ - op1 = op0 & 1; - op0 = (op0 >> 1) | (dev->carry << 7); - dev->carry = op1; - break; - case 6: /* ADD */ - op0 += op1; - dev->carry = op0 < op1; - break; - case 7: /* ADC */ - op0 += op1 + dev->carry; - if (dev->carry) - dev->carry = op0 <= op1; - else - dev->carry = op0 < op1; - break; - } - - switch (opcode) { - case 5: /* From SFBR */ - case 7: /* Read-modify-write */ - ncr53c810_reg_writeb(dev, reg, op0); - break; - case 6: /* To SFBR */ - dev->sfbr = op0; - break; - } - } - break; - - case 2: /* Transfer Control. */ - ncr53c810_log("02: Transfer Control\n"); - if ((insn & 0x002e0000) == 0) { - ncr53c810_log("NOP\n"); - break; - } - if (dev->sist1 & NCR_SIST1_STO) { - ncr53c810_log("Delayed select timeout\n"); - dev->sstop = 1; - break; - } - cond = jmp = (insn & (1 << 19)) != 0; - if (cond == jmp && (insn & (1 << 21))) { - ncr53c810_log("Compare carry %d\n", dev->carry == jmp); - cond = dev->carry != 0; - } - if (cond == jmp && (insn & (1 << 17))) { - ncr53c810_log("Compare phase %d %c= %d\n", (dev->sstat1 & PHASE_MASK), - jmp ? '=' : '!', ((insn >> 24) & 7)); - cond = (dev->sstat1 & PHASE_MASK) == ((insn >> 24) & 7); - } - if (cond == jmp && (insn & (1 << 18))) { - mask = (~insn >> 8) & 0xff; - ncr53c810_log("Compare data 0x%x & 0x%x %c= 0x%x\n", dev->sfbr, mask, - jmp ? '=' : '!', insn & mask); - cond = (dev->sfbr & mask) == (insn & mask); - } - if (cond == jmp) { - if (insn & (1 << 23)) { - /* Relative address. */ - addr = dev->dsp + sextract32(addr, 0, 24); - } - switch ((insn >> 27) & 7) { - case 0: /* Jump */ - ncr53c810_log("Jump to 0x%08x\n", addr); - dev->adder = addr; - dev->dsp = addr; - break; - case 1: /* Call */ - ncr53c810_log("Call 0x%08x\n", addr); - dev->temp = dev->dsp; - dev->dsp = addr; - break; - case 2: /* Return */ - ncr53c810_log("Return to 0x%08x\n", dev->temp); - dev->dsp = dev->temp; - break; - case 3: /* Interrupt */ - ncr53c810_log("Interrupt 0x%08x\n", dev->dsps); - if ((insn & (1 << 20)) != 0) { - dev->istat |= NCR_ISTAT_INTF; - ncr53c810_update_irq(dev); - } else - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SIR); - break; - default: - ncr53c810_log("Illegal transfer control\n"); - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_IID); - break; - } - } else - ncr53c810_log("Control condition failed\n"); - break; - - case 3: - ncr53c810_log("00: Memory move\n"); - if ((insn & (1 << 29)) == 0) { - /* Memory move. */ - /* ??? The docs imply the destination address is loaded into - the TEMP register. However the Linux drivers rely on - the value being presrved. */ - dest = read_dword(dev, dev->dsp); - dev->dsp += 4; - ncr53c810_memcpy(dev, dest, addr, insn & 0xffffff); - } else { - pp = data; - - if (insn & (1 << 28)) - addr = dev->dsa + sextract32(addr, 0, 24); - n = (insn & 7); - reg = (insn >> 16) & 0xff; - if (insn & (1 << 24)) { - DMAPageRead(addr, data, n); - ncr53c810_log("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n, addr, - *(unsigned *)pp); - for (i = 0; i < n; i++) - ncr53c810_reg_writeb(dev, reg + i, data[i]); - } else { - ncr53c810_log("Store reg 0x%x size %d addr 0x%08x\n", reg, n, addr); - for (i = 0; i < n; i++) - data[i] = ncr53c810_reg_readb(dev, reg + i); - DMAPageWrite(addr, data, n); - } - } - break; - - default: - ncr53c810_log("%02X: Unknown command\n", (uint8_t) (insn >> 30)); - } - - dev->timer_period += (40LL * TIMER_USEC); - - ncr53c810_log("instructions processed %i\n", insn_processed); - if (insn_processed > 10000 && !dev->waiting) { - /* Some windows drivers make the device spin waiting for a memory - location to change. If we have been executed a lot of code then - assume this is the case and force an unexpected device disconnect. - This is apparently sufficient to beat the drivers into submission. - */ - ncr53c810_log("Some windows drivers make the device spin...\n"); - if (!(dev->sien0 & NCR_SIST0_UDC)) - ncr53c810_log("inf. loop with UDC masked\n"); - ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_UDC, 0); - ncr53c810_disconnect(dev); - } else if (!dev->sstop && !dev->waiting) { - if (dev->dcntl & NCR_DCNTL_SSM) { - ncr53c810_log("NCR 810: SCRIPTS: Single-step mode\n"); - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_SSI); - } else { - ncr53c810_log("NCR 810: SCRIPTS: Normal mode\n"); - if (insn_processed < 100) - goto again; - } - } else { - if (dev->sstop) - ncr53c810_log("NCR 810: SCRIPTS: Stopped\n"); - if (dev->waiting) - ncr53c810_log("NCR 810: SCRIPTS: Waiting\n"); - } - - ncr53c810_log("SCRIPTS execution stopped\n"); -} - - -static void -ncr53c810_execute_script(ncr53c810_t *dev) -{ - dev->sstop = 0; - dev->timer_period = 40LL * TIMER_USEC; - dev->timer_enabled = 1; -} - - -static void -ncr53c810_callback(void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *) p; - - dev->timer_period = 0; - if (!dev->sstop) { - if (dev->waiting) - dev->timer_period = 40LL * TIMER_USEC; - else - ncr53c810_process_script(dev); - } - - if (dev->sstop) { - dev->timer_enabled = 0; - dev->timer_period = 0; - } else - dev->timer_enabled = 1; -} - - -static void -ncr53c810_reg_writeb(ncr53c810_t *dev, uint32_t offset, uint8_t val) -{ - uint8_t tmp = 0; - -#define CASE_SET_REG24(name, addr) \ - case addr : dev->name &= 0xffffff00; dev->name |= val; break; \ - case addr + 1: dev->name &= 0xffff00ff; dev->name |= val << 8; break; \ - case addr + 2: dev->name &= 0xff00ffff; dev->name |= val << 16; break; - -#define CASE_SET_REG32(name, addr) \ - case addr : dev->name &= 0xffffff00; dev->name |= val; break; \ - case addr + 1: dev->name &= 0xffff00ff; dev->name |= val << 8; break; \ - case addr + 2: dev->name &= 0xff00ffff; dev->name |= val << 16; break; \ - case addr + 3: dev->name &= 0x00ffffff; dev->name |= val << 24; break; - -#ifdef DEBUG_NCR_REG - ncr53c810_log("Write reg %02x = %02x\n", offset, val); -#endif - - dev->regop = 1; - - switch (offset) { - case 0x00: /* SCNTL0 */ - dev->scntl0 = val; - if (val & NCR_SCNTL0_START) { - /* Looks like this (turn on bit 4 of SSTAT0 to mark arbitration in progress) - is enough to make BIOS v4.x happy. */ - ncr53c810_log("NCR 810: Selecting SCSI ID %i\n", dev->sdid); - dev->select_id = dev->sdid; - dev->sstat0 |= 0x10; - } - break; - case 0x01: /* SCNTL1 */ - dev->scntl1 = val & ~NCR_SCNTL1_SST; - if (val & NCR_SCNTL1_IARB) { - dev->select_id = dev->sdid; - ncr53c810_log("Arbitration lost\n"); - dev->sstat0 |= 0x08; - dev->waiting = 0; - } - if (val & NCR_SCNTL1_RST) { - if (!(dev->sstat0 & NCR_SSTAT0_RST)) { - dev->sstat0 |= NCR_SSTAT0_RST; - ncr53c810_script_scsi_interrupt(dev, NCR_SIST0_RST, 0); - } - } else - dev->sstat0 &= ~NCR_SSTAT0_RST; - break; - case 0x02: /* SCNTL2 */ - val &= ~(NCR_SCNTL2_WSR | NCR_SCNTL2_WSS); - dev->scntl2 = val; - break; - case 0x03: /* SCNTL3 */ - dev->scntl3 = val; - break; - case 0x04: /* SCID */ - dev->scid = val; - break; - case 0x05: /* SXFER */ - dev->sxfer = val; - break; - case 0x06: /* SDID */ - if ((dev->ssid & 0x80) && (val & 0xf) != (dev->ssid & 0xf)) - ncr53c810_log("Destination ID does not match SSID\n"); - dev->sdid = val & 0xf; - break; - case 0x07: /* GPREG0 */ - ncr53c810_log("NCR 810: GPREG0 write %02X\n", val); - dev->gpreg0 = val & 0x03; - break; - case 0x08: /* SFBR */ - /* The CPU is not allowed to write to this register. However the - SCRIPTS register move instructions are. */ - dev->sfbr = val; - break; - case 0x09: /* SOCL */ - ncr53c810_log("NCR 810: SOCL write %02X\n", val); - dev->socl = val; - break; - case 0x0a: case 0x0b: - /* Openserver writes to these readonly registers on startup */ - return; - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - /* Linux writes to these readonly registers on startup. */ - return; - CASE_SET_REG32(dsa, 0x10) - case 0x14: /* ISTAT */ - ncr53c810_log("ISTAT write: %02X\n", val); - tmp = dev->istat; - dev->istat = (dev->istat & 0x0f) | (val & 0xf0); - if ((val & NCR_ISTAT_ABRT) && !(val & NCR_ISTAT_SRST)) - ncr53c810_script_dma_interrupt(dev, NCR_DSTAT_ABRT); - if (val & NCR_ISTAT_INTF) { - dev->istat &= ~NCR_ISTAT_INTF; - ncr53c810_update_irq(dev); - } - - if ((dev->waiting == 1) && (val & NCR_ISTAT_SIGP)) { - ncr53c810_log("Woken by SIGP\n"); - dev->waiting = 0; - dev->dsp = dev->dnad; - /* ncr53c810_execute_script(dev); */ - } - if ((val & NCR_ISTAT_SRST) && !(tmp & NCR_ISTAT_SRST)) { - ncr53c810_soft_reset(dev); - ncr53c810_update_irq(dev); - dev->istat = 0; - } - break; - case 0x16: /* MBOX0 */ - dev->mbox0 = val; - break; - case 0x17: /* MBOX1 */ - dev->mbox1 = val; - break; - case 0x18: /* CTEST0 */ - /* nothing to do */ - break; - case 0x19: /* CTEST1 */ - /* nothing to do */ - break; - case 0x1a: /* CTEST2 */ - dev->ctest2 = val & NCR_CTEST2_PCICIE; - break; - case 0x1b: /* CTEST3 */ - dev->ctest3 = val & 0x0f; - break; - CASE_SET_REG32(temp, 0x1c) - case 0x21: /* CTEST4 */ - if (val & 7) - ncr53c810_log("Unimplemented CTEST4-FBL 0x%x\n", val); - dev->ctest4 = val; - break; - case 0x22: /* CTEST5 */ - if (val & (NCR_CTEST5_ADCK | NCR_CTEST5_BBCK)) - ncr53c810_log("CTEST5 DMA increment not implemented\n"); - dev->ctest5 = val; - break; - CASE_SET_REG24(dbc, 0x24) - CASE_SET_REG32(dnad, 0x28) - case 0x2c: /* DSP[0:7] */ - dev->dsp &= 0xffffff00; - dev->dsp |= val; - break; - case 0x2d: /* DSP[8:15] */ - dev->dsp &= 0xffff00ff; - dev->dsp |= val << 8; - break; - case 0x2e: /* DSP[16:23] */ - dev->dsp &= 0xff00ffff; - dev->dsp |= val << 16; - break; - case 0x2f: /* DSP[24:31] */ - dev->dsp &= 0x00ffffff; - dev->dsp |= val << 24; - if (!(dev->dmode & NCR_DMODE_MAN) && dev->sstop) - ncr53c810_execute_script(dev); - break; - CASE_SET_REG32(dsps, 0x30) - CASE_SET_REG32(scratcha, 0x34) - case 0x38: /* DMODE */ - dev->dmode = val; - break; - case 0x39: /* DIEN */ - ncr53c810_log("DIEN write: %02X\n", val); - dev->dien = val; - ncr53c810_update_irq(dev); - break; - case 0x3a: /* SBR */ - dev->sbr = val; - break; - case 0x3b: /* DCNTL */ - dev->dcntl = val & ~(NCR_DCNTL_PFF | NCR_DCNTL_STD); - if ((val & NCR_DCNTL_STD) && dev->sstop) - ncr53c810_execute_script(dev); - break; - case 0x40: /* SIEN0 */ - dev->sien0 = val; - ncr53c810_update_irq(dev); - break; - case 0x41: /* SIEN1 */ - dev->sien1 = val; - ncr53c810_update_irq(dev); - break; - case 0x47: /* GPCNTL0 */ - break; - case 0x48: /* STIME0 */ - dev->stime0 = val; - break; - case 0x49: /* STIME1 */ - if (val & 0xf) { - ncr53c810_log("General purpose timer not implemented\n"); - /* ??? Raising the interrupt immediately seems to be sufficient - to keep the FreeBSD driver happy. */ - ncr53c810_script_scsi_interrupt(dev, 0, NCR_SIST1_GEN); - } - break; - case 0x4a: /* RESPID */ - dev->respid = val; - break; - case 0x4d: /* STEST1 */ - dev->stest1 = val; - break; - case 0x4e: /* STEST2 */ - if (val & 1) - ncr53c810_log("Low level mode not implemented\n"); - dev->stest2 = val; - break; - case 0x4f: /* STEST3 */ - if (val & 0x41) - ncr53c810_log("SCSI FIFO test mode not implemented\n"); - dev->stest3 = val; - break; - case 0x54: - break; - CASE_SET_REG32(scratchb, 0x5c) - default: - ncr53c810_log("Unhandled writeb 0x%x = 0x%x\n", offset, val); - } -#undef CASE_SET_REG24 -#undef CASE_SET_REG32 -} - - -static uint8_t -ncr53c810_reg_readb(ncr53c810_t *dev, uint32_t offset) -{ - uint8_t tmp; -#define CASE_GET_REG24(name, addr) \ - case addr: return dev->name & 0xff; \ - case addr + 1: return (dev->name >> 8) & 0xff; \ - case addr + 2: return (dev->name >> 16) & 0xff; - -#define CASE_GET_REG32(name, addr) \ - case addr: return dev->name & 0xff; \ - case addr + 1: return (dev->name >> 8) & 0xff; \ - case addr + 2: return (dev->name >> 16) & 0xff; \ - case addr + 3: return (dev->name >> 24) & 0xff; - - dev->regop = 1; - - switch (offset) { - case 0x00: /* SCNTL0 */ - ncr53c810_log("NCR 810: Read SCNTL0 %02X\n", dev->scntl0); - return dev->scntl0; - case 0x01: /* SCNTL1 */ - ncr53c810_log("NCR 810: Read SCNTL1 %02X\n", dev->scntl1); - return dev->scntl1; - case 0x02: /* SCNTL2 */ - ncr53c810_log("NCR 810: Read SCNTL2 %02X\n", dev->scntl2); - return dev->scntl2; - case 0x03: /* SCNTL3 */ - ncr53c810_log("NCR 810: Read SCNTL3 %02X\n", dev->scntl3); - return dev->scntl3; - case 0x04: /* SCID */ - ncr53c810_log("NCR 810: Read SCID %02X\n", dev->scid); - return dev->scid; - case 0x05: /* SXFER */ - ncr53c810_log("NCR 810: Read SXFER %02X\n", dev->sxfer); - return dev->sxfer; - case 0x06: /* SDID */ - ncr53c810_log("NCR 810: Read SDID %02X\n", dev->sdid); - return dev->sdid; - case 0x07: /* GPREG0 */ - ncr53c810_log("NCR 810: Read GPREG0 %02X\n", dev->gpreg0 & 3); - return dev->gpreg0 & 3; - case 0x08: /* Revision ID */ - ncr53c810_log("NCR 810: Read REVID 00\n"); - return 0x00; - case 0xa: /* SSID */ - ncr53c810_log("NCR 810: Read SSID %02X\n", dev->ssid); - return dev->ssid; - case 0xb: /* SBCL */ - /* Bit 7 = REQ (SREQ/ status) - Bit 6 = ACK (SACK/ status) - Bit 5 = BSY (SBSY/ status) - Bit 4 = SEL (SSEL/ status) - Bit 3 = ATN (SATN/ status) - Bit 2 = MSG (SMSG/ status) - Bit 1 = C/D (SC_D/ status) - Bit 0 = I/O (SI_O/ status) */ - tmp = (dev->sstat1 & 7); - ncr53c810_log("NCR 810: Read SBCL %02X\n", tmp); - return tmp; /* For now, return the MSG, C/D, and I/O bits from SSTAT1. */ - case 0xc: /* DSTAT */ - tmp = dev->dstat | NCR_DSTAT_DFE; - if ((dev->istat & NCR_ISTAT_INTF) == 0) - dev->dstat = 0; - ncr53c810_update_irq(dev); - ncr53c810_log("NCR 810: Read DSTAT %02X\n", tmp); - return tmp; - case 0x0d: /* SSTAT0 */ - ncr53c810_log("NCR 810: Read SSTAT0 %02X\n", dev->sstat0); - return dev->sstat0; - case 0x0e: /* SSTAT1 */ - ncr53c810_log("NCR 810: Read SSTAT1 %02X\n", dev->sstat1); - return dev->sstat1; - case 0x0f: /* SSTAT2 */ - ncr53c810_log("NCR 810: Read SSTAT2 %02X\n", dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2); - return dev->scntl1 & NCR_SCNTL1_CON ? 0 : 2; - CASE_GET_REG32(dsa, 0x10) - case 0x14: /* ISTAT */ - ncr53c810_log("NCR 810: Read ISTAT %02X\n", dev->istat); - tmp = dev->istat; - return tmp; - case 0x16: /* MBOX0 */ - ncr53c810_log("NCR 810: Read MBOX0 %02X\n", dev->mbox0); - return dev->mbox0; - case 0x17: /* MBOX1 */ - ncr53c810_log("NCR 810: Read MBOX1 %02X\n", dev->mbox1); - return dev->mbox1; - case 0x18: /* CTEST0 */ - ncr53c810_log("NCR 810: Read CTEST0 FF\n"); - return 0xff; - case 0x19: /* CTEST1 */ - ncr53c810_log("NCR 810: Read CTEST1 F0\n"); - return 0xf0; /* dma fifo empty */ - case 0x1a: /* CTEST2 */ - tmp = dev->ctest2 | NCR_CTEST2_DACK | NCR_CTEST2_CM; - if (dev->istat & NCR_ISTAT_SIGP) { - dev->istat &= ~NCR_ISTAT_SIGP; - tmp |= NCR_CTEST2_SIGP; - } - ncr53c810_log("NCR 810: Read CTEST2 %02X\n", tmp); - return tmp; - case 0x1b: /* CTEST3 */ - ncr53c810_log("NCR 810: Read CTEST3 %02X\n", - (dev->ctest3 & (0x08 | 0x02 | 0x01)) | dev->chip_rev); - return (dev->ctest3 & (0x08 | 0x02 | 0x01)) | dev->chip_rev; - CASE_GET_REG32(temp, 0x1c) - case 0x20: /* DFIFO */ - ncr53c810_log("NCR 810: Read DFIFO 00\n"); - return 0; - case 0x21: /* CTEST4 */ - ncr53c810_log("NCR 810: Read CTEST4 %02X\n", dev->ctest4); - return dev->ctest4; - case 0x22: /* CTEST5 */ - ncr53c810_log("NCR 810: Read CTEST5 %02X\n", dev->ctest5); - return dev->ctest5; - case 0x23: /* CTEST6 */ - ncr53c810_log("NCR 810: Read CTEST6 00\n"); - return 0; - CASE_GET_REG24(dbc, 0x24) - case 0x27: /* DCMD */ - ncr53c810_log("NCR 810: Read DCMD %02X\n", dev->dcmd); - return dev->dcmd; - CASE_GET_REG32(dnad, 0x28) - CASE_GET_REG32(dsp, 0x2c) - CASE_GET_REG32(dsps, 0x30) - CASE_GET_REG32(scratcha, 0x34) - case 0x38: /* DMODE */ - ncr53c810_log("NCR 810: Read DMODE %02X\n", dev->dmode); - return dev->dmode; - case 0x39: /* DIEN */ - ncr53c810_log("NCR 810: Read DIEN %02X\n", dev->dien); - return dev->dien; - case 0x3a: /* SBR */ - ncr53c810_log("NCR 810: Read SBR %02X\n", dev->sbr); - return dev->sbr; - case 0x3b: /* DCNTL */ - ncr53c810_log("NCR 810: Read DCNTL %02X\n", dev->dcntl); - return dev->dcntl; - CASE_GET_REG32(adder, 0x3c) /* ADDER Output (Debug of relative jump address) */ - case 0x40: /* SIEN0 */ - ncr53c810_log("NCR 810: Read SIEN0 %02X\n", dev->sien0); - return dev->sien0; - case 0x41: /* SIEN1 */ - ncr53c810_log("NCR 810: Read SIEN1 %02X\n", dev->sien1); - return dev->sien1; - case 0x42: /* SIST0 */ - tmp = dev->sist0; - dev->sist0 = 0; - ncr53c810_update_irq(dev); - ncr53c810_log("NCR 810: Read SIST0 %02X\n", tmp); - return tmp; - case 0x43: /* SIST1 */ - tmp = dev->sist1; - dev->sist1 = 0; - ncr53c810_update_irq(dev); - ncr53c810_log("NCR 810: Read SIST1 %02X\n", tmp); - return tmp; - case 0x46: /* MACNTL */ - ncr53c810_log("NCR 810: Read MACNTL 4F\n"); - return 0x4f; - case 0x47: /* GPCNTL0 */ - ncr53c810_log("NCR 810: Read GPCNTL0 0F\n"); - return 0x0f; - case 0x48: /* STIME0 */ - ncr53c810_log("NCR 810: Read STIME0 %02X\n", dev->stime0); - return dev->stime0; - case 0x4a: /* RESPID */ - ncr53c810_log("NCR 810: Read RESPID %02X\n", dev->respid); - return dev->respid; - case 0x4c: /* STEST0 */ - ncr53c810_log("NCR 810: Read STEST0 %02X\n", dev->stest1); - return 0x00; - case 0x4d: /* STEST1 */ - ncr53c810_log("NCR 810: Read STEST1 %02X\n", dev->stest1); - return dev->stest1; - case 0x4e: /* STEST2 */ - ncr53c810_log("NCR 810: Read STEST2 %02X\n", dev->stest2); - return dev->stest2; - case 0x4f: /* STEST3 */ - ncr53c810_log("NCR 810: Read STEST3 %02X\n", dev->stest3); - return dev->stest3; - case 0x50: /* SIDL */ - /* This is needed by the linux drivers. We currently only update it - during the MSG IN phase. */ - ncr53c810_log("NCR 810: Read SIDL %02X\n", dev->sidl); - return dev->sidl; - case 0x52: /* STEST4 */ - ncr53c810_log("NCR 810: Read STEST4 E0\n"); - return 0xe0; - case 0x58: /* SBDL */ - /* Some drivers peek at the data bus during the MSG IN phase. */ - if ((dev->sstat1 & PHASE_MASK) == PHASE_MI) { - ncr53c810_log("NCR 810: Read SBDL %02X\n", dev->msg[0]); - return dev->msg[0]; - } - ncr53c810_log("NCR 810: Read SBDL 00\n"); - return 0; - case 0x59: /* SBDL high */ - ncr53c810_log("NCR 810: Read SBDLH 00\n"); - return 0; - CASE_GET_REG32(scratchb, 0x5c) - } - ncr53c810_log("readb 0x%x\n", offset); - return 0; - -#undef CASE_GET_REG24 -#undef CASE_GET_REG32 -} - - -static uint8_t -ncr53c810_io_readb(uint16_t addr, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - return ncr53c810_reg_readb(dev, addr & 0xff); -} - - -static uint16_t -ncr53c810_io_readw(uint16_t addr, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - uint16_t val; - - addr &= 0xff; - val = ncr53c810_reg_readb(dev, addr); - val |= ncr53c810_reg_readb(dev, addr + 1) << 8; - return val; -} - - -static uint32_t -ncr53c810_io_readl(uint16_t addr, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - uint32_t val; - - addr &= 0xff; - val = ncr53c810_reg_readb(dev, addr); - val |= ncr53c810_reg_readb(dev, addr + 1) << 8; - val |= ncr53c810_reg_readb(dev, addr + 2) << 16; - val |= ncr53c810_reg_readb(dev, addr + 3) << 24; - return val; -} - - -static void -ncr53c810_io_writeb(uint16_t addr, uint8_t val, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - ncr53c810_reg_writeb(dev, addr & 0xff, val); -} - - -static void -ncr53c810_io_writew(uint16_t addr, uint16_t val, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - addr &= 0xff; - ncr53c810_reg_writeb(dev, addr, val & 0xff); - ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); -} - - -static void -ncr53c810_io_writel(uint16_t addr, uint32_t val, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - addr &= 0xff; - ncr53c810_reg_writeb(dev, addr, val & 0xff); - ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); - ncr53c810_reg_writeb(dev, addr + 2, (val >> 16) & 0xff); - ncr53c810_reg_writeb(dev, addr + 3, (val >> 24) & 0xff); -} - - -static void -ncr53c810_mmio_writeb(uint32_t addr, uint8_t val, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - - ncr53c810_reg_writeb(dev, addr & 0xff, val); -} - - -static void -ncr53c810_mmio_writew(uint32_t addr, uint16_t val, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - - addr &= 0xff; - ncr53c810_reg_writeb(dev, addr, val & 0xff); - ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); -} - - -static void -ncr53c810_mmio_writel(uint32_t addr, uint32_t val, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - - addr &= 0xff; - ncr53c810_reg_writeb(dev, addr, val & 0xff); - ncr53c810_reg_writeb(dev, addr + 1, (val >> 8) & 0xff); - ncr53c810_reg_writeb(dev, addr + 2, (val >> 16) & 0xff); - ncr53c810_reg_writeb(dev, addr + 3, (val >> 24) & 0xff); -} - - -static uint8_t -ncr53c810_mmio_readb(uint32_t addr, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - - return ncr53c810_reg_readb(dev, addr & 0xff); -} - - -static uint16_t -ncr53c810_mmio_readw(uint32_t addr, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - uint16_t val; - - addr &= 0xff; - val = ncr53c810_reg_readb(dev, addr); - val |= ncr53c810_reg_readb(dev, addr + 1) << 8; - return val; -} - - -static uint32_t -ncr53c810_mmio_readl(uint32_t addr, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - uint32_t val; - - addr &= 0xff; - val = ncr53c810_reg_readb(dev, addr); - val |= ncr53c810_reg_readb(dev, addr + 1) << 8; - val |= ncr53c810_reg_readb(dev, addr + 2) << 16; - val |= ncr53c810_reg_readb(dev, addr + 3) << 24; - return val; -} - - -static void -ncr53c810_io_set(ncr53c810_t *dev, uint32_t base, uint16_t len) -{ - ncr53c810_log("NCR53c810: [PCI] Setting I/O handler at %04X\n", base); - io_sethandler(base, len, - ncr53c810_io_readb, ncr53c810_io_readw, ncr53c810_io_readl, - ncr53c810_io_writeb, ncr53c810_io_writew, ncr53c810_io_writel, dev); -} - - -static void -ncr53c810_io_remove(ncr53c810_t *dev, uint32_t base, uint16_t len) -{ - ncr53c810_log("NCR53c810: Removing I/O handler at %04X\n", base); - io_removehandler(base, len, - ncr53c810_io_readb, ncr53c810_io_readw, ncr53c810_io_readl, - ncr53c810_io_writeb, ncr53c810_io_writew, ncr53c810_io_writel, dev); -} - - -static void -ncr53c810_mem_init(ncr53c810_t *dev, uint32_t addr) -{ - mem_mapping_add(&dev->mmio_mapping, addr, 0x100, - ncr53c810_mmio_readb, ncr53c810_mmio_readw, ncr53c810_mmio_readl, - ncr53c810_mmio_writeb, ncr53c810_mmio_writew, ncr53c810_mmio_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); -} - - -static void -ncr53c810_mem_set_addr(ncr53c810_t *dev, uint32_t base) -{ - mem_mapping_set_addr(&dev->mmio_mapping, base, 0x100); -} - - -static void -ncr53c810_mem_disable(ncr53c810_t *dev) -{ - mem_mapping_disable(&dev->mmio_mapping); -} - - -uint8_t ncr53c810_pci_regs[256]; -bar_t ncr53c810_pci_bar[2]; - - -static uint8_t -ncr53c810_pci_read(int func, int addr, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - - ncr53c810_log("NCR53c810: Reading register %02X\n", addr & 0xff); - - if ((addr >= 0x80) && (addr <= 0xDF)) - return ncr53c810_reg_readb(dev, addr & 0x7F); - - switch (addr) { - case 0x00: - return 0x00; - case 0x01: - return 0x10; - case 0x02: - return 0x01; - case 0x03: - return 0x00; - case 0x04: - return ncr53c810_pci_regs[0x04] & 0x57; /*Respond to IO and memory accesses*/ - case 0x05: - return ncr53c810_pci_regs[0x05] & 0x01; - case 0x07: - return 2; - case 0x08: - return 0x10; /*Revision ID*/ - case 0x09: - return 0; /*Programming interface*/ - case 0x0A: - return 0; /*devubclass*/ - case 0x0B: - return 1; /*Class code*/ - case 0x0C: - case 0x0D: - return ncr53c810_pci_regs[addr]; - case 0x0E: - return 0; /*Header type */ - case 0x10: - return 1; /*I/O space*/ - case 0x11: - return ncr53c810_pci_bar[0].addr_regs[1]; - case 0x12: - return ncr53c810_pci_bar[0].addr_regs[2]; - case 0x13: - return ncr53c810_pci_bar[0].addr_regs[3]; - case 0x14: - return 0; /*Memory space*/ - case 0x15: - return ncr53c810_pci_bar[1].addr_regs[1]; - case 0x16: - return ncr53c810_pci_bar[1].addr_regs[2]; - case 0x17: - return ncr53c810_pci_bar[1].addr_regs[3]; - case 0x2C: - return 0x00; - case 0x2D: - return 0x10; - case 0x2E: - return 0x01; - case 0x2F: - return 0x00; - case 0x3C: - return dev->irq; - case 0x3D: - return PCI_INTA; - case 0x3E: - return 0x11; - case 0x3F: - return 0x40; - } - - return(0); -} - - -static void -ncr53c810_pci_write(int func, int addr, uint8_t val, void *p) -{ - ncr53c810_t *dev = (ncr53c810_t *)p; - uint8_t valxor; - - ncr53c810_log("NCR53c810: Write value %02X to register %02X\n", val, addr & 0xff); - - if ((addr >= 0x80) && (addr <= 0xDF)) { - ncr53c810_reg_writeb(dev, addr & 0x7F, val); - return; - } - - switch (addr) - { - case 0x04: - valxor = (val & 0x57) ^ ncr53c810_pci_regs[addr]; - if (valxor & PCI_COMMAND_IO) { - ncr53c810_io_remove(dev, dev->PCIBase, 0x0100); - if ((dev->PCIBase != 0) && (val & PCI_COMMAND_IO)) { - ncr53c810_io_set(dev, dev->PCIBase, 0x0100); - } - } - if (valxor & PCI_COMMAND_MEM) { - ncr53c810_mem_disable(dev); - if ((dev->MMIOBase != 0) && (val & PCI_COMMAND_MEM)) { - ncr53c810_mem_set_addr(dev, dev->MMIOBase); - } - } - ncr53c810_pci_regs[addr] = val & 0x57; - break; - - case 0x05: - ncr53c810_pci_regs[addr] = val & 0x01; - break; - - case 0x0C: - case 0x0D: - ncr53c810_pci_regs[addr] = val; - break; - - case 0x10: case 0x11: case 0x12: case 0x13: - /* I/O Base set. */ - /* First, remove the old I/O. */ - ncr53c810_io_remove(dev, dev->PCIBase, 0x0100); - /* Then let's set the PCI regs. */ - ncr53c810_pci_bar[0].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - ncr53c810_pci_bar[0].addr &= 0xff00; - dev->PCIBase = ncr53c810_pci_bar[0].addr; - /* Log the new base. */ - ncr53c810_log("NCR53c810: New I/O base is %04X\n" , dev->PCIBase); - /* We're done, so get out of the here. */ - if (ncr53c810_pci_regs[4] & PCI_COMMAND_IO) { - if (dev->PCIBase != 0) { - ncr53c810_io_set(dev, dev->PCIBase, 0x0100); - } - } - return; - - case 0x15: case 0x16: case 0x17: - /* MMIO Base set. */ - /* First, remove the old I/O. */ - ncr53c810_mem_disable(dev); - /* Then let's set the PCI regs. */ - ncr53c810_pci_bar[1].addr_regs[addr & 3] = val; - /* Then let's calculate the new I/O base. */ - dev->MMIOBase = ncr53c810_pci_bar[1].addr & 0xffffff00; - /* Log the new base. */ - ncr53c810_log("NCR53c810: New MMIO base is %08X\n" , dev->MMIOBase); - /* We're done, so get out of the here. */ - if (ncr53c810_pci_regs[4] & PCI_COMMAND_MEM) { - if (dev->MMIOBase != 0) { - ncr53c810_mem_set_addr(dev, dev->MMIOBase); - } - } - return; - - case 0x3C: - ncr53c810_pci_regs[addr] = val; - dev->irq = val; - return; - } -} - - -static void * -ncr53c810_init(const device_t *info) -{ - ncr53c810_t *dev; - - dev = malloc(sizeof(ncr53c810_t)); - memset(dev, 0x00, sizeof(ncr53c810_t)); - - dev->chip_rev = 0; - dev->pci_slot = pci_add_card(PCI_ADD_NORMAL, ncr53c810_pci_read, ncr53c810_pci_write, dev); - - ncr53c810_pci_bar[0].addr_regs[0] = 1; - ncr53c810_pci_bar[1].addr_regs[0] = 0; - ncr53c810_pci_regs[0x04] = 3; - - ncr53c810_mem_init(dev, 0x0fffff00); - ncr53c810_mem_disable(dev); - - ncr53c810_soft_reset(dev); - - timer_add(ncr53c810_callback, &dev->timer_period, &dev->timer_enabled, dev); - - dev->has_bios = device_get_config_int("bios"); - - /* Enable our BIOS space in PCI, if needed. */ - if (dev->has_bios) - rom_init(&dev->bios, NCR53C810_ROM, 0xc8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - - return(dev); -} - - -static void -ncr53c810_close(void *priv) -{ - ncr53c810_t *dev = (ncr53c810_t *)priv; - - if (dev) { - free(dev); - dev = NULL; - } -} - - -static const device_config_t ncr53c810_pci_config[] = { - { - "bios", "Enable BIOS", CONFIG_BINARY, "", 0 - }, - { - "", "", -1 - } -}; - - -const device_t ncr53c810_pci_device = -{ - "NCR 53c810 (SCSI)", - DEVICE_PCI, - 0, - ncr53c810_init, ncr53c810_close, NULL, - NULL, NULL, NULL, - ncr53c810_pci_config -}; diff --git a/src/scsi - Cópia/scsi_ncr53c810.h b/src/scsi - Cópia/scsi_ncr53c810.h deleted file mode 100644 index 29666e935..000000000 --- a/src/scsi - Cópia/scsi_ncr53c810.h +++ /dev/null @@ -1,31 +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 NCR 53C810 SCSI Host Adapter made by - * NCR and later Symbios and LSI. This controller was designed - * for the PCI bus. - * - * Version: @(#)scsi_ncr53c810.c 1.0.1 2018/03/18 - * - * Authors: TheCollector1995, - * Miran Grca, - * Paul Brook (QEMU), - * Artyom Tarasenko (QEMU), - * - * Copyright 2006-2018 Paul Brook. - * Copyright 2009-2018 Artyom Tarasenko. - * Copyright 2017,2018 Miran Grca. - */ -#ifndef SCSI_NCR5C3810_H -# define SCSI_NCR53C810_H - - -extern const device_t ncr53c810_pci_device; - - -#endif /*SCSI_NCR53C810_H*/ diff --git a/src/scsi - Cópia/scsi_x54x.c b/src/scsi - Cópia/scsi_x54x.c deleted file mode 100644 index e8c334eab..000000000 --- a/src/scsi - Cópia/scsi_x54x.c +++ /dev/null @@ -1,1980 +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 code common to the AHA-154x series of - * SCSI Host Adapters made by Adaptec, Inc. and the BusLogic - * series of SCSI Host Adapters made by Mylex. - * These controllers were designed for various buses. - * - * Version: @(#)scsi_x54x.c 1.0.21 2018/06/12 - * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#include -#include -#include -#include -#include -#include -#include -#define HAVE_STDARG_H -#include "../86box.h" -#include "../io.h" -#include "../dma.h" -#include "../pic.h" -#include "../pci.h" -#include "../mca.h" -#include "../mem.h" -#include "../rom.h" -#include "../device.h" -#include "../nvr.h" -#include "../timer.h" -#include "../plat.h" -#include "../cpu/cpu.h" -#include "scsi.h" -#include "scsi_device.h" -#include "scsi_aha154x.h" -#include "scsi_x54x.h" - - -#define X54X_RESET_DURATION_US UINT64_C(50000) - - -static void x54x_cmd_callback(void *priv); - -static volatile -x54x_t *x54x_dev; - - -#ifdef ENABLE_X54X_LOG -int x54x_do_log = ENABLE_X54X_LOG; -#endif - - -static void -x54x_log(const char *fmt, ...) -{ -#ifdef ENABLE_X54X_LOG - va_list ap; - - if (x54x_do_log) { - pclog("In %s mode: ",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real"); - va_start(ap, fmt); - pclog_ex(fmt, ap); - va_end(ap); - } -#endif -} - - -static void -x54x_irq(x54x_t *dev, int set) -{ - int int_type = 0; - int irq; - - if (dev->ven_get_irq) - irq = dev->ven_get_irq(dev); - else - irq = dev->Irq; - - if (dev->bus & DEVICE_PCI) { - x54x_log("PCI IRQ: %02X, PCI_INTA\n", dev->pci_slot); - if (set) - pci_set_irq(dev->pci_slot, PCI_INTA); - else - pci_clear_irq(dev->pci_slot, PCI_INTA); - } else { - if (set) { - if (dev->interrupt_type) - int_type = dev->interrupt_type(dev); - - if (int_type) - picintlevel(1 << irq); - else - picint(1 << irq); - } else - picintc(1 << irq); - } -} - - -static void -raise_irq(x54x_t *dev, int suppress, uint8_t Interrupt) -{ - if (Interrupt & (INTR_MBIF | INTR_MBOA)) { - if (! (dev->Interrupt & INTR_HACC)) { - dev->Interrupt |= Interrupt; /* Report now. */ - } else { - dev->PendingInterrupt |= Interrupt; /* Report later. */ - } - } else if (Interrupt & INTR_HACC) { - if (dev->Interrupt == 0 || dev->Interrupt == (INTR_ANY | INTR_HACC)) { - x54x_log("%s: RaiseInterrupt(): Interrupt=%02X\n", - dev->name, dev->Interrupt); - } - dev->Interrupt |= Interrupt; - } else { - x54x_log("%s: RaiseInterrupt(): Invalid interrupt state!\n", dev->name); - } - - dev->Interrupt |= INTR_ANY; - - if (dev->IrqEnabled && !suppress) - x54x_irq(dev, 1); -} - - -static void -clear_irq(x54x_t *dev) -{ - dev->Interrupt = 0; - x54x_log("%s: lowering IRQ %i (stat 0x%02x)\n", - dev->name, dev->Irq, dev->Interrupt); - x54x_irq(dev, 0); - if (dev->PendingInterrupt) { - x54x_log("%s: Raising Interrupt 0x%02X (Pending)\n", - dev->name, dev->Interrupt); - if (dev->MailboxOutInterrupts || !(dev->Interrupt & INTR_MBOA)) { - raise_irq(dev, 0, dev->PendingInterrupt); - } - dev->PendingInterrupt = 0; - } -} - - -static void -target_check(uint8_t id) -{ - if (! scsi_device_valid(id)) { - fatal("BIOS INT13 device on ID %02i has disappeared\n", id); - } -} - - -static uint8_t -completion_code(uint8_t *sense) -{ - switch (sense[12]) { - case 0x00: - return(0x00); - - case 0x20: - return(0x01); - - case 0x12: - case 0x21: - return(0x02); - - case 0x27: - return(0x03); - - case 0x14: - case 0x16: - return(0x04); - - case 0x10: - case 0x11: - return(0x10); - - case 0x17: - case 0x18: - return(0x11); - - case 0x01: - case 0x03: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - return(0x20); - - case 0x15: - case 0x02: - return(0x40); - - case 0x04: - case 0x28: - case 0x29: - case 0x2a: - return(0xaa); - - default: - break; - }; - - return(0xff); -} - - -static uint8_t -x54x_bios_command_08(uint8_t id, uint8_t *buffer) -{ - uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; - uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; - uint32_t len = 0; - int i, ret, sc; - - ret = scsi_device_read_capacity(id, cdb, rcbuf, &len); - sc = completion_code(scsi_device_sense(id)); - if (ret == 0) return(sc); - - memset(buffer, 0x00, 6); - for (i=0; i<4; i++) - buffer[i] = rcbuf[i]; - for (i=4; i<6; i++) - buffer[i] = rcbuf[(i + 2) ^ 1]; - x54x_log("BIOS Command 0x08: %02X %02X %02X %02X %02X %02X\n", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - - return(0); -} - - -static int -x54x_bios_command_15(uint8_t id, uint8_t *buffer) -{ - uint8_t cdb[12] = { GPCMD_READ_CDROM_CAPACITY, 0,0,0,0,0,0,0,0,0,0,0 }; - uint8_t rcbuf[8] = { 0,0,0,0,0,0,0,0 }; - uint32_t len = 0; - int i, ret, sc; - - ret = scsi_device_read_capacity(id, cdb, rcbuf, &len); - sc = completion_code(scsi_device_sense(id)); - - memset(buffer, 0x00, 6); - for (i=0; i<4; i++) - buffer[i] = (ret == 0) ? 0 : rcbuf[i]; - - scsi_device_type_data(id, &(buffer[4]), &(buffer[5])); - - x54x_log("BIOS Command 0x15: %02X %02X %02X %02X %02X %02X\n", - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); - - return(sc); -} - - -/* This returns the completion code. */ -static uint8_t -x54x_bios_command(x54x_t *x54x, uint8_t max_id, BIOSCMD *cmd, int8_t islba) -{ - uint8_t cdb[12] = { 0,0,0,0,0,0,0,0,0,0,0,0 }; - scsi_device_t *dev; - uint32_t dma_address; - uint32_t lba; - int sector_len = cmd->secount; - uint8_t ret; - - if (islba) - lba = lba32_blk(cmd); - else - lba = (cmd->u.chs.cyl << 9) + (cmd->u.chs.head << 5) + cmd->u.chs.sec; - - x54x_log("BIOS Command = 0x%02X\n", cmd->command); - - if ((cmd->id > max_id) || (cmd->lun > 7)) { - x54x_log("BIOS Target ID %i or LUN %i are above maximum\n", - cmd->id, cmd->lun); - return(0x80); - } - - if (cmd->lun) { - x54x_log("BIOS Target LUN is not 0\n"); - return(0x80); - } - - /* Get pointer to selected device. */ - dev = &SCSIDevices[cmd->id]; - dev->BufferLength = 0; - - if (! scsi_device_present(cmd->id)) { - x54x_log("BIOS Target ID %i has no device attached\n", cmd->id); - return(0x80); - } - - if ((dev->LunType == SCSI_CDROM) && !x54x->cdrom_boot) { - x54x_log("BIOS Target ID %i is CD-ROM on unsupported BIOS\n", cmd->id); - return(0x80); - } - - dma_address = ADDR_TO_U32(cmd->dma_address); - - x54x_log("BIOS Data Buffer write: length %d, pointer 0x%04X\n", - sector_len, dma_address); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - switch(cmd->command) { - case 0x00: /* Reset Disk System, in practice it's a nop */ - return(0); - - case 0x01: /* Read Status of Last Operation */ - target_check(cmd->id); - - /* - * Assuming 14 bytes because that is the default - * length for SCSI sense, and no command-specific - * indication is given. - */ - dev->BufferLength = 14; - dev->CmdBuffer = (uint8_t *)malloc(14); - memset(dev->CmdBuffer, 0x00, 14); - - if (sector_len > 0) { - x54x_log("BIOS DMA: Reading 14 bytes at %08X\n", - dma_address); - DMAPageWrite(dma_address, - scsi_device_sense(cmd->id), 14); - } - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(0); - - case 0x02: /* Read Desired Sectors to Memory */ - target_check(cmd->id); - - dev->BufferLength = -1; - - cdb[0] = GPCMD_READ_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = 0; - cdb[8] = sector_len; -#if 0 - x54x_log("BIOS CMD(READ, %08lx, %d)\n", lba, cmd->secount); -#endif - - scsi_device_command_phase0(cmd->id, cdb); - - if (dev->Phase == SCSI_PHASE_STATUS) - goto skip_read_phase1; - - dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); - - scsi_device_command_phase1(cmd->id); - if (sector_len > 0) { - x54x_log("BIOS DMA: Reading %i bytes at %08X\n", - dev->BufferLength, dma_address); - DMAPageWrite(dma_address, - dev->CmdBuffer, dev->BufferLength); - } - -skip_read_phase1: - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(completion_code(scsi_device_sense(cmd->id))); - - case 0x03: /* Write Desired Sectors from Memory */ - target_check(cmd->id); - - dev->BufferLength = -1; - - cdb[0] = GPCMD_WRITE_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = 0; - cdb[8] = sector_len; -#if 0 - x54x_log("BIOS CMD(WRITE, %08lx, %d)\n", lba, cmd->secount); -#endif - - scsi_device_command_phase0(cmd->id, cdb); - - if (dev->Phase == SCSI_PHASE_STATUS) - goto skip_write_phase1; - - dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); - - if (sector_len > 0) { - x54x_log("BIOS DMA: Reading %i bytes at %08X\n", - dev->BufferLength, dma_address); - DMAPageRead(dma_address, - dev->CmdBuffer, dev->BufferLength); - } - - scsi_device_command_phase1(cmd->id); - -skip_write_phase1: - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(completion_code(scsi_device_sense(cmd->id))); - - case 0x04: /* Verify Desired Sectors */ - target_check(cmd->id); - - cdb[0] = GPCMD_VERIFY_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - cdb[7] = 0; - cdb[8] = sector_len; - - scsi_device_command_phase0(cmd->id, cdb); - - return(completion_code(scsi_device_sense(cmd->id))); - - case 0x05: /* Format Track, invalid since SCSI has no tracks */ -//FIXME: add a longer delay here --FvK - return(1); - - case 0x06: /* Identify SCSI Devices, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x07: /* Format Unit */ - target_check(cmd->id); - - cdb[0] = GPCMD_FORMAT_UNIT; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command_phase0(cmd->id, cdb); - - return(completion_code(scsi_device_sense(cmd->id))); - - case 0x08: /* Read Drive Parameters */ - target_check(cmd->id); - - dev->BufferLength = 6; - dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); - memset(dev->CmdBuffer, 0x00, dev->BufferLength); - - ret = x54x_bios_command_08(cmd->id, dev->CmdBuffer); - - x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); - DMAPageWrite(dma_address, - dev->CmdBuffer, 4 /* dev->BufferLength */); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(ret); - - case 0x09: /* Initialize Drive Pair Characteristics, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x0c: /* Seek */ - target_check(cmd->id); - - cdb[0] = GPCMD_SEEK_10; - cdb[1] = (cmd->lun & 7) << 5; - cdb[2] = (lba >> 24) & 0xff; - cdb[3] = (lba >> 16) & 0xff; - cdb[4] = (lba >> 8) & 0xff; - cdb[5] = lba & 0xff; - - scsi_device_command_phase0(cmd->id, cdb); - - return((dev->Status == SCSI_STATUS_OK) ? 1 : 0); - - case 0x0d: /* Alternate Disk Reset, in practice it's a nop */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x10: /* Test Drive Ready */ - target_check(cmd->id); - - cdb[0] = GPCMD_TEST_UNIT_READY; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command_phase0(cmd->id, cdb); - - return(completion_code(scsi_device_sense(cmd->id))); - - case 0x11: /* Recalibrate */ - target_check(cmd->id); - - cdb[0] = GPCMD_REZERO_UNIT; - cdb[1] = (cmd->lun & 7) << 5; - - scsi_device_command_phase0(cmd->id, cdb); - - return(completion_code(scsi_device_sense(cmd->id))); - - case 0x14: /* Controller Diagnostic */ -//FIXME: add a longer delay here --FvK - return(0); - - case 0x15: /* Read DASD Type */ - target_check(cmd->id); - - dev->BufferLength = 6; - dev->CmdBuffer = (uint8_t *)malloc(dev->BufferLength); - memset(dev->CmdBuffer, 0x00, dev->BufferLength); - - ret = x54x_bios_command_15(cmd->id, dev->CmdBuffer); - - x54x_log("BIOS DMA: Reading 6 bytes at %08X\n", dma_address); - DMAPageWrite(dma_address, - dev->CmdBuffer, 4 /* dev->BufferLength */); - - if (dev->CmdBuffer != NULL) { - free(dev->CmdBuffer); - dev->CmdBuffer = NULL; - } - - return(ret); - - default: - x54x_log("BIOS: Unimplemented command: %02X\n", cmd->command); - return(1); - } - - x54x_log("BIOS Request complete\n"); -} - - -static void -x54x_cmd_done(x54x_t *dev, int suppress) -{ - int fast = 0; - - dev->DataReply = 0; - dev->Status |= STAT_IDLE; - - if (dev->ven_cmd_is_fast) { - fast = dev->ven_cmd_is_fast(dev); - } - - if ((dev->Command != CMD_START_SCSI) || fast) { - dev->Status &= ~STAT_DFULL; - x54x_log("%s: Raising IRQ %i\n", dev->name, dev->Irq); - raise_irq(dev, suppress, INTR_HACC); - } - - dev->Command = 0xff; - dev->CmdParam = 0; -} - - -static void -x54x_add_to_period(int TransferLength) -{ - x54x_dev->temp_period += (int64_t) TransferLength; -} - - -static void -x54x_mbi_setup(x54x_t *dev, uint32_t CCBPointer, CCBU *CmdBlock, - uint8_t HostStatus, uint8_t TargetStatus, uint8_t mbcc) -{ - Req_t *req = &dev->Req; - - req->CCBPointer = CCBPointer; - memcpy(&(req->CmdBlock), CmdBlock, sizeof(CCB32)); - req->Is24bit = dev->Mbx24bit; - req->HostStatus = HostStatus; - req->TargetStatus = TargetStatus; - req->MailboxCompletionCode = mbcc; - - x54x_log("Mailbox in setup\n"); -} - - -static void -x54x_ccb(x54x_t *dev) -{ - Req_t *req = &dev->Req; - - /* Rewrite the CCB up to the CDB. */ - x54x_log("CCB completion code and statuses rewritten (pointer %08X)\n", req->CCBPointer); - DMAPageWrite(req->CCBPointer + 0x000D, &(req->MailboxCompletionCode), 1); - DMAPageWrite(req->CCBPointer + 0x000E, &(req->HostStatus), 1); - DMAPageWrite(req->CCBPointer + 0x000F, &(req->TargetStatus), 1); - x54x_add_to_period(3); - - if (dev->MailboxOutInterrupts) - dev->ToRaise = INTR_MBOA | INTR_ANY; - else - dev->ToRaise = 0; -} - - -static void -x54x_mbi(x54x_t *dev) -{ - Req_t *req = &dev->Req; -// uint32_t CCBPointer = req->CCBPointer; - addr24 CCBPointer; - CCBU *CmdBlock = &(req->CmdBlock); - uint8_t HostStatus = req->HostStatus; - uint8_t TargetStatus = req->TargetStatus; - uint32_t MailboxCompletionCode = req->MailboxCompletionCode; - uint32_t Incoming; - - Incoming = dev->MailboxInAddr + (dev->MailboxInPosCur * (dev->Mbx24bit ? sizeof(Mailbox_t) : sizeof(Mailbox32_t))); - - if (MailboxCompletionCode != MBI_NOT_FOUND) { - CmdBlock->common.HostStatus = HostStatus; - CmdBlock->common.TargetStatus = TargetStatus; - - /* Rewrite the CCB up to the CDB. */ - x54x_log("CCB statuses rewritten (pointer %08X)\n", req->CCBPointer); - DMAPageWrite(req->CCBPointer + 0x000E, &(req->HostStatus), 1); - DMAPageWrite(req->CCBPointer + 0x000F, &(req->TargetStatus), 1); - x54x_add_to_period(2); - } else { - x54x_log("Mailbox not found!\n"); - } - - x54x_log("Host Status 0x%02X, Target Status 0x%02X\n",HostStatus,TargetStatus); - - if (dev->Mbx24bit) { - U32_TO_ADDR(CCBPointer, req->CCBPointer); - x54x_log("Mailbox 24-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); - DMAPageWrite(Incoming, &(req->MailboxCompletionCode), 1); - DMAPageWrite(Incoming + 1, (uint8_t *)&CCBPointer, 3); - x54x_add_to_period(4); - x54x_log("%i bytes of 24-bit mailbox written to: %08X\n", sizeof(Mailbox_t), Incoming); - } else { - x54x_log("Mailbox 32-bit: Status=0x%02X, CCB at 0x%04X\n", req->MailboxCompletionCode, CCBPointer); - DMAPageWrite(Incoming, (uint8_t *)&(req->CCBPointer), 4); - DMAPageWrite(Incoming + 4, &(req->HostStatus), 1); - DMAPageWrite(Incoming + 5, &(req->TargetStatus), 1); - DMAPageWrite(Incoming + 7, &(req->MailboxCompletionCode), 1); - x54x_add_to_period(7); - x54x_log("%i bytes of 32-bit mailbox written to: %08X\n", sizeof(Mailbox32_t), Incoming); - } - - dev->MailboxInPosCur++; - if (dev->MailboxInPosCur >= dev->MailboxCount) - dev->MailboxInPosCur = 0; - - dev->ToRaise = INTR_MBIF | INTR_ANY; - if (dev->MailboxOutInterrupts) - dev->ToRaise |= INTR_MBOA; -} - - -static void -x54x_rd_sge(int Is24bit, uint32_t Address, SGE32 *SG) -{ - SGE SGE24; - - if (Is24bit) { - DMAPageRead(Address, (uint8_t *)&SGE24, sizeof(SGE)); - x54x_add_to_period(sizeof(SGE)); - - /* Convert the 24-bit entries into 32-bit entries. */ - x54x_log("Read S/G block: %06X, %06X\n", SGE24.Segment, SGE24.SegmentPointer); - SG->Segment = ADDR_TO_U32(SGE24.Segment); - SG->SegmentPointer = ADDR_TO_U32(SGE24.SegmentPointer); - } else { - DMAPageRead(Address, (uint8_t *)SG, sizeof(SGE32)); - x54x_add_to_period(sizeof(SGE32)); - } -} - - -static int -x54x_get_length(Req_t *req, int Is24bit) -{ - uint32_t DataPointer, DataLength; - uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); - SGE32 SGBuffer; - uint32_t DataToTransfer = 0, i = 0; - - if (Is24bit) { - DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); - x54x_log("Data length: %08X\n", req->CmdBlock.old.DataLength); - } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; - } - x54x_log("Data Buffer write: length %d, pointer 0x%04X\n", - DataLength, DataPointer); - - if (!DataLength) - return(0); - - if (req->CmdBlock.common.ControlByte != 0x03) { - if (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND || - req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES) { - for (i = 0; i < DataLength; i += SGEntryLength) { - x54x_rd_sge(Is24bit, DataPointer + i, &SGBuffer); - - DataToTransfer += SGBuffer.Segment; - } - return(DataToTransfer); - } else if (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND || - req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) { - return(DataLength); - } else { - return(0); - } - } else { - return(0); - } -} - - -static void -x54x_set_residue(Req_t *req, int32_t TransferLength) -{ - uint32_t Residue = 0; - addr24 Residue24; - int32_t BufLen = SCSIDevices[req->TargetID].BufferLength; - - if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES) || - (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { - - if ((TransferLength > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { - TransferLength -= BufLen; - if (TransferLength > 0) - Residue = TransferLength; - } - - if (req->Is24bit) { - U32_TO_ADDR(Residue24, Residue); - DMAPageWrite(req->CCBPointer + 0x0004, (uint8_t *)&Residue24, 3); - x54x_add_to_period(3); - x54x_log("24-bit Residual data length for reading: %d\n", Residue); - } else { - DMAPageWrite(req->CCBPointer + 0x0004, (uint8_t *)&Residue, 4); - x54x_add_to_period(4); - x54x_log("32-bit Residual data length for reading: %d\n", Residue); - } - } -} - - -static void -x54x_buf_dma_transfer(Req_t *req, int Is24bit, int TransferLength, int dir) -{ - uint32_t DataPointer, DataLength; - uint32_t SGEntryLength = (Is24bit ? sizeof(SGE) : sizeof(SGE32)); - uint32_t Address, i; - int32_t BufLen = SCSIDevices[req->TargetID].BufferLength; - uint8_t read_from_host = (dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_OUT) || (req->CmdBlock.common.ControlByte == 0x00))); - uint8_t write_to_host = (!dir && ((req->CmdBlock.common.ControlByte == CCB_DATA_XFER_IN) || (req->CmdBlock.common.ControlByte == 0x00))); - int sg_pos = 0; - SGE32 SGBuffer; - uint32_t DataToTransfer = 0; - - if (Is24bit) { - DataPointer = ADDR_TO_U32(req->CmdBlock.old.DataPointer); - DataLength = ADDR_TO_U32(req->CmdBlock.old.DataLength); - } else { - DataPointer = req->CmdBlock.new.DataPointer; - DataLength = req->CmdBlock.new.DataLength; - } - x54x_log("Data Buffer %s: length %d (%u), pointer 0x%04X\n", - dir ? "write" : "read", BufLen, DataLength, DataPointer); - - if ((req->CmdBlock.common.ControlByte != 0x03) && TransferLength && BufLen) { - if ((req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND) || - (req->CmdBlock.common.Opcode == SCATTER_GATHER_COMMAND_RES)) { - - /* If the control byte is 0x00, it means that the transfer direction is set up by the SCSI command without - checking its length, so do this procedure for both no read/write commands. */ - if ((DataLength > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { - for (i = 0; i < DataLength; i += SGEntryLength) { - x54x_rd_sge(Is24bit, DataPointer + i, &SGBuffer); - - Address = SGBuffer.SegmentPointer; - DataToTransfer = MIN((int) SGBuffer.Segment, BufLen); - - if (read_from_host && DataToTransfer) { - x54x_log("Reading S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - DMAPageRead(Address, &(SCSIDevices[req->TargetID].CmdBuffer[sg_pos]), DataToTransfer); - } - else if (write_to_host && DataToTransfer) { - x54x_log("Writing S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - DMAPageWrite(Address, &(SCSIDevices[req->TargetID].CmdBuffer[sg_pos]), DataToTransfer); - } - else - x54x_log("No action on S/G segment %i: length %i, pointer %08X\n", i, DataToTransfer, Address); - - sg_pos += SGBuffer.Segment; - - BufLen -= SGBuffer.Segment; - if (BufLen < 0) - BufLen = 0; - - x54x_log("After S/G segment done: %i, %i\n", sg_pos, BufLen); - } - } - } else if ((req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND) || - (req->CmdBlock.common.Opcode == SCSI_INITIATOR_COMMAND_RES)) { - Address = DataPointer; - - if ((DataLength > 0) && (BufLen > 0) && (req->CmdBlock.common.ControlByte < 0x03)) { - if (read_from_host) - DMAPageRead(Address, SCSIDevices[req->TargetID].CmdBuffer, MIN(BufLen, (int) DataLength)); - else if (write_to_host) - DMAPageWrite(Address, SCSIDevices[req->TargetID].CmdBuffer, MIN(BufLen, (int) DataLength)); - } - } - } -} - - -void -x54x_buf_alloc(uint8_t id, int length) -{ - if (SCSIDevices[id].CmdBuffer != NULL) { - free(SCSIDevices[id].CmdBuffer); - SCSIDevices[id].CmdBuffer = NULL; - } - - x54x_log("Allocating data buffer (%i bytes)\n", length); - SCSIDevices[id].CmdBuffer = (uint8_t *) malloc(length); - memset(SCSIDevices[id].CmdBuffer, 0, length); -} - - -void -x54x_buf_free(uint8_t id) -{ - if (SCSIDevices[id].CmdBuffer != NULL) { - free(SCSIDevices[id].CmdBuffer); - SCSIDevices[id].CmdBuffer = NULL; - } -} - - -static uint8_t -ConvertSenseLength(uint8_t RequestSenseLength) -{ - x54x_log("Unconverted Request Sense length %i\n", RequestSenseLength); - - if (RequestSenseLength == 0) - RequestSenseLength = 14; - else if (RequestSenseLength == 1) - RequestSenseLength = 0; - - x54x_log("Request Sense length %i\n", RequestSenseLength); - - return(RequestSenseLength); -} - - -uint32_t -SenseBufferPointer(Req_t *req) -{ - uint32_t SenseBufferAddress; - if (req->Is24bit) { - SenseBufferAddress = req->CCBPointer; - SenseBufferAddress += req->CmdBlock.common.CdbLength + 18; - } else { - SenseBufferAddress = req->CmdBlock.new.SensePointer; - } - - return(SenseBufferAddress); -} - - -static void -SenseBufferFree(Req_t *req, int Copy) -{ - uint8_t SenseLength = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); - uint32_t SenseBufferAddress; - uint8_t temp_sense[256]; - - if (SenseLength && Copy) { - scsi_device_request_sense(req->TargetID, temp_sense, SenseLength); - - /* - * The sense address, in 32-bit mode, is located in the - * Sense Pointer of the CCB, but in 24-bit mode, it is - * located at the end of the Command Descriptor Block. - */ - SenseBufferAddress = SenseBufferPointer(req); - - x54x_log("Request Sense address: %02X\n", SenseBufferAddress); - - x54x_log("SenseBufferFree(): Writing %i bytes at %08X\n", - SenseLength, SenseBufferAddress); - DMAPageWrite(SenseBufferAddress, temp_sense, SenseLength); - x54x_add_to_period(SenseLength); - x54x_log("Sense data written to buffer: %02X %02X %02X\n", - temp_sense[2], temp_sense[12], temp_sense[13]); - } -} - - -static void -x54x_scsi_cmd(x54x_t *dev) -{ - Req_t *req = &dev->Req; - uint8_t id, lun; - uint8_t temp_cdb[12]; - uint32_t i; - int target_cdb_len = 12; - int target_data_len; - uint8_t bit24 = !!req->Is24bit; - int32_t *BufLen; - uint8_t phase; - uint32_t SenseBufferAddress; - int64_t p; - - id = req->TargetID; - lun = req->LUN; - - target_cdb_len = 12; - target_data_len = x54x_get_length(req, bit24); - - if (!scsi_device_valid(id)) - fatal("SCSI target on %02i has disappeared\n", id); - - x54x_log("target_data_len = %i\n", target_data_len); - - x54x_log("SCSI command being executed on ID %i, LUN %i\n", id, lun); - - x54x_log("SCSI CDB[0]=0x%02X\n", req->CmdBlock.common.Cdb[0]); - for (i=1; iCmdBlock.common.CdbLength; i++) - x54x_log("SCSI CDB[%i]=%i\n", i, req->CmdBlock.common.Cdb[i]); - - memset(temp_cdb, 0x00, target_cdb_len); - if (req->CmdBlock.common.CdbLength <= target_cdb_len) { - memcpy(temp_cdb, req->CmdBlock.common.Cdb, - req->CmdBlock.common.CdbLength); - x54x_add_to_period(req->CmdBlock.common.CdbLength); - } else { - memcpy(temp_cdb, req->CmdBlock.common.Cdb, target_cdb_len); - x54x_add_to_period(target_cdb_len); - } - - dev->Residue = 0; - - BufLen = scsi_device_get_buf_len(id); - *BufLen = target_data_len; - - x54x_log("Command buffer: %08X\n", SCSIDevices[id].CmdBuffer); - - scsi_device_command_phase0(id, temp_cdb); - - phase = SCSIDevices[id].Phase; - - x54x_log("Control byte: %02X\n", (req->CmdBlock.common.ControlByte == 0x03)); - - if (phase != SCSI_PHASE_STATUS) { - if ((temp_cdb[0] == 0x03) && (req->CmdBlock.common.ControlByte == 0x03)) { - /* Request sense in non-data mode - sense goes to sense buffer. */ - *BufLen = ConvertSenseLength(req->CmdBlock.common.RequestSenseLength); - x54x_buf_alloc(id, *BufLen); - scsi_device_command_phase1(id); - if ((SCSIDevices[id].Status != SCSI_STATUS_OK) && (*BufLen > 0)) { - SenseBufferAddress = SenseBufferPointer(req); - DMAPageWrite(SenseBufferAddress, SCSIDevices[id].CmdBuffer, *BufLen); - x54x_add_to_period(*BufLen); - } - } else { - p = scsi_device_get_callback(id); - if (p <= 0LL) - x54x_add_to_period(*BufLen); - else - dev->media_period += p; - x54x_buf_alloc(id, MIN(target_data_len, *BufLen)); - if (phase == SCSI_PHASE_DATA_OUT) - x54x_buf_dma_transfer(req, bit24, target_data_len, 1); - scsi_device_command_phase1(id); - if (phase == SCSI_PHASE_DATA_IN) - x54x_buf_dma_transfer(req, bit24, target_data_len, 0); - - SenseBufferFree(req, (SCSIDevices[id].Status != SCSI_STATUS_OK)); - } - } else - SenseBufferFree(req, (SCSIDevices[id].Status != SCSI_STATUS_OK)); - - x54x_set_residue(req, target_data_len); - - x54x_buf_free(id); - - x54x_log("Request complete\n"); - - if (SCSIDevices[id].Status == SCSI_STATUS_OK) { - x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); - } else if (SCSIDevices[id].Status == SCSI_STATUS_CHECK_CONDITION) { - x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_CHECK_CONDITION, MBI_ERROR); - } - - x54x_log("SCSIDevices[%02i].Status = %02X\n", id, SCSIDevices[id].Status); -} - - -static void -x54x_notify(x54x_t *dev) -{ - if (dev->MailboxIsBIOS) - x54x_ccb(dev); - else - x54x_mbi(dev); -} - - -static void -x54x_req_setup(x54x_t *dev, uint32_t CCBPointer, Mailbox32_t *Mailbox32) -{ - Req_t *req = &dev->Req; - uint8_t id, lun; - - /* Fetch data from the Command Control Block. */ - DMAPageRead(CCBPointer, (uint8_t *)&req->CmdBlock, sizeof(CCB32)); - x54x_add_to_period(sizeof(CCB32)); - - req->Is24bit = dev->Mbx24bit; - req->CCBPointer = CCBPointer; - req->TargetID = dev->Mbx24bit ? req->CmdBlock.old.Id : req->CmdBlock.new.Id; - req->LUN = dev->Mbx24bit ? req->CmdBlock.old.Lun : req->CmdBlock.new.Lun; - - id = req->TargetID; - lun = req->LUN; - if ((id > dev->max_id) || (lun > 7)) { - x54x_log("SCSI Target ID %i or LUN %i is not valid\n",id,lun); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, - CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); - x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); - x54x_notify(dev); - return; - } - - x54x_log("Scanning SCSI Target ID %i\n", id); - - SCSIDevices[id].Status = SCSI_STATUS_OK; - - /* If there is no device at ID:0, timeout the selection - the LUN is then checked later. */ - if (! scsi_device_present(id)) { - x54x_log("SCSI Target ID %i and LUN %i have no device attached\n",id,lun); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, - CCB_SELECTION_TIMEOUT, SCSI_STATUS_OK, MBI_ERROR); - x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); - x54x_notify(dev); - } else { - x54x_log("SCSI Target ID %i detected and working\n", id); - - x54x_log("Transfer Control %02X\n", req->CmdBlock.common.ControlByte); - x54x_log("CDB Length %i\n", req->CmdBlock.common.CdbLength); - x54x_log("CCB Opcode %x\n", req->CmdBlock.common.Opcode); - if ((req->CmdBlock.common.Opcode > 0x04) && (req->CmdBlock.common.Opcode != 0x81)) { - x54x_log("Invalid opcode: %02X\n", - req->CmdBlock.common.ControlByte); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_OP_CODE, SCSI_STATUS_OK, MBI_ERROR); - x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); - x54x_notify(dev); - return; - } - if (req->CmdBlock.common.Opcode == 0x81) { - x54x_log("Bus reset opcode\n"); - scsi_device_reset(id); - x54x_mbi_setup(dev, req->CCBPointer, &req->CmdBlock, - CCB_COMPLETE, SCSI_STATUS_OK, MBI_SUCCESS); - x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); - x54x_notify(dev); - return; - } - - if (req->CmdBlock.common.ControlByte > 0x03) { - x54x_log("Invalid control byte: %02X\n", - req->CmdBlock.common.ControlByte); - x54x_mbi_setup(dev, CCBPointer, &req->CmdBlock, CCB_INVALID_DIRECTION, SCSI_STATUS_OK, MBI_ERROR); - x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); - x54x_notify(dev); - return; - } - - x54x_log("%s: Callback: Process SCSI request\n", dev->name); - x54x_scsi_cmd(dev); - - x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); - x54x_notify(dev); - } -} - - -static void -x54x_req_abort(x54x_t *dev, uint32_t CCBPointer) -{ - CCBU CmdBlock; - - /* Fetch data from the Command Control Block. */ - DMAPageRead(CCBPointer, (uint8_t *)&CmdBlock, sizeof(CCB32)); - x54x_add_to_period(sizeof(CCB32)); - - x54x_mbi_setup(dev, CCBPointer, &CmdBlock, - 0x26, SCSI_STATUS_OK, MBI_NOT_FOUND); - x54x_log("%s: Callback: Send incoming mailbox\n", dev->name); - x54x_notify(dev); -} - - -static uint32_t -x54x_mbo(x54x_t *dev, Mailbox32_t *Mailbox32) -{ - Mailbox_t MailboxOut; - uint32_t Outgoing; - uint32_t ccbp; - uint32_t Addr; - uint32_t Cur; - - if (dev->MailboxIsBIOS) { - Addr = dev->BIOSMailboxOutAddr; - Cur = dev->BIOSMailboxOutPosCur; - } else { - Addr = dev->MailboxOutAddr; - Cur = dev->MailboxOutPosCur; - } - - if (dev->Mbx24bit) { - Outgoing = Addr + (Cur * sizeof(Mailbox_t)); - DMAPageRead(Outgoing, (uint8_t *)&MailboxOut, sizeof(Mailbox_t)); - x54x_add_to_period(sizeof(Mailbox_t)); - - ccbp = *(uint32_t *) &MailboxOut; - Mailbox32->CCBPointer = (ccbp >> 24) | ((ccbp >> 8) & 0xff00) | ((ccbp << 8) & 0xff0000); - Mailbox32->u.out.ActionCode = MailboxOut.CmdStatus; - } else { - Outgoing = Addr + (Cur * sizeof(Mailbox32_t)); - - DMAPageRead(Outgoing, (uint8_t *)Mailbox32, sizeof(Mailbox32_t)); - x54x_add_to_period(sizeof(Mailbox32_t)); - } - - return(Outgoing); -} - - -uint8_t -x54x_mbo_process(x54x_t *dev) -{ - Mailbox32_t mb32; - uint32_t Outgoing; - uint8_t CmdStatus = MBO_FREE; - uint32_t CodeOffset = 0; - - CodeOffset = dev->Mbx24bit ? 0 : 7; - - Outgoing = x54x_mbo(dev, &mb32); - - if (mb32.u.out.ActionCode == MBO_START) { - x54x_log("Start Mailbox Command\n"); - x54x_req_setup(dev, mb32.CCBPointer, &mb32); - } else if (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT)) { - x54x_log("Abort Mailbox Command\n"); - x54x_req_abort(dev, mb32.CCBPointer); - } /* else { - x54x_log("Invalid action code: %02X\n", mb32.u.out.ActionCode); - } */ - - if ((mb32.u.out.ActionCode == MBO_START) || (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT))) { - /* We got the mailbox, mark it as free in the guest. */ - x54x_log("x54x_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset); - DMAPageWrite(Outgoing + CodeOffset, &CmdStatus, 1); - x54x_add_to_period(1); - - if (dev->ToRaise) - raise_irq(dev, 0, dev->ToRaise); - - if (dev->MailboxIsBIOS) - dev->BIOSMailboxReq--; - else - dev->MailboxReq--; - - return(1); - } - - return(0); -} - - -static void -x54x_do_mail(x54x_t *dev) -{ - int aggressive = 1; - - dev->MailboxIsBIOS = 0; - - if (dev->is_aggressive_mode) { - aggressive = dev->is_aggressive_mode(dev); - x54x_log("Processing mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); - }/* else { - x54x_log("Defaulting to process mailboxes in %s mode...\n", aggressive ? "aggressive" : "strict"); - }*/ - - if (!dev->MailboxCount) { - x54x_log("x54x_do_mail(): No Mailboxes\n"); - return; - } - - if (aggressive) { - /* Search for a filled mailbox - stop if we have scanned all mailboxes. */ - for (dev->MailboxOutPosCur = 0; dev->MailboxOutPosCur < dev->MailboxCount; dev->MailboxOutPosCur++) { - if (x54x_mbo_process(dev)) - break; - } - } else { - /* Strict round robin mode - only process the current mailbox and advance the pointer if successful. */ -x54x_do_mail_again: - if (x54x_mbo_process(dev)) { - dev->MailboxOutPosCur++; - dev->MailboxOutPosCur %= dev->MailboxCount; - goto x54x_do_mail_again; - } - } -} - - -static void -x54x_cmd_done(x54x_t *dev, int suppress); - - -static void -x54x_cmd_callback(void *priv) -{ - double period; - x54x_t *dev = (x54x_t *) x54x_dev; - - int mailboxes_present, bios_mailboxes_present; - - mailboxes_present = (!(dev->Status & STAT_INIT) && dev->MailboxInit && dev->MailboxReq); - bios_mailboxes_present = (dev->ven_callback && dev->BIOSMailboxInit && dev->BIOSMailboxReq); - - if (!mailboxes_present && !bios_mailboxes_present) { - /* If we did not get anything, do nothing and wait 10 us. */ - dev->timer_period = 10LL * TIMER_USEC; - return; - } - - dev->temp_period = dev->media_period = 0LL; - - if (!mailboxes_present) { - /* Do only BIOS mailboxes. */ - dev->ven_callback(dev); - } else if (!bios_mailboxes_present) { - /* Do only normal mailboxes. */ - x54x_do_mail(dev); - } else { - /* Do both kinds of mailboxes. */ - if (dev->callback_phase) - dev->ven_callback(dev); - else - x54x_do_mail(dev); - - dev->callback_phase = (dev->callback_phase + 1) & 0x01; - } - - period = (1000000.0 / x54x_dev->ha_bps) * ((double) TIMER_USEC) * ((double) dev->temp_period); - dev->timer_period = dev->media_period + ((int64_t) period) + (40LL * TIMER_USEC); - x54x_log("Temporary period: %" PRId64 " us (%" PRIi64 " periods)\n", dev->timer_period, dev->temp_period); -} - - -static uint8_t -x54x_in(uint16_t port, void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - uint8_t ret; - - switch (port & 3) { - case 0: - default: - ret = dev->Status; - break; - - case 1: - ret = dev->DataBuf[dev->DataReply]; - if (dev->DataReplyLeft) { - dev->DataReply++; - dev->DataReplyLeft--; - if (! dev->DataReplyLeft) - x54x_cmd_done(dev, 0); - } - break; - - case 2: - if (dev->int_geom_writable) - ret = dev->Interrupt; - else - ret = dev->Interrupt & ~0x70; - break; - - case 3: - /* Bits according to ASPI4DOS.SYS v3.36: - 0 Not checked - 1 Must be 0 - 2 Must be 0-0-0-1 - 3 Must be 0 - 4 Must be 0-1-0-0 - 5 Must be 0 - 6 Not checked - 7 Not checked - */ - if (dev->int_geom_writable) - ret = dev->Geometry; - else { - switch(dev->Geometry) { - case 0: default: ret = 'A'; break; - case 1: ret = 'D'; break; - case 2: ret = 'A'; break; - case 3: ret = 'P'; break; - } - ret ^= 1; - dev->Geometry++; - dev->Geometry &= 0x03; - break; - } - break; - } - -#if 0 - x54x_log("%s: Read Port 0x%02X, Value %02X\n", dev->name, port, ret); -#endif - return(ret); -} - - -static uint16_t -x54x_inw(uint16_t port, void *priv) -{ - return((uint16_t) x54x_in(port, priv)); -} - - -static uint32_t -x54x_inl(uint16_t port, void *priv) -{ - return((uint32_t) x54x_in(port, priv)); -} - - -static uint8_t -x54x_read(uint32_t port, void *priv) -{ - return(x54x_in(port & 3, priv)); -} - - -static uint16_t -x54x_readw(uint32_t port, void *priv) -{ - return(x54x_inw(port & 3, priv)); -} - - -static uint32_t -x54x_readl(uint32_t port, void *priv) -{ - return(x54x_inl(port & 3, priv)); -} - - -static void -x54x_reset_poll(void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - - dev->Status = STAT_INIT | STAT_IDLE; - - dev->ResetCB = 0LL; -} - - -static void -x54x_reset(x54x_t *dev) -{ - int i; - - clear_irq(dev); - if (dev->int_geom_writable) - dev->Geometry = 0x80; - else - dev->Geometry = 0x00; - dev->callback_phase = 0; - dev->Command = 0xFF; - dev->CmdParam = 0; - dev->CmdParamLeft = 0; - dev->Mbx24bit = 1; - dev->MailboxInPosCur = 0; - dev->MailboxOutInterrupts = 0; - dev->PendingInterrupt = 0; - dev->IrqEnabled = 1; - dev->MailboxCount = 0; - dev->MailboxOutPosCur = 0; - - /* Reset all devices on controller reset. */ - for (i = 0; i < 16; i++) - scsi_device_reset(i); - - if (dev->ven_reset) - dev->ven_reset(dev); -} - - -void -x54x_reset_ctrl(x54x_t *dev, uint8_t Reset) -{ - /* Say hello! */ - x54x_log("%s %s (IO=0x%04X, IRQ=%d, DMA=%d, BIOS @%05lX) ID=%d\n", - dev->vendor, dev->name, dev->Base, dev->Irq, dev->DmaChannel, - dev->rom_addr, dev->HostID); - - x54x_reset(dev); - - if (Reset) { - dev->Status = STAT_STST; - dev->ResetCB = X54X_RESET_DURATION_US * TIMER_USEC; - } else { - dev->Status = STAT_INIT | STAT_IDLE; - } -} - - -static void -x54x_out(uint16_t port, uint8_t val, void *priv) -{ - ReplyInquireSetupInformation *ReplyISI; - x54x_t *dev = (x54x_t *)priv; - MailboxInit_t *mbi; - int i = 0; - BIOSCMD *cmd; - uint16_t cyl = 0; - int suppress = 0; - uint32_t FIFOBuf; - uint8_t reset; - addr24 Address; - uint8_t host_id = dev->HostID; - uint8_t irq = 0; - - x54x_log("%s: Write Port 0x%02X, Value %02X\n", dev->name, port, val); - - switch (port & 3) { - case 0: - if ((val & CTRL_HRST) || (val & CTRL_SRST)) { - reset = (val & CTRL_HRST); - x54x_log("Reset completed = %x\n", reset); - x54x_reset_ctrl(dev, reset); - x54x_log("Controller reset: "); - break; - } - - if (val & CTRL_SCRST) { - /* Reset all devices on SCSI bus reset. */ - for (i = 0; i < 16; i++) - scsi_device_reset(i); - } - - if (val & CTRL_IRST) { - clear_irq(dev); - x54x_log("Interrupt reset: "); - } - break; - - case 1: - /* Fast path for the mailbox execution command. */ - if ((val == CMD_START_SCSI) && (dev->Command == 0xff)) { - dev->MailboxReq++; - x54x_log("Start SCSI command: "); - return; - } - if (dev->ven_fast_cmds) { - if (dev->Command == 0xff) { - if (dev->ven_fast_cmds(dev, val)) - return; - } - } - - if (dev->Command == 0xff) { - dev->Command = val; - dev->CmdParam = 0; - dev->CmdParamLeft = 0; - - dev->Status &= ~(STAT_INVCMD | STAT_IDLE); - x54x_log("%s: Operation Code 0x%02X\n", dev->name, val); - switch (dev->Command) { - case CMD_MBINIT: - dev->CmdParamLeft = sizeof(MailboxInit_t); - break; - - case CMD_BIOSCMD: - dev->CmdParamLeft = 10; - break; - - case CMD_EMBOI: - case CMD_BUSON_TIME: - case CMD_BUSOFF_TIME: - case CMD_DMASPEED: - case CMD_RETSETUP: - case CMD_ECHO: - case CMD_OPTIONS: - dev->CmdParamLeft = 1; - break; - - case CMD_SELTIMEOUT: - dev->CmdParamLeft = 4; - break; - - case CMD_WRITE_CH2: - case CMD_READ_CH2: - dev->CmdParamLeft = 3; - break; - - default: - if (dev->get_ven_param_len) - dev->CmdParamLeft = dev->get_ven_param_len(dev); - break; - } - } else { - dev->CmdBuf[dev->CmdParam] = val; - dev->CmdParam++; - dev->CmdParamLeft--; - - if (dev->ven_cmd_phase1) - dev->ven_cmd_phase1(dev); - } - - if (! dev->CmdParamLeft) { - x54x_log("Running Operation Code 0x%02X\n", dev->Command); - switch (dev->Command) { - case CMD_NOP: /* No Operation */ - dev->DataReplyLeft = 0; - break; - - case CMD_MBINIT: /* mailbox initialization */ - dev->Mbx24bit = 1; - - mbi = (MailboxInit_t *)dev->CmdBuf; - - dev->MailboxInit = 1; - dev->MailboxCount = mbi->Count; - dev->MailboxOutAddr = ADDR_TO_U32(mbi->Address); - dev->MailboxInAddr = dev->MailboxOutAddr + (dev->MailboxCount * sizeof(Mailbox_t)); - - x54x_log("Initialize Mailbox: MBO=0x%08lx, MBI=0x%08lx, %d entries at 0x%08lx\n", - dev->MailboxOutAddr, - dev->MailboxInAddr, - mbi->Count, - ADDR_TO_U32(mbi->Address)); - - dev->Status &= ~STAT_INIT; - dev->DataReplyLeft = 0; - x54x_log("Mailbox init: "); - break; - - case CMD_BIOSCMD: /* execute BIOS */ - cmd = (BIOSCMD *)dev->CmdBuf; - if (!dev->lba_bios) { - /* 1640 uses LBA. */ - cyl = ((cmd->u.chs.cyl & 0xff) << 8) | ((cmd->u.chs.cyl >> 8) & 0xff); - cmd->u.chs.cyl = cyl; - } - if (dev->lba_bios) { - /* 1640 uses LBA. */ - x54x_log("BIOS LBA=%06lx (%lu)\n", - lba32_blk(cmd), - lba32_blk(cmd)); - } else { - cmd->u.chs.head &= 0xf; - cmd->u.chs.sec &= 0x1f; - x54x_log("BIOS CHS=%04X/%02X%02X\n", - cmd->u.chs.cyl, - cmd->u.chs.head, - cmd->u.chs.sec); - } - dev->DataBuf[0] = x54x_bios_command(dev, dev->max_id, cmd, (dev->lba_bios)?1:0); - x54x_log("BIOS Completion/Status Code %x\n", dev->DataBuf[0]); - dev->DataReplyLeft = 1; - break; - - case CMD_INQUIRY: /* Inquiry */ - memcpy(dev->DataBuf, dev->fw_rev, 4); - x54x_log("Adapter inquiry: %c %c %c %c\n", dev->fw_rev[0], dev->fw_rev[1], dev->fw_rev[2], dev->fw_rev[3]); - dev->DataReplyLeft = 4; - break; - - case CMD_EMBOI: /* enable MBO Interrupt */ - if (dev->CmdBuf[0] <= 1) { - dev->MailboxOutInterrupts = dev->CmdBuf[0]; - x54x_log("Mailbox out interrupts: %s\n", dev->MailboxOutInterrupts ? "ON" : "OFF"); - suppress = 1; - } else { - dev->Status |= STAT_INVCMD; - } - dev->DataReplyLeft = 0; - break; - - case CMD_SELTIMEOUT: /* Selection Time-out */ - dev->DataReplyLeft = 0; - break; - - case CMD_BUSON_TIME: /* bus-on time */ - dev->BusOnTime = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - x54x_log("Bus-on time: %d\n", dev->CmdBuf[0]); - break; - - case CMD_BUSOFF_TIME: /* bus-off time */ - dev->BusOffTime = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - x54x_log("Bus-off time: %d\n", dev->CmdBuf[0]); - break; - - case CMD_DMASPEED: /* DMA Transfer Rate */ - dev->ATBusSpeed = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - x54x_log("DMA transfer rate: %02X\n", dev->CmdBuf[0]); - break; - - case CMD_RETDEVS: /* return Installed Devices */ - memset(dev->DataBuf, 0x00, 8); - - if (dev->ven_get_host_id) - host_id = dev->ven_get_host_id(dev); - - for (i=0; i<8; i++) { - dev->DataBuf[i] = 0x00; - - /* Skip the HA .. */ - if (i == host_id) continue; - - /* TODO: Query device for LUN's. */ - if (scsi_device_present(i)) - dev->DataBuf[i] |= 1; - } - dev->DataReplyLeft = i; - break; - - case CMD_RETCONF: /* return Configuration */ - if (dev->ven_get_dma) - dev->DataBuf[0] = (1<ven_get_dma(dev)); - else - dev->DataBuf[0] = (1<DmaChannel); - - if (dev->ven_get_irq) - irq = dev->ven_get_irq(dev); - else - irq = dev->Irq; - - if (irq >= 9) - dev->DataBuf[1]=(1<<(irq-9)); - else - dev->DataBuf[1]=0; - if (dev->ven_get_host_id) - dev->DataBuf[2] = dev->ven_get_host_id(dev); - else - dev->DataBuf[2] = dev->HostID; - x54x_log("Configuration data: %02X %02X %02X\n", dev->DataBuf[0], dev->DataBuf[1], dev->DataBuf[2]); - dev->DataReplyLeft = 3; - break; - - case CMD_RETSETUP: /* return Setup */ - { - ReplyISI = (ReplyInquireSetupInformation *)dev->DataBuf; - memset(ReplyISI, 0x00, sizeof(ReplyInquireSetupInformation)); - - ReplyISI->uBusTransferRate = dev->ATBusSpeed; - ReplyISI->uPreemptTimeOnBus = dev->BusOnTime; - ReplyISI->uTimeOffBus = dev->BusOffTime; - ReplyISI->cMailbox = dev->MailboxCount; - U32_TO_ADDR(ReplyISI->MailboxAddress, dev->MailboxOutAddr); - - if (dev->get_ven_data) { - dev->get_ven_data(dev); - } - - dev->DataReplyLeft = dev->CmdBuf[0]; - x54x_log("Return Setup Information: %d (length: %i)\n", dev->CmdBuf[0], sizeof(ReplyInquireSetupInformation)); - } - break; - - case CMD_ECHO: /* ECHO data */ - dev->DataBuf[0] = dev->CmdBuf[0]; - dev->DataReplyLeft = 1; - break; - - case CMD_WRITE_CH2: /* write channel 2 buffer */ - dev->DataReplyLeft = 0; - Address.hi = dev->CmdBuf[0]; - Address.mid = dev->CmdBuf[1]; - Address.lo = dev->CmdBuf[2]; - FIFOBuf = ADDR_TO_U32(Address); - x54x_log("Adaptec LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); - DMAPageRead(FIFOBuf, dev->dma_buffer, 64); - break; - - case CMD_READ_CH2: /* write channel 2 buffer */ - dev->DataReplyLeft = 0; - Address.hi = dev->CmdBuf[0]; - Address.mid = dev->CmdBuf[1]; - Address.lo = dev->CmdBuf[2]; - FIFOBuf = ADDR_TO_U32(Address); - x54x_log("Adaptec LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); - DMAPageWrite(FIFOBuf, dev->dma_buffer, 64); - break; - - case CMD_OPTIONS: /* Set adapter options */ - if (dev->CmdParam == 1) - dev->CmdParamLeft = dev->CmdBuf[0]; - dev->DataReplyLeft = 0; - break; - - default: - if (dev->ven_cmds) - suppress = dev->ven_cmds(dev); - else { - dev->DataReplyLeft = 0; - dev->Status |= STAT_INVCMD; - } - break; - } - } - - if (dev->DataReplyLeft) - dev->Status |= STAT_DFULL; - else if (!dev->CmdParamLeft) - x54x_cmd_done(dev, suppress); - break; - - case 2: - if (dev->int_geom_writable) - dev->Interrupt = val; - break; - - case 3: - if (dev->int_geom_writable) - dev->Geometry = val; - break; - } -} - - -static void -x54x_outw(uint16_t port, uint16_t val, void *priv) -{ - x54x_out(port, val & 0xFF, priv); -} - - -static void -x54x_outl(uint16_t port, uint32_t val, void *priv) -{ - x54x_out(port, val & 0xFF, priv); -} - - -static void -x54x_write(uint32_t port, uint8_t val, void *priv) -{ - x54x_out(port & 3, val, priv); -} - - -static void -x54x_writew(uint32_t port, uint16_t val, void *priv) -{ - x54x_outw(port & 3, val, priv); -} - - -static void -x54x_writel(uint32_t port, uint32_t val, void *priv) -{ - x54x_outl(port & 3, val, priv); -} - - -void -x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len) -{ - int bit32 = 0; - - if (dev->bus & DEVICE_PCI) - bit32 = 1; - else if ((dev->bus & DEVICE_MCA) && dev->bit32) - bit32 = 1; - - if (bit32) { - x54x_log("x54x: [PCI] Setting I/O handler at %04X\n", base); - io_sethandler(base, len, - x54x_in, x54x_inw, x54x_inl, - x54x_out, x54x_outw, x54x_outl, dev); - } else { - x54x_log("x54x: [ISA] Setting I/O handler at %04X\n", base); - io_sethandler(base, len, - x54x_in, x54x_inw, NULL, - x54x_out, x54x_outw, NULL, dev); - } -} - - -void -x54x_io_remove(x54x_t *dev, uint32_t base, uint8_t len) -{ - int bit32 = 0; - - if (dev->bus & DEVICE_PCI) - bit32 = 1; - else if ((dev->bus & DEVICE_MCA) && dev->bit32) - bit32 = 1; - - x54x_log("x54x: Removing I/O handler at %04X\n", base); - - if (bit32) { - io_removehandler(base, len, - x54x_in, x54x_inw, x54x_inl, - x54x_out, x54x_outw, x54x_outl, dev); - } else { - io_removehandler(base, len, - x54x_in, x54x_inw, NULL, - x54x_out, x54x_outw, NULL, dev); - } -} - - -void -x54x_mem_init(x54x_t *dev, uint32_t addr) -{ - int bit32 = 0; - - if (dev->bus & DEVICE_PCI) - bit32 = 1; - else if ((dev->bus & DEVICE_MCA) && dev->bit32) - bit32 = 1; - - if (bit32) { - mem_mapping_add(&dev->mmio_mapping, addr, 0x20, - x54x_read, x54x_readw, x54x_readl, - x54x_write, x54x_writew, x54x_writel, - NULL, MEM_MAPPING_EXTERNAL, dev); - } else { - mem_mapping_add(&dev->mmio_mapping, addr, 0x20, - x54x_read, x54x_readw, NULL, - x54x_write, x54x_writew, NULL, - NULL, MEM_MAPPING_EXTERNAL, dev); - } -} - - -void -x54x_mem_enable(x54x_t *dev) -{ - mem_mapping_enable(&dev->mmio_mapping); -} - - -void -x54x_mem_set_addr(x54x_t *dev, uint32_t base) -{ - mem_mapping_set_addr(&dev->mmio_mapping, base, 0x20); -} - - -void -x54x_mem_disable(x54x_t *dev) -{ - mem_mapping_disable(&dev->mmio_mapping); -} - - -/* General initialization routine for all boards. */ -void * -x54x_init(const device_t *info) -{ - x54x_t *dev; - - /* Allocate control block and set up basic stuff. */ - dev = malloc(sizeof(x54x_t)); - if (dev == NULL) return(dev); - memset(dev, 0x00, sizeof(x54x_t)); - dev->type = info->local; - - dev->bus = info->flags; - dev->callback_phase = 0; - - timer_add(x54x_reset_poll, &dev->ResetCB, &dev->ResetCB, dev); - dev->timer_period = 10LL * TIMER_USEC; - timer_add(x54x_cmd_callback, &dev->timer_period, TIMER_ALWAYS_ENABLED, dev); - - x54x_dev = dev; - - return(dev); -} - - -void -x54x_close(void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - - if (dev) { - x54x_dev = NULL; - - /* Tell the timer to terminate. */ - dev->timer_period = 0LL; - - dev->MailboxInit = dev->BIOSMailboxInit = 0; - dev->MailboxCount = dev->BIOSMailboxCount = 0; - dev->MailboxReq = dev->BIOSMailboxReq = 0; - - if (dev->ven_data) - free(dev->ven_data); - - if (dev->nvr != NULL) - free(dev->nvr); - - free(dev); - dev = NULL; - } -} - - -void -x54x_device_reset(void *priv) -{ - x54x_t *dev = (x54x_t *)priv; - - x54x_reset_ctrl(dev, 1); - - dev->ResetCB = 0LL; - dev->Status = STAT_IDLE | STAT_INIT; -} diff --git a/src/scsi - Cópia/scsi_x54x.h b/src/scsi - Cópia/scsi_x54x.h deleted file mode 100644 index 13699a181..000000000 --- a/src/scsi - Cópia/scsi_x54x.h +++ /dev/null @@ -1,510 +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. - * - * Header of the code common to the AHA-154x series of SCSI - * Host Adapters made by Adaptec, Inc. and the BusLogic series - * of SCSI Host Adapters made by Mylex. - * These controllers were designed for various buses. - * - * Version: @(#)scsi_x54x.h 1.0.7 2018/04/06 - * - * Authors: TheCollector1995, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#ifndef SCSI_X54X_H - -#define SCSI_X54X_H - -#define SCSI_DELAY_TM 1 /* was 50 */ - - -#define ROM_SIZE 16384 /* one ROM is 16K */ -#define NVR_SIZE 256 /* size of NVR */ - - -/* EEPROM map and bit definitions. */ -#define EE0_HOSTID 0x07 /* EE(0) [2:0] */ -#define EE0_ALTFLOP 0x80 /* EE(0) [7] FDC at 370h */ -#define EE1_IRQCH 0x07 /* EE(1) [3:0] */ -#define EE1_DMACH 0x70 /* EE(1) [7:4] */ -#define EE2_RMVOK 0x01 /* EE(2) [0] Support removable disks */ -#define EE2_HABIOS 0x02 /* EE(2) [1] HA Bios Space Reserved */ -#define EE2_INT19 0x04 /* EE(2) [2] HA Bios Controls INT19 */ -#define EE2_DYNSCAN 0x08 /* EE(2) [3] Dynamically scan bus */ -#define EE2_TWODRV 0x10 /* EE(2) [4] Allow more than 2 drives */ -#define EE2_SEEKRET 0x20 /* EE(2) [5] Immediate return on seek */ -#define EE2_EXT1G 0x80 /* EE(2) [7] Extended Translation >1GB */ -#define EE3_SPEED 0x00 /* EE(3) [7:0] DMA Speed */ -#define SPEED_33 0xFF -#define SPEED_50 0x00 -#define SPEED_56 0x04 -#define SPEED_67 0x01 -#define SPEED_80 0x02 -#define SPEED_10 0x03 -#define EE4_FLOPTOK 0x80 /* EE(4) [7] Support Flopticals */ -#define EE6_PARITY 0x01 /* EE(6) [0] parity check enable */ -#define EE6_TERM 0x02 /* EE(6) [1] host term enable */ -#define EE6_RSTBUS 0x04 /* EE(6) [2] reset SCSI bus on boot */ -#define EEE_SYNC 0x01 /* EE(E) [0] Enable Sync Negotiation */ -#define EEE_DISCON 0x02 /* EE(E) [1] Enable Disconnection */ -#define EEE_FAST 0x04 /* EE(E) [2] Enable FAST SCSI */ -#define EEE_START 0x08 /* EE(E) [3] Enable Start Unit */ - - -/* - * Host Adapter I/O ports. - * - * READ Port x+0: STATUS - * WRITE Port x+0: CONTROL - * - * READ Port x+1: DATA - * WRITE Port x+1: COMMAND - * - * READ Port x+2: INTERRUPT STATUS - * WRITE Port x+2: (undefined?) - * - * R/W Port x+3: (undefined) - */ - -/* WRITE CONTROL commands. */ -#define CTRL_HRST 0x80 /* Hard reset */ -#define CTRL_SRST 0x40 /* Soft reset */ -#define CTRL_IRST 0x20 /* interrupt reset */ -#define CTRL_SCRST 0x10 /* SCSI bus reset */ - -/* READ STATUS. */ -#define STAT_STST 0x80 /* self-test in progress */ -#define STAT_DFAIL 0x40 /* internal diagnostic failure */ -#define STAT_INIT 0x20 /* mailbox initialization required */ -#define STAT_IDLE 0x10 /* HBA is idle */ -#define STAT_CDFULL 0x08 /* Command/Data output port is full */ -#define STAT_DFULL 0x04 /* Data input port is full */ -#define STAT_INVCMD 0x01 /* Invalid command */ - -/* READ/WRITE DATA. */ -#define CMD_NOP 0x00 /* No operation */ -#define CMD_MBINIT 0x01 /* mailbox initialization */ -#define CMD_START_SCSI 0x02 /* Start SCSI command */ -#define CMD_BIOSCMD 0x03 /* Execute ROM BIOS command */ -#define CMD_INQUIRY 0x04 /* Adapter inquiry */ -#define CMD_EMBOI 0x05 /* enable Mailbox Out Interrupt */ -#define CMD_SELTIMEOUT 0x06 /* Set SEL timeout */ -#define CMD_BUSON_TIME 0x07 /* set bus-On time */ -#define CMD_BUSOFF_TIME 0x08 /* set bus-off time */ -#define CMD_DMASPEED 0x09 /* set ISA DMA speed */ -#define CMD_RETDEVS 0x0A /* return installed devices */ -#define CMD_RETCONF 0x0B /* return configuration data */ -#define CMD_TARGET 0x0C /* set HBA to target mode */ -#define CMD_RETSETUP 0x0D /* return setup data */ -#define CMD_WRITE_CH2 0x1A /* write channel 2 buffer */ -#define CMD_READ_CH2 0x1B /* read channel 2 buffer */ -#define CMD_ECHO 0x1F /* ECHO command data */ -#define CMD_OPTIONS 0x21 /* set adapter options */ - -/* READ INTERRUPT STATUS. */ -#define INTR_ANY 0x80 /* any interrupt */ -#define INTR_SRCD 0x08 /* SCSI reset detected */ -#define INTR_HACC 0x04 /* HA command complete */ -#define INTR_MBOA 0x02 /* MBO empty */ -#define INTR_MBIF 0x01 /* MBI full */ - - -/* Structure for the INQUIRE_SETUP_INFORMATION reply. */ -#pragma pack(push,1) -typedef struct { - uint8_t uOffset :4, - uTransferPeriod :3, - fSynchronous :1; -} ReplyInquireSetupInformationSynchronousValue; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t fSynchronousInitiationEnabled :1, - fParityCheckingEnabled :1, - uReserved1 :6; - uint8_t uBusTransferRate; - uint8_t uPreemptTimeOnBus; - uint8_t uTimeOffBus; - uint8_t cMailbox; - addr24 MailboxAddress; - ReplyInquireSetupInformationSynchronousValue SynchronousValuesId0To7[8]; - uint8_t uDisconnectPermittedId0To7; - uint8_t VendorSpecificData[28]; -} ReplyInquireSetupInformation; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Count; - addr24 Address; -} MailboxInit_t; -#pragma pack(pop) - -/* - * Mailbox Definitions. - * - * Mailbox Out (MBO) command values. - */ -#define MBO_FREE 0x00 -#define MBO_START 0x01 -#define MBO_ABORT 0x02 - -/* Mailbox In (MBI) status values. */ -#define MBI_FREE 0x00 -#define MBI_SUCCESS 0x01 -#define MBI_ABORT 0x02 -#define MBI_NOT_FOUND 0x03 -#define MBI_ERROR 0x04 - -#pragma pack(push,1) -typedef struct { - uint8_t CmdStatus; - addr24 CCBPointer; -} Mailbox_t; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint32_t CCBPointer; - union { - struct { - uint8_t Reserved[3]; - uint8_t ActionCode; - } out; - struct { - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Reserved; - uint8_t CompletionCode; - } in; - } u; -} Mailbox32_t; -#pragma pack(pop) - -/* - * - * CCB - SCSI Command Control Block - * - * The CCB is a superset of the CDB (Command Descriptor Block) - * and specifies detailed information about a SCSI command. - * - */ -/* Byte 0 Command Control Block Operation Code */ -#define SCSI_INITIATOR_COMMAND 0x00 -#define TARGET_MODE_COMMAND 0x01 -#define SCATTER_GATHER_COMMAND 0x02 -#define SCSI_INITIATOR_COMMAND_RES 0x03 -#define SCATTER_GATHER_COMMAND_RES 0x04 -#define BUS_RESET 0x81 - -/* Byte 1 Address and Direction Control */ -#define CCB_TARGET_ID_SHIFT 0x06 /* CCB Op Code = 00, 02 */ -#define CCB_INITIATOR_ID_SHIFT 0x06 /* CCB Op Code = 01 */ -#define CCB_DATA_XFER_IN 0x01 -#define CCB_DATA_XFER_OUT 0x02 -#define CCB_LUN_MASK 0x07 /* Logical Unit Number */ - -/* Byte 2 SCSI_Command_Length - Length of SCSI CDB - Byte 3 Request Sense Allocation Length */ -#define FOURTEEN_BYTES 0x00 /* Request Sense Buffer size */ -#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ - -/* Bytes 4, 5 and 6 Data Length - Data transfer byte count */ -/* Bytes 7, 8 and 9 Data Pointer - SGD List or Data Buffer */ -/* Bytes 10, 11 and 12 Link Pointer - Next CCB in Linked List */ -/* Byte 13 Command Link ID - TBD (I don't know yet) */ -/* Byte 14 Host Status - Host Adapter status */ -#define CCB_COMPLETE 0x00 /* CCB completed without error */ -#define CCB_LINKED_COMPLETE 0x0A /* Linked command completed */ -#define CCB_LINKED_COMPLETE_INT 0x0B /* Linked complete with intr */ -#define CCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ -#define CCB_DATA_OVER_UNDER_RUN 0x12 -#define CCB_UNEXPECTED_BUS_FREE 0x13 /* Trg dropped SCSI BSY */ -#define CCB_PHASE_SEQUENCE_FAIL 0x14 /* Trg bus phase sequence fail */ -#define CCB_BAD_MBO_COMMAND 0x15 /* MBO command not 0, 1 or 2 */ -#define CCB_INVALID_OP_CODE 0x16 /* CCB invalid operation code */ -#define CCB_BAD_LINKED_LUN 0x17 /* Linked CCB LUN diff from 1st */ -#define CCB_INVALID_DIRECTION 0x18 /* Invalid target direction */ -#define CCB_DUPLICATE_CCB 0x19 /* Duplicate CCB */ -#define CCB_INVALID_CCB 0x1A /* Invalid CCB - bad parameter */ - -/* Byte 15 Target Status - - See scsi.h files for these statuses. - Bytes 16 and 17 Reserved (must be 0) - Bytes 18 through 18+n-1, where n=size of CDB Command Descriptor Block */ - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Reserved1 :3, - ControlByte :2, - TagQueued :1, - QueueTag :2; - uint8_t CdbLength; - uint8_t RequestSenseLength; - uint32_t DataLength; - uint32_t DataPointer; - uint8_t Reserved2[2]; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Id; - uint8_t Lun :5, - LegacyTagEnable :1, - LegacyQueueTag :2; - uint8_t Cdb[12]; - uint8_t Reserved3[6]; - uint32_t SensePointer; -} CCB32; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Lun :3, - ControlByte :2, - Id :3; - uint8_t CdbLength; - uint8_t RequestSenseLength; - addr24 DataLength; - addr24 DataPointer; - addr24 LinkPointer; - uint8_t LinkId; - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Reserved[2]; - uint8_t Cdb[12]; -} CCB; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - uint8_t Opcode; - uint8_t Pad1 :3, - ControlByte :2, - Pad2 :3; - uint8_t CdbLength; - uint8_t RequestSenseLength; - uint8_t Pad3[9]; - uint8_t CompletionCode; /* Only used by the 1542C/CF(/CP?) BIOS mailboxes */ - uint8_t HostStatus; - uint8_t TargetStatus; - uint8_t Pad4[2]; - uint8_t Cdb[12]; -} CCBC; -#pragma pack(pop) - -#pragma pack(push,1) -typedef union { - CCB32 new; - CCB old; - CCBC common; -} CCBU; -#pragma pack(pop) - -#pragma pack(push,1) -typedef struct { - CCBU CmdBlock; - uint8_t *RequestSenseBuffer; - uint32_t CCBPointer; - int Is24bit; - uint8_t TargetID, - LUN, - HostStatus, - TargetStatus, - MailboxCompletionCode; -} Req_t; -#pragma pack(pop) - -typedef struct { - int8_t type; /* type of device */ - - char vendor[16]; /* name of device vendor */ - char name[16]; /* name of device */ - - int64_t timer_period, temp_period; - uint8_t callback_phase; - int64_t media_period; - double ha_bps; /* bytes per second */ - - int8_t Irq; - uint8_t IrqEnabled; - - int8_t DmaChannel; - int8_t HostID; - uint32_t Base; - uint8_t pos_regs[8]; /* MCA */ - - wchar_t *bios_path; /* path to BIOS image file */ - uint32_t rom_addr; /* address of BIOS ROM */ - uint16_t rom_ioaddr; /* offset in BIOS of I/O addr */ - uint16_t rom_shram; /* index to shared RAM */ - uint16_t rom_shramsz; /* size of shared RAM */ - uint16_t rom_fwhigh; /* offset in BIOS of ver ID */ - rom_t bios; /* BIOS memory descriptor */ - rom_t uppersck; /* BIOS memory descriptor */ - uint8_t *rom1; /* main BIOS image */ - uint8_t *rom2; /* SCSI-Select image */ - - wchar_t *nvr_path; /* path to NVR image file */ - uint8_t *nvr; /* EEPROM buffer */ - - int64_t ResetCB; - - volatile uint8_t /* for multi-threading, keep */ - Status, /* these volatile */ - Interrupt; - - Req_t Req; - uint8_t Geometry; - uint8_t Control; - uint8_t Command; - uint8_t CmdBuf[128]; - uint8_t CmdParam; - uint32_t CmdParamLeft; - uint8_t DataBuf[65536]; - uint16_t DataReply; - uint16_t DataReplyLeft; - - volatile uint32_t - MailboxInit, - MailboxCount, - MailboxOutAddr, - MailboxOutPosCur, - MailboxInAddr, - MailboxInPosCur, - MailboxReq; - - volatile int - Mbx24bit, - MailboxOutInterrupts; - - volatile int - PendingInterrupt, - Lock; - - uint8_t shadow_ram[128]; - - volatile uint8_t - MailboxIsBIOS, - ToRaise; - - uint8_t shram_mode; - - uint8_t sync; - uint8_t parity; - - uint8_t dma_buffer[128]; - - volatile - uint32_t BIOSMailboxInit, - BIOSMailboxCount, - BIOSMailboxOutAddr, - BIOSMailboxOutPosCur, - BIOSMailboxReq, - Residue; - - uint8_t BusOnTime, - BusOffTime, - ATBusSpeed; - - char *fw_rev; /* The 4 bytes of the revision command information + 2 extra bytes for BusLogic */ - uint16_t bus; /* Basically a copy of device flags */ - uint8_t setup_info_len; - uint8_t max_id; - uint8_t pci_slot; - uint8_t bit32; - uint8_t lba_bios; - - mem_mapping_t mmio_mapping; - - uint8_t int_geom_writable; - uint8_t cdrom_boot; - - /* Pointer to a structure of vendor-specific data that only the vendor-specific code can understand */ - void *ven_data; - - /* Pointer to a function that performs vendor-specific operation during the timer callback */ - void (*ven_callback)(void *p); - /* Pointer to a function that executes the second parameter phase of the vendor-specific command */ - void (*ven_cmd_phase1)(void *p); - /* Pointer to a function that gets the host adapter ID in case it has to be read from a non-standard location */ - uint8_t (*ven_get_host_id)(void *p); - /* Pointer to a function that updates the IRQ in the vendor-specific space */ - uint8_t (*ven_get_irq)(void *p); - /* Pointer to a function that updates the DMA channel in the vendor-specific space */ - uint8_t (*ven_get_dma)(void *p); - /* Pointer to a function that returns whether command is fast */ - uint8_t (*ven_cmd_is_fast)(void *p); - /* Pointer to a function that executes vendor-specific fast path commands */ - uint8_t (*ven_fast_cmds)(void *p, uint8_t cmd); - /* Pointer to a function that gets the parameter length for vendor-specific commands */ - uint8_t (*get_ven_param_len)(void *p); - /* Pointer to a function that executes vendor-specific commands and returns whether or not to suppress the IRQ */ - uint8_t (*ven_cmds)(void *p); - /* Pointer to a function that fills in the vendor-specific setup data */ - void (*get_ven_data)(void *p); - /* Pointer to a function that determines if the mode is aggressive */ - uint8_t (*is_aggressive_mode)(void *p); - /* Pointer to a function that returns interrupt type (0 = edge, 1 = level) */ - uint8_t (*interrupt_type)(void *p); - /* Pointer to a function that resets vendor-specific data */ - void (*ven_reset)(void *p); -} x54x_t; - - -#pragma pack(push,1) -typedef struct -{ - uint8_t command; - uint8_t lun:3, - reserved:2, - id:3; - union { - struct { - uint16_t cyl; - uint8_t head; - uint8_t sec; - } chs; - struct { - uint8_t lba0; /* MSB */ - uint8_t lba1; - uint8_t lba2; - uint8_t lba3; /* LSB */ - } lba; - } u; - uint8_t secount; - addr24 dma_address; -} BIOSCMD; -#pragma pack(pop) -#define lba32_blk(p) ((uint32_t)(p->u.lba.lba0<<24) | (p->u.lba.lba1<<16) | \ - (p->u.lba.lba2<<8) | p->u.lba.lba3) - - -extern void x54x_reset_ctrl(x54x_t *dev, uint8_t Reset); -extern void x54x_buf_alloc(uint8_t id, int length); -extern void x54x_buf_free(uint8_t id); -extern uint8_t x54x_mbo_process(x54x_t *dev); -extern void x54x_wait_for_poll(void); -extern void x54x_io_set(x54x_t *dev, uint32_t base, uint8_t len); -extern void x54x_io_remove(x54x_t *dev, uint32_t base, uint8_t len); -extern void x54x_mem_init(x54x_t *dev, uint32_t addr); -extern void x54x_mem_enable(x54x_t *dev); -extern void x54x_mem_set_addr(x54x_t *dev, uint32_t base); -extern void x54x_mem_disable(x54x_t *dev); -extern void *x54x_init(const device_t *info); -extern void x54x_close(void *priv); -extern void x54x_device_reset(void *priv); - - -#endif diff --git a/src/video/startblit.fnd b/src/video/startblit.fnd deleted file mode 100644 index 892d57e1a..000000000 --- a/src/video/startblit.fnd +++ /dev/null @@ -1,176 +0,0 @@ - ----------- STARTBLIT.FND - ----------- VIDEO.C - ----------- VIDEO.H - ----------- VID_ATI18800.C - ----------- VID_ATI18800.H - ----------- VID_ATI28800.C - ----------- VID_ATI28800.H - ----------- VID_ATI68860_RAMDAC.C - ----------- VID_ATI68860_RAMDAC.H - ----------- VID_ATI_EEPROM.C - ----------- VID_ATI_EEPROM.H - ----------- VID_ATI_MACH64.C - ----------- VID_ATI_MACH64.H - ----------- VID_BT485_RAMDAC.C - ----------- VID_BT485_RAMDAC.H - ----------- VID_CGA.C - ----------- VID_CGA.H - ----------- VID_CGA_COMP.C - ----------- VID_CGA_COMP.H - ----------- VID_CL54XX.C - ----------- VID_CL54XX.H - ----------- VID_COLORPLUS.C - ----------- VID_COLORPLUS.H - ----------- VID_COMPAQ_CGA.C - ----------- VID_COMPAQ_CGA.H - ----------- VID_EGA.C - ----------- VID_EGA.H - ----------- VID_EGA_RENDER.C - ----------- VID_EGA_RENDER.H - ----------- VID_ET4000.C - ----------- VID_ET4000.H - ----------- VID_ET4000W32.C - ----------- VID_ET4000W32.H - ----------- VID_ET4000W32I.C - ----------- VID_GENIUS.C - ----------- VID_GENIUS.H - ----------- VID_HERCULES.C - ----------- VID_HERCULES.H - ----------- VID_HERCULESPLUS.C - ----------- VID_HERCULESPLUS.H - ----------- VID_ICD2061.C - ----------- VID_ICD2061.H - ----------- VID_ICS2595.C - ----------- VID_ICS2595.H - ----------- VID_INCOLOR.C - ----------- VID_INCOLOR.H - ----------- VID_MDA.C - ----------- VID_MDA.H - ----------- VID_NVIDIA.C - ----------- VID_NVIDIA.H - ----------- VID_NV_RIVA128.C - ----------- VID_NV_RIVA128.H - ----------- VID_OAK_OTI.C - ----------- VID_OAK_OTI.H - ----------- VID_PARADISE.C - ----------- VID_PARADISE.H - ----------- VID_S3.C - ----------- VID_S3.H - ----------- VID_S3_VIRGE.C - ----------- VID_S3_VIRGE.H - ----------- VID_SC1502X_RAMDAC.C - ----------- VID_SC1502X_RAMDAC.H - ----------- VID_SDAC_RAMDAC.C - ----------- VID_SDAC_RAMDAC.H - ----------- VID_STG_RAMDAC.C - ----------- VID_STG_RAMDAC.H - ----------- VID_SVGA.C - ----------- VID_SVGA.H - ----------- VID_SVGA_RENDER.C - ----------- VID_SVGA_RENDER.H - ----------- VID_TABLE.C - ----------- VID_TGUI9440.C - ----------- VID_TGUI9440.H - ----------- VID_TI_CF62011.C - ----------- VID_TI_CF62011.H - ----------- VID_TKD8001_RAMDAC.C - ----------- VID_TKD8001_RAMDAC.H - ----------- VID_TVGA.C - ----------- VID_TVGA.H - ----------- VID_VGA.C - ----------- VID_VGA.H - ----------- VID_VOODOO.C - ----------- VID_VOODOO.H - ----------- VID_VOODOO_CODEGEN_X86-64.H - ----------- VID_VOODOO_CODEGEN_X86.H - ----------- VID_VOODOO_DITHER.H - ----------- VID_WY700.C - ----------- VID_WY700.H diff --git a/src/video/vid_ati68860_ramdac - Cópia (2).c b/src/video/vid_ati68860_ramdac - Cópia (2).c deleted file mode 100644 index 89a9827d3..000000000 --- a/src/video/vid_ati68860_ramdac - Cópia (2).c +++ /dev/null @@ -1,197 +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. - * - * ATI 68860 RAMDAC emulation (for Mach64) - * - * ATI 68860/68880 Truecolor DACs: - * REG08 (R/W): - * bit 0-? Always 2 ?? - * - * REG0A (R/W): - * bit 0-? Always 1Dh ?? - * - * REG0B (R/W): (GMR ?) - * bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp, - * A0h: 15bpp, A1h: 16bpp, C0h: 24bpp, - * E3h: 32bpp (80h for VGA modes ?) - * - * REG0C (R/W): Device Setup Register A - * bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT - * 2-3 Depends on Video memory (= VRAM width ?) . - * 1: Less than 1Mb, 2: 1Mb, 3: > 1Mb - * 5-6 Always set ? - * 7 If set can remove "snow" in some cases - * (A860_Delay_L ?) ?? - * - * Version: @(#)vid_ati68860.c 1.0.3 2017/11/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../mem.h" -#include "video.h" -#include "vid_svga.h" -#include "vid_ati68860_ramdac.h" -#include "vid_svga_render.h" - - -void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga) -{ - switch (addr) - { - case 0: - svga_out(0x3c8, val, svga); - break; - case 1: - svga_out(0x3c9, val, svga); - break; - case 2: - svga_out(0x3c6, val, svga); - break; - case 3: - svga_out(0x3c7, val, svga); - break; - default: - ramdac->regs[addr & 0xf] = val; - switch (addr & 0xf) - { - case 0x4: - ramdac->dac_write = val; - ramdac->dac_pos = 0; - break; - case 0x5: - switch (ramdac->dac_pos) - { - case 0: - ramdac->dac_r = val; - ramdac->dac_pos++; - break; - case 1: - ramdac->dac_g = val; - ramdac->dac_pos++; - break; - case 2: - if (ramdac->dac_write > 1) - break; - ramdac->pal[ramdac->dac_write].r = ramdac->dac_r; - ramdac->pal[ramdac->dac_write].g = ramdac->dac_g; - ramdac->pal[ramdac->dac_write].b = val; - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[ramdac->dac_write] = makecol32(ramdac->pal[ramdac->dac_write].r, ramdac->pal[ramdac->dac_write].g, ramdac->pal[ramdac->dac_write].b); - else - ramdac->pallook[ramdac->dac_write] = makecol32((ramdac->pal[ramdac->dac_write].r & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].g & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].b & 0x3f) * 4); - ramdac->dac_pos = 0; - ramdac->dac_write = (ramdac->dac_write + 1) & 255; - break; - } - break; - - case 0xb: - switch (val) - { - case 0x82: - ramdac->render = svga_render_4bpp_highres; - break; - case 0x83: - ramdac->render = svga_render_8bpp_highres; - break; - case 0xa0: case 0xb0: - ramdac->render = svga_render_15bpp_highres; - break; - case 0xa1: case 0xb1: - ramdac->render = svga_render_16bpp_highres; - break; - case 0xc0: case 0xd0: - ramdac->render = svga_render_24bpp_highres; - break; - case 0xe2: case 0xf7: - ramdac->render = svga_render_32bpp_highres; - break; - case 0xe3: - ramdac->render = svga_render_ABGR8888_highres; - break; - case 0xf2: - ramdac->render = svga_render_RGBA8888_highres; - break; - default: - ramdac->render = svga_render_8bpp_highres; - break; - } - break; - case 0xc: - svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT); - break; - } - break; - } -} - -uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga) -{ - uint8_t ret = 0; - switch (addr) - { - case 0: - ret = svga_in(0x3c8, svga); - break; - case 1: - ret = svga_in(0x3c9, svga); - break; - case 2: - ret = svga_in(0x3c6, svga); - break; - case 3: - ret = svga_in(0x3c7, svga); - break; - case 4: case 8: - ret = 2; - break; - case 6: case 0xa: - ret = 0x1d; - break; - case 0xf: - ret = 0xd0; - break; - - default: - ret = ramdac->regs[addr & 0xf]; - break; - } - return ret; -} - -void ati68860_ramdac_init(ati68860_ramdac_t *ramdac) -{ - ramdac->render = svga_render_8bpp_highres; -} - -void ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type) -{ - int c; - - if (ramdac->ramdac_type != type) - { - ramdac->ramdac_type = type; - - for (c = 0; c < 2; c++) - { - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g, ramdac->pal[c].b); - else - ramdac->pallook[c] = makecol32((ramdac->pal[c].r & 0x3f) * 4, (ramdac->pal[c].g & 0x3f) * 4, (ramdac->pal[c].b & 0x3f) * 4); - } - } -} diff --git a/src/video/vid_ati68860_ramdac - Cópia (3).c b/src/video/vid_ati68860_ramdac - Cópia (3).c deleted file mode 100644 index 89a9827d3..000000000 --- a/src/video/vid_ati68860_ramdac - Cópia (3).c +++ /dev/null @@ -1,197 +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. - * - * ATI 68860 RAMDAC emulation (for Mach64) - * - * ATI 68860/68880 Truecolor DACs: - * REG08 (R/W): - * bit 0-? Always 2 ?? - * - * REG0A (R/W): - * bit 0-? Always 1Dh ?? - * - * REG0B (R/W): (GMR ?) - * bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp, - * A0h: 15bpp, A1h: 16bpp, C0h: 24bpp, - * E3h: 32bpp (80h for VGA modes ?) - * - * REG0C (R/W): Device Setup Register A - * bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT - * 2-3 Depends on Video memory (= VRAM width ?) . - * 1: Less than 1Mb, 2: 1Mb, 3: > 1Mb - * 5-6 Always set ? - * 7 If set can remove "snow" in some cases - * (A860_Delay_L ?) ?? - * - * Version: @(#)vid_ati68860.c 1.0.3 2017/11/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../mem.h" -#include "video.h" -#include "vid_svga.h" -#include "vid_ati68860_ramdac.h" -#include "vid_svga_render.h" - - -void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga) -{ - switch (addr) - { - case 0: - svga_out(0x3c8, val, svga); - break; - case 1: - svga_out(0x3c9, val, svga); - break; - case 2: - svga_out(0x3c6, val, svga); - break; - case 3: - svga_out(0x3c7, val, svga); - break; - default: - ramdac->regs[addr & 0xf] = val; - switch (addr & 0xf) - { - case 0x4: - ramdac->dac_write = val; - ramdac->dac_pos = 0; - break; - case 0x5: - switch (ramdac->dac_pos) - { - case 0: - ramdac->dac_r = val; - ramdac->dac_pos++; - break; - case 1: - ramdac->dac_g = val; - ramdac->dac_pos++; - break; - case 2: - if (ramdac->dac_write > 1) - break; - ramdac->pal[ramdac->dac_write].r = ramdac->dac_r; - ramdac->pal[ramdac->dac_write].g = ramdac->dac_g; - ramdac->pal[ramdac->dac_write].b = val; - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[ramdac->dac_write] = makecol32(ramdac->pal[ramdac->dac_write].r, ramdac->pal[ramdac->dac_write].g, ramdac->pal[ramdac->dac_write].b); - else - ramdac->pallook[ramdac->dac_write] = makecol32((ramdac->pal[ramdac->dac_write].r & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].g & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].b & 0x3f) * 4); - ramdac->dac_pos = 0; - ramdac->dac_write = (ramdac->dac_write + 1) & 255; - break; - } - break; - - case 0xb: - switch (val) - { - case 0x82: - ramdac->render = svga_render_4bpp_highres; - break; - case 0x83: - ramdac->render = svga_render_8bpp_highres; - break; - case 0xa0: case 0xb0: - ramdac->render = svga_render_15bpp_highres; - break; - case 0xa1: case 0xb1: - ramdac->render = svga_render_16bpp_highres; - break; - case 0xc0: case 0xd0: - ramdac->render = svga_render_24bpp_highres; - break; - case 0xe2: case 0xf7: - ramdac->render = svga_render_32bpp_highres; - break; - case 0xe3: - ramdac->render = svga_render_ABGR8888_highres; - break; - case 0xf2: - ramdac->render = svga_render_RGBA8888_highres; - break; - default: - ramdac->render = svga_render_8bpp_highres; - break; - } - break; - case 0xc: - svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT); - break; - } - break; - } -} - -uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga) -{ - uint8_t ret = 0; - switch (addr) - { - case 0: - ret = svga_in(0x3c8, svga); - break; - case 1: - ret = svga_in(0x3c9, svga); - break; - case 2: - ret = svga_in(0x3c6, svga); - break; - case 3: - ret = svga_in(0x3c7, svga); - break; - case 4: case 8: - ret = 2; - break; - case 6: case 0xa: - ret = 0x1d; - break; - case 0xf: - ret = 0xd0; - break; - - default: - ret = ramdac->regs[addr & 0xf]; - break; - } - return ret; -} - -void ati68860_ramdac_init(ati68860_ramdac_t *ramdac) -{ - ramdac->render = svga_render_8bpp_highres; -} - -void ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type) -{ - int c; - - if (ramdac->ramdac_type != type) - { - ramdac->ramdac_type = type; - - for (c = 0; c < 2; c++) - { - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g, ramdac->pal[c].b); - else - ramdac->pallook[c] = makecol32((ramdac->pal[c].r & 0x3f) * 4, (ramdac->pal[c].g & 0x3f) * 4, (ramdac->pal[c].b & 0x3f) * 4); - } - } -} diff --git a/src/video/vid_ati68860_ramdac - Cópia.c b/src/video/vid_ati68860_ramdac - Cópia.c deleted file mode 100644 index 89a9827d3..000000000 --- a/src/video/vid_ati68860_ramdac - Cópia.c +++ /dev/null @@ -1,197 +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. - * - * ATI 68860 RAMDAC emulation (for Mach64) - * - * ATI 68860/68880 Truecolor DACs: - * REG08 (R/W): - * bit 0-? Always 2 ?? - * - * REG0A (R/W): - * bit 0-? Always 1Dh ?? - * - * REG0B (R/W): (GMR ?) - * bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp, - * A0h: 15bpp, A1h: 16bpp, C0h: 24bpp, - * E3h: 32bpp (80h for VGA modes ?) - * - * REG0C (R/W): Device Setup Register A - * bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT - * 2-3 Depends on Video memory (= VRAM width ?) . - * 1: Less than 1Mb, 2: 1Mb, 3: > 1Mb - * 5-6 Always set ? - * 7 If set can remove "snow" in some cases - * (A860_Delay_L ?) ?? - * - * Version: @(#)vid_ati68860.c 1.0.3 2017/11/04 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2017 Sarah Walker. - * Copyright 2016,2017 Miran Grca. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../mem.h" -#include "video.h" -#include "vid_svga.h" -#include "vid_ati68860_ramdac.h" -#include "vid_svga_render.h" - - -void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga) -{ - switch (addr) - { - case 0: - svga_out(0x3c8, val, svga); - break; - case 1: - svga_out(0x3c9, val, svga); - break; - case 2: - svga_out(0x3c6, val, svga); - break; - case 3: - svga_out(0x3c7, val, svga); - break; - default: - ramdac->regs[addr & 0xf] = val; - switch (addr & 0xf) - { - case 0x4: - ramdac->dac_write = val; - ramdac->dac_pos = 0; - break; - case 0x5: - switch (ramdac->dac_pos) - { - case 0: - ramdac->dac_r = val; - ramdac->dac_pos++; - break; - case 1: - ramdac->dac_g = val; - ramdac->dac_pos++; - break; - case 2: - if (ramdac->dac_write > 1) - break; - ramdac->pal[ramdac->dac_write].r = ramdac->dac_r; - ramdac->pal[ramdac->dac_write].g = ramdac->dac_g; - ramdac->pal[ramdac->dac_write].b = val; - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[ramdac->dac_write] = makecol32(ramdac->pal[ramdac->dac_write].r, ramdac->pal[ramdac->dac_write].g, ramdac->pal[ramdac->dac_write].b); - else - ramdac->pallook[ramdac->dac_write] = makecol32((ramdac->pal[ramdac->dac_write].r & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].g & 0x3f) * 4, (ramdac->pal[ramdac->dac_write].b & 0x3f) * 4); - ramdac->dac_pos = 0; - ramdac->dac_write = (ramdac->dac_write + 1) & 255; - break; - } - break; - - case 0xb: - switch (val) - { - case 0x82: - ramdac->render = svga_render_4bpp_highres; - break; - case 0x83: - ramdac->render = svga_render_8bpp_highres; - break; - case 0xa0: case 0xb0: - ramdac->render = svga_render_15bpp_highres; - break; - case 0xa1: case 0xb1: - ramdac->render = svga_render_16bpp_highres; - break; - case 0xc0: case 0xd0: - ramdac->render = svga_render_24bpp_highres; - break; - case 0xe2: case 0xf7: - ramdac->render = svga_render_32bpp_highres; - break; - case 0xe3: - ramdac->render = svga_render_ABGR8888_highres; - break; - case 0xf2: - ramdac->render = svga_render_RGBA8888_highres; - break; - default: - ramdac->render = svga_render_8bpp_highres; - break; - } - break; - case 0xc: - svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT); - break; - } - break; - } -} - -uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga) -{ - uint8_t ret = 0; - switch (addr) - { - case 0: - ret = svga_in(0x3c8, svga); - break; - case 1: - ret = svga_in(0x3c9, svga); - break; - case 2: - ret = svga_in(0x3c6, svga); - break; - case 3: - ret = svga_in(0x3c7, svga); - break; - case 4: case 8: - ret = 2; - break; - case 6: case 0xa: - ret = 0x1d; - break; - case 0xf: - ret = 0xd0; - break; - - default: - ret = ramdac->regs[addr & 0xf]; - break; - } - return ret; -} - -void ati68860_ramdac_init(ati68860_ramdac_t *ramdac) -{ - ramdac->render = svga_render_8bpp_highres; -} - -void ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type) -{ - int c; - - if (ramdac->ramdac_type != type) - { - ramdac->ramdac_type = type; - - for (c = 0; c < 2; c++) - { - if (ramdac->ramdac_type == RAMDAC_8BIT) - ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g, ramdac->pal[c].b); - else - ramdac->pallook[c] = makecol32((ramdac->pal[c].r & 0x3f) * 4, (ramdac->pal[c].g & 0x3f) * 4, (ramdac->pal[c].b & 0x3f) * 4); - } - } -} diff --git a/src/video/vid_ati68860_ramdac - Cópia.h b/src/video/vid_ati68860_ramdac - Cópia.h deleted file mode 100644 index c71376b42..000000000 --- a/src/video/vid_ati68860_ramdac - Cópia.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright holders: Sarah Walker - see COPYING for more details -*/ -typedef struct ati68860_ramdac_t -{ - uint8_t regs[16]; - void (*render)(struct svga_t *svga); - - int dac_write, dac_pos; - int dac_r, dac_g; - PALETTE pal; - uint32_t pallook[2]; - - int ramdac_type; -} ati68860_ramdac_t; - -void ati68860_ramdac_out(uint16_t addr, uint8_t val, ati68860_ramdac_t *ramdac, svga_t *svga); -uint8_t ati68860_ramdac_in(uint16_t addr, ati68860_ramdac_t *ramdac, svga_t *svga); -void ati68860_ramdac_init(ati68860_ramdac_t *ramdac); -void ati68860_set_ramdac_type(ati68860_ramdac_t *ramdac, int type); diff --git a/src/video/vid_bt485_ramdac - Cópia.c b/src/video/vid_bt485_ramdac - Cópia.c deleted file mode 100644 index 4609d9ada..000000000 --- a/src/video/vid_bt485_ramdac - Cópia.c +++ /dev/null @@ -1,348 +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. - * - * Emulation of the Brooktree BT485 and BT485A true colour - * RAM DAC's. - * - * Version: @(#)vid_bt485_ramdac.c 1.0.11 2018/10/03 - * - * Authors: Miran Grca, - * TheCollector1995, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 TheCollector1995. - */ -#include -#include -#include -#include -#include "../86box.h" -#include "../mem.h" -#include "video.h" -#include "vid_svga.h" -#include "vid_bt485_ramdac.h" - - -static void -bt485_set_bpp(bt485_ramdac_t *ramdac, svga_t *svga) -{ - if (!(ramdac->cr2 & 0x20)) - svga->bpp = 8; - else switch ((ramdac->cr1 >> 5) & 0x03) { - case 0: - svga->bpp = 32; - break; - case 1: - if (ramdac->cr1 & 0x08) - svga->bpp = 16; - else - svga->bpp = 15; - break; - case 2: - svga->bpp = 8; - break; - case 3: - svga->bpp = 4; - break; - } - svga_recalctimings(svga); -} - - -void -bt485_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga) -{ - uint32_t o32; - uint8_t *cd; - uint8_t index; - uint8_t rs = (addr & 0x03); - rs |= (!!rs2 << 2); - rs |= (!!rs3 << 3); - - switch (rs) { - case 0x00: /* Palette Write Index Register (RS value = 0000) */ - case 0x03: /* Palette Read Index Register (RS value = 0011) */ - svga_out(addr, val, svga); - if ((ramdac->type >= BT485) && (svga->hwcursor.xsize == 64)) { - svga->dac_read |= ((int) (ramdac->cr3 & 0x03) << 8); - svga->dac_write |= ((int) (ramdac->cr3 & 0x03) << 8); - } - break; - case 0x01: /* Palette Data Register (RS value = 0001) */ - case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - svga_out(addr, val, svga); - break; - case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ - ramdac->ext_write = val; - svga->dac_pos = 0; - svga->dac_status = 0; - ramdac->ext_read = (val - 1) & 0xff; - break; - case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ - ramdac->ext_read = val; - svga->dac_pos = 0; - svga->dac_status = 3; - ramdac->ext_write = (val + 1) & 0xff; - break; - case 0x05: /* Ext Palette Data Register (RS value = 0101) */ - svga->dac_status = 0; - svga->fullchange = changeframecount; - switch (svga->dac_pos) { - case 0: - svga->dac_r = val; - svga->dac_pos++; - break; - case 1: - svga->dac_g = val; - svga->dac_pos++; - break; - case 2: - index = ramdac->ext_write & 3; - ramdac->extpal[index].r = svga->dac_r; - ramdac->extpal[index].g = svga->dac_g; - ramdac->extpal[index].b = val; - if (svga->ramdac_type == RAMDAC_8BIT) - ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b); - else - ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]); - - if ((svga->crtc[0x33] & 0x40) && !index) { - o32 = svga->overscan_color; - svga->overscan_color = ramdac->extpallook[0]; - if (o32 != svga->overscan_color) - svga_recalctimings(svga); - } - ramdac->ext_write = (ramdac->ext_write + 1); - svga->dac_pos = 0; - break; - } - break; - case 0x06: /* Command Register 0 (RS value = 0110) */ - ramdac->cr0 = val; - svga->ramdac_type = (val & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT; - break; - case 0x08: /* Command Register 1 (RS value = 1000) */ - ramdac->cr1 = val; - bt485_set_bpp(ramdac, svga); - break; - case 0x09: /* Command Register 2 (RS value = 1001) */ - ramdac->cr2 = val; - svga->hwcursor.ena = !!(val & 0x03); - pclog("Hardware cursor is now %s\n", svga->hwcursor.ena ? "ON" : "OFF"); - bt485_set_bpp(ramdac, svga); - break; - case 0x0a: - if ((ramdac->type >= BT485) && (ramdac->cr0 & 0x80)) { - switch ((svga->dac_write & 0xff)) { - case 0x01: - /* Command Register 3 (RS value = 1010) */ - ramdac->cr3 = val; - svga->hwcursor.xsize = svga->hwcursor.ysize = (val & 4) ? 64 : 32; - svga->hwcursor.yoff = (svga->hwcursor.ysize == 32) ? 32 : 0; - svga->hwcursor.x = ramdac->hwc_x - svga->hwcursor.xsize; - svga->hwcursor.y = ramdac->hwc_y - svga->hwcursor.ysize; - if (svga->hwcursor.xsize == 64) - svga->dac_write = (svga->dac_write & 0x00ff) | ((val & 0x03) << 8); - svga_recalctimings(svga); - break; - case 0x02: - case 0x20: - case 0x21: - case 0x22: - if (ramdac->type != BT485A) - break; - else if (svga->dac_write == 2) { - ramdac->cr4 = val; - break; - } - break; - } - } - break; - case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ - if (svga->hwcursor.xsize == 64) - cd = (uint8_t *) ramdac->cursor64_data; - else - cd = (uint8_t *) ramdac->cursor32_data; - - cd[svga->dac_write] = val; - - svga->dac_write++; - svga->dac_write &= ((svga->hwcursor.xsize == 64) ? 0x03ff : 0x00ff); - break; - case 0x0c: /* Cursor X Low Register (RS value = 1100) */ - ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val; - svga->hwcursor.x = ramdac->hwc_x - svga->hwcursor.xsize; - break; - case 0x0d: /* Cursor X High Register (RS value = 1101) */ - ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8); - svga->hwcursor.x = ramdac->hwc_x - svga->hwcursor.xsize; - break; - case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ - ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val; - svga->hwcursor.y = ramdac->hwc_y - svga->hwcursor.ysize; - break; - case 0x0f: /* Cursor Y High Register (RS value = 1111) */ - ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8); - svga->hwcursor.y = ramdac->hwc_y - svga->hwcursor.ysize; - break; - } - - return; -} - - -uint8_t -bt485_ramdac_in(uint16_t addr, int rs2, int rs3, bt485_ramdac_t *ramdac, svga_t *svga) -{ - uint8_t temp = 0xff; - uint8_t *cd; - uint8_t index; - uint8_t rs = (addr & 0x03); - rs |= (!!rs2 << 2); - rs |= (!!rs3 << 3); - - switch (rs) { - case 0x00: /* Palette Write Index Register (RS value = 0000) */ - case 0x01: /* Palette Data Register (RS value = 0001) */ - case 0x02: /* Pixel Read Mask Register (RS value = 0010) */ - temp = svga_in(addr, svga); - break; - case 0x03: /* Palette Read Index Register (RS value = 0011) */ - temp = svga->dac_read & 0xff; - break; - case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */ - temp = ramdac->ext_write; - break; - case 0x05: /* Ext Palette Data Register (RS value = 0101) */ - index = ramdac->ext_read & 3; - svga->dac_status = 3; - switch (svga->dac_pos) { - case 0: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].r; - else - temp = ramdac->extpal[index].r & 0x3f; - case 1: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].g; - else - temp = ramdac->extpal[index].g & 0x3f; - case 2: - svga->dac_pos=0; - ramdac->ext_read = ramdac->ext_read + 1; - if (svga->ramdac_type == RAMDAC_8BIT) - temp = ramdac->extpal[index].b; - else - temp = ramdac->extpal[index].b & 0x3f; - } - break; - case 0x06: /* Command Register 0 (RS value = 0110) */ - temp = ramdac->cr0; - break; - case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */ - temp = ramdac->ext_read; - break; - case 0x08: /* Command Register 1 (RS value = 1000) */ - temp = ramdac->cr1; - break; - case 0x09: /* Command Register 2 (RS value = 1001) */ - temp = ramdac->cr2; - break; - case 0x0a: - if ((ramdac->type >= BT485) && (ramdac->cr0 & 0x80)) { - switch ((svga->dac_write & 0xff)) { - case 0x00: - temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00); - break; - case 0x01: - temp = ramdac->cr3; - break; - case 0x02: - case 0x20: - case 0x21: - case 0x22: - if (ramdac->type != BT485A) - break; - else if (svga->dac_write == 2) { - temp = ramdac->cr4; - break; - } else { - /* TODO: Red, Green, and Blue Signature Analysis Registers */ - temp = 0xff; - break; - } - break; - } - } else - temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00); - break; - case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */ - if (svga->hwcursor.xsize == 64) - cd = (uint8_t *) ramdac->cursor64_data; - else - cd = (uint8_t *) ramdac->cursor32_data; - - temp = cd[svga->dac_read]; - - svga->dac_read++; - svga->dac_read &= ((svga->hwcursor.xsize == 64) ? 0x03ff : 0x00ff); - break; - case 0x0c: /* Cursor X Low Register (RS value = 1100) */ - temp = ramdac->hwc_x & 0xff; - break; - case 0x0d: /* Cursor X High Register (RS value = 1101) */ - temp = (ramdac->hwc_x >> 8) & 0xff; - break; - case 0x0e: /* Cursor Y Low Register (RS value = 1110) */ - temp = ramdac->hwc_y & 0xff; - break; - case 0x0f: /* Cursor Y High Register (RS value = 1111) */ - temp = (ramdac->hwc_y >> 8) & 0xff; - break; - } - - return temp; -} - -void bt485_init(bt485_ramdac_t *ramdac, svga_t *svga, uint8_t type) -{ - memset(ramdac, 0, sizeof(bt485_ramdac_t)); - ramdac->type = type; - - if (ramdac->type < BT485) { - /* The BT484 and AT&T 20C504 only have a 32x32 cursor. */ - svga->hwcursor.xsize = svga->hwcursor.ysize = 32; - svga->hwcursor.yoff = 32; - } - - /* Set the RAM DAC status byte to the correct ID bits. - - Both the BT484 and BT485 datasheets say this: - SR7-SR6: These bits are identification values. SR7=0 and SR6=1. - But all other sources seem to assume SR7=1 and SR6=0. */ - switch (ramdac->type) { - case BT484: - ramdac->status = 0x40; - break; - case ATT20C504: - ramdac->status = 0x40; - break; - case BT485: - ramdac->status = 0x60; - break; - case ATT20C505: - ramdac->status = 0xd0; - break; - case BT485A: - ramdac->status = 0x20; - break; - } -} diff --git a/src/video/vid_bt485_ramdac - Cópia.h b/src/video/vid_bt485_ramdac - Cópia.h deleted file mode 100644 index 8e5eac4f9..000000000 --- a/src/video/vid_bt485_ramdac - Cópia.h +++ /dev/null @@ -1,47 +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. - * - * Header of the emulation of the Brooktree BT485 and BT485A - * true colour RAM DAC's. - * - * Version: @(#)vid_bt485_ramdac.h 1.0.3 2018/10/03 - * - * Authors: Miran Grca, - * TheCollector1995, - * - * Copyright 2016-2018 Miran Grca. - * Copyright 2018 TheCollector1995. - */ -typedef struct bt485_ramdac_t -{ - PALETTE extpal; - uint32_t extpallook[256]; - uint8_t cursor32_data[256]; - uint8_t cursor64_data[1024]; - int hwc_y, hwc_x; - uint8_t cr0; - uint8_t cr1; - uint8_t cr2; - uint8_t cr3; - uint8_t cr4; - uint8_t status; - uint8_t type; - uint8_t ext_read, ext_write; -} bt485_ramdac_t; - -enum { - BT484 = 0, - ATT20C504, - BT485, - ATT20C505, - BT485A -}; - -extern void bt485_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, bt485_ramdac_t *ramdac, svga_t *svga); -extern uint8_t bt485_ramdac_in(uint16_t addr, int rs2, int rs3, bt485_ramdac_t *ramdac, svga_t *svga); -extern void bt485_init(bt485_ramdac_t *ramdac, svga_t *svga, uint8_t type); diff --git a/src/video/vid_svga.c.good b/src/video/vid_svga.c.good deleted file mode 100644 index 8c82b0dd9..000000000 --- a/src/video/vid_svga.c.good +++ /dev/null @@ -1,1372 +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. - * - * Generic SVGA handling. - * - * This is intended to be used by another SVGA driver, - * and not as a card in it's own right. - * - * Version: @(#)vid_svga.c 1.0.32 2018/10/02 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../io.h" -#include "../pit.h" -#include "../mem.h" -#include "../rom.h" -#include "../timer.h" -#include "video.h" -#include "vid_svga.h" -#include "vid_svga_render.h" - - -#define svga_output 0 - -void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga); - -extern int cyc_total; -extern uint8_t edatlookup[4][4]; - -uint8_t svga_rotate[8][256]; - -static const uint32_t mask16[16] = { - 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, - 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, - 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, - 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff -}; - -/*Primary SVGA device. As multiple video cards are not yet supported this is the - only SVGA device.*/ -static svga_t *svga_pri; - - -svga_t -*svga_get_pri() -{ - return svga_pri; -} - - -void -svga_set_override(svga_t *svga, int val) -{ - if (svga->override && !val) - svga->fullchange = changeframecount; - svga->override = val; -} - - -/* Used to add custom write modes, eg. by the CL-GD 54xx to add write modes 4 and 5. */ -void -svga_set_ven_write(svga_t *svga, void (*ven_write)(struct svga_t *svga, uint8_t val, uint32_t addr)) -{ - svga->ven_write = ven_write; -} - - -void -svga_out(uint16_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - int c; - uint8_t o; - - switch (addr) { - case 0x3c0: - case 0x3c1: - if (!svga->attrff) { - svga->attraddr = val & 31; - if ((val & 0x20) != svga->attr_palette_enable) { - svga->fullchange = 3; - svga->attr_palette_enable = val & 0x20; - svga_recalctimings(svga); - } - } else { - if ((svga->attraddr == 0x13) && (svga->attrregs[0x13] != val)) - svga->fullchange = changeframecount; - o = svga->attrregs[svga->attraddr & 31]; - svga->attrregs[svga->attraddr & 31] = val; - if (svga->attraddr < 16) - svga->fullchange = changeframecount; - if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) { - for (c = 0; c < 16; c++) { - if (svga->attrregs[0x10] & 0x80) { - svga->egapal[c] = (svga->attrregs[c] & 0xf) | - ((svga->attrregs[0x14] & 0xf) << 4); - } else { - svga->egapal[c] = (svga->attrregs[c] & 0x3f) | - ((svga->attrregs[0x14] & 0xc) << 4); - } - } - } - /* Recalculate timings on change of attribute register 0x11 - (overscan border color) too. */ - if (svga->attraddr == 0x10) { - if (o != val) - svga_recalctimings(svga); - } else if (svga->attraddr == 0x11) { - svga->overscan_color = svga->pallook[svga->attrregs[0x11]]; - if (o != val) - svga_recalctimings(svga); - } else if (svga->attraddr == 0x12) { - if ((val & 0xf) != svga->plane_mask) - svga->fullchange = changeframecount; - svga->plane_mask = val & 0xf; - } - } - svga->attrff ^= 1; - break; - case 0x3c2: - svga->miscout = val; - svga->vidclock = val & 4; - io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); - if (!(val & 1)) - io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p); - svga_recalctimings(svga); - break; - case 0x3c4: - svga->seqaddr = val; - break; - case 0x3c5: - if (svga->seqaddr > 0xf) - return; - o = svga->seqregs[svga->seqaddr & 0xf]; - svga->seqregs[svga->seqaddr & 0xf] = val; - if (o != val && (svga->seqaddr & 0xf) == 1) - svga_recalctimings(svga); - switch (svga->seqaddr & 0xf) { - case 1: - if (svga->scrblank && !(val & 0x20)) - svga->fullchange = 3; - svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20); - svga_recalctimings(svga); - break; - case 2: - svga->writemask = val & 0xf; - break; - case 3: - svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2; - svga->charseta = ((val & 3) * 0x10000) + 2; - if (val & 0x10) - svga->charseta += 0x8000; - if (val & 0x20) - svga->charsetb += 0x8000; - break; - case 4: - svga->chain2_write = !(val & 4); - svga->chain4 = val & 8; - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - !svga->gdcreg[1]) && svga->chain4; - break; - } - break; - case 0x3c6: - svga->dac_mask = val; - pclog("[W 3C6] svga->dac_mask = %02X\n", val); - break; - case 0x3C7: - svga->dac_read = val; - svga->dac_pos = 0; - svga->dac_status = 3; - svga->dac_write = (val + 1) & 0xff; - pclog("[W 3C7] svga->dac_read = %02X\n", val); - pclog("[W 3C7] svga->dac_pos = 00\n"); - pclog("[W 3C7] svga->dac_status = 03\n"); - pclog("[W 3C7] svga->dac_write = %02X\n", svga->dac_write); - break; - case 0x3c8: - svga->dac_write = val; - svga->dac_pos = 0; - svga->dac_status = 0; - svga->dac_read = (val - 1) & 0xff; - pclog("[W 3C8] svga->dac_write = %02X\n", val); - pclog("[W 3C8] svga->dac_pos = 00\n"); - pclog("[W 3C8] svga->dac_status = 00\n"); - pclog("[W 3C8] svga->dac_read = %02X\n", svga->dac_read); - break; - case 0x3c9: - svga->fullchange = changeframecount; - switch (svga->dac_pos) { - case 0: - svga->dac_r = val; - svga->dac_pos++; - break; - case 1: - svga->dac_g = val; - svga->dac_pos++; - break; - case 2: - svga->vgapal[svga->dac_write].r = svga->dac_r; - svga->vgapal[svga->dac_write].g = svga->dac_g; - svga->vgapal[svga->dac_write].b = val; - if (svga->ramdac_type == RAMDAC_8BIT) - svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r, svga->vgapal[svga->dac_write].g, svga->vgapal[svga->dac_write].b); - else - svga->pallook[svga->dac_write] = makecol32(video_6to8[svga->vgapal[svga->dac_write].r & 0x3f], video_6to8[svga->vgapal[svga->dac_write].g & 0x3f], video_6to8[svga->vgapal[svga->dac_write].b & 0x3f]); - svga->dac_pos = 0; - svga->dac_write = (svga->dac_write + 1) & 255; - break; - } - pclog("[W 3C9] val = %02X\n", val); - break; - case 0x3ce: - svga->gdcaddr = val; - break; - case 0x3cf: - o = svga->gdcreg[svga->gdcaddr & 15]; - switch (svga->gdcaddr & 15) { - case 2: - svga->colourcompare=val; - break; - case 4: - svga->readplane = val & 3; - break; - case 5: - svga->writemode = val & 3; - svga->readmode = val & 8; - svga->chain2_read = val & 0x10; - break; - case 6: - if ((svga->gdcreg[6] & 0xc) != (val & 0xc)) { - switch (val&0xC) { - case 0x0: /*128k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000); - svga->banked_mask = 0xffff; - break; - case 0x4: /*64k at A0000*/ - mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000); - svga->banked_mask = 0xffff; - break; - case 0x8: /*32k at B0000*/ - mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000); - svga->banked_mask = 0x7fff; - break; - case 0xC: /*32k at B8000*/ - mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000); - svga->banked_mask = 0x7fff; - break; - } - } - break; - case 7: - svga->colournocare=val; - break; - } - svga->gdcreg[svga->gdcaddr & 15] = val; - svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - !svga->gdcreg[1]) && svga->chain4; - if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || - ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) - svga_recalctimings(svga); - break; - } -} - - -uint8_t -svga_in(uint16_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - uint8_t ret = 0xff; - - switch (addr) { - case 0x3c0: - ret = svga->attraddr | svga->attr_palette_enable; - break; - case 0x3c1: - ret = svga->attrregs[svga->attraddr]; - break; - case 0x3c2: - if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x4e) - ret = 0; - else - ret = 0x10; - break; - case 0x3c4: - ret = svga->seqaddr; - break; - case 0x3c5: - ret = svga->seqregs[svga->seqaddr & 0x0f]; - break; - case 0x3c6: - ret = svga->dac_mask; - pclog("[R 3C6] svga->dac_mask = %02X\n", ret); - break; - case 0x3c7: - ret = svga->dac_status; - pclog("[R 3C7] svga->dac_status = %02X\n", ret); - break; - case 0x3c8: - ret = svga->dac_write; - pclog("[R 3C8] svga->dac_write = %02X\n", ret); - break; - case 0x3c9: - svga->dac_status = 3; - switch (svga->dac_pos) { - case 0: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - ret = svga->vgapal[svga->dac_read].r; - else - ret = svga->vgapal[svga->dac_read].r & 0x3f; - break; - case 1: - svga->dac_pos++; - if (svga->ramdac_type == RAMDAC_8BIT) - ret = svga->vgapal[svga->dac_read].g; - else - ret = svga->vgapal[svga->dac_read].g & 0x3f; - break; - case 2: - svga->dac_pos=0; - svga->dac_read = (svga->dac_read + 1) & 255; - if (svga->ramdac_type == RAMDAC_8BIT) - ret = svga->vgapal[(svga->dac_read - 1) & 255].b; - else - ret = svga->vgapal[(svga->dac_read - 1) & 255].b & 0x3f; - break; - } - pclog("[R 3C9] ret = %02X\n", ret); - break; - case 0x3cc: - ret = svga->miscout; - break; - case 0x3ce: - ret = svga->gdcaddr; - break; - case 0x3cf: - /* The spec says GDC addresses 0xF8 to 0xFB return the latch. */ - switch(svga->gdcaddr) { - case 0xf8: - ret = (svga->latch & 0xFF); - break; - case 0xf9: - ret = ((svga->latch & 0xFF00) >> 8); - break; - case 0xfa: - ret = ((svga->latch & 0xFF0000) >> 16); - break; - case 0xfb: - ret = ((svga->latch & 0xFF000000) >> 24); - break; - default: - ret = svga->gdcreg[svga->gdcaddr & 0xf]; - break; - } - break; - case 0x3da: - svga->attrff = 0; - svga->attrff = 0; - - if (svga->cgastat & 0x01) - svga->cgastat &= ~0x30; - else - svga->cgastat ^= 0x30; - ret = svga->cgastat; - break; - } - - return(ret); -} - - -void -svga_set_ramdac_type(svga_t *svga, int type) -{ - int c; - - if (svga->ramdac_type != type) { - svga->ramdac_type = type; - - for (c = 0; c < 256; c++) { - if (svga->ramdac_type == RAMDAC_8BIT) - svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b); - else - svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, - (svga->vgapal[c].g & 0x3f) * 4, - (svga->vgapal[c].b & 0x3f) * 4); - } - } -} - - -void -svga_recalctimings(svga_t *svga) -{ - double crtcconst, _dispontime, _dispofftime, disptime; - - svga->vtotal = svga->crtc[6]; - svga->dispend = svga->crtc[0x12]; - svga->vsyncstart = svga->crtc[0x10]; - svga->split = svga->crtc[0x18]; - svga->vblankstart = svga->crtc[0x15]; - - if (svga->crtc[7] & 1) - svga->vtotal |= 0x100; - if (svga->crtc[7] & 32) - svga->vtotal |= 0x200; - svga->vtotal += 2; - - if (svga->crtc[7] & 2) - svga->dispend |= 0x100; - if (svga->crtc[7] & 64) - svga->dispend |= 0x200; - svga->dispend++; - - if (svga->crtc[7] & 4) - svga->vsyncstart |= 0x100; - if (svga->crtc[7] & 128) - svga->vsyncstart |= 0x200; - svga->vsyncstart++; - - if (svga->crtc[7] & 0x10) - svga->split|=0x100; - if (svga->crtc[9] & 0x40) - svga->split|=0x200; - svga->split++; - - if (svga->crtc[7] & 0x08) - svga->vblankstart |= 0x100; - if (svga->crtc[9] & 0x20) - svga->vblankstart |= 0x200; - svga->vblankstart++; - - svga->hdisp = svga->crtc[1]; - svga->hdisp++; - - svga->htotal = svga->crtc[0]; - svga->htotal += 6; /*+6 is required for Tyrian*/ - - svga->rowoffset = svga->crtc[0x13]; - - svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1; - - svga->lowres = svga->attrregs[0x10] & 0x40; - - svga->interlace = 0; - - svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd]; - - svga->hdisp_time = svga->hdisp; - svga->render = svga_render_blank; - if (!svga->scrblank && svga->attr_palette_enable) { - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - if (svga->seqregs[1] & 8) /*40 column*/ { - svga->render = svga_render_text_40; - svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18; - } else { - svga->render = svga_render_text_80; - svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9; - } - svga->hdisp_old = svga->hdisp; - } else { - svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8; - svga->hdisp_old = svga->hdisp; - - switch (svga->gdcreg[5] & 0x60) { - case 0x00: - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_4bpp_lowres; - else - svga->render = svga_render_4bpp_highres; - break; - case 0x20: /*4 colours*/ - if (svga->seqregs[1] & 8) /*Low res (320)*/ - svga->render = svga_render_2bpp_lowres; - else - svga->render = svga_render_2bpp_highres; - break; - case 0x40: case 0x60: /*256+ colours*/ - switch (svga->bpp) { - case 8: - if (svga->lowres) - svga->render = svga_render_8bpp_lowres; - else - svga->render = svga_render_8bpp_highres; - break; - case 15: - if (svga->lowres) - svga->render = svga_render_15bpp_lowres; - else - svga->render = svga_render_15bpp_highres; - break; - case 16: - if (svga->lowres) - svga->render = svga_render_16bpp_lowres; - else - svga->render = svga_render_16bpp_highres; - break; - case 24: - if (svga->lowres) - svga->render = svga_render_24bpp_lowres; - else - svga->render = svga_render_24bpp_highres; - break; - case 32: - if (svga->lowres) - svga->render = svga_render_32bpp_lowres; - else - svga->render = svga_render_32bpp_highres; - break; - } - break; - } - } - } - - svga->linedbl = svga->crtc[9] & 0x80; - svga->rowcount = svga->crtc[9] & 31; - if (enable_overscan) { - overscan_y = (svga->rowcount + 1) << 1; - if (svga->seqregs[1] & 8) /*Low res (320)*/ - overscan_y <<= 1; - if (overscan_y < 16) - overscan_y = 16; - } - if (svga->recalctimings_ex) - svga->recalctimings_ex(svga); - - if (svga->vblankstart < svga->dispend) - svga->dispend = svga->vblankstart; - - crtcconst = (svga->seqregs[1] & 1) ? (svga->clock * 8.0) : (svga->clock * 9.0); - - disptime = svga->htotal; - _dispontime = svga->hdisp_time; - - if (svga->seqregs[1] & 8) { - disptime *= 2; - _dispontime *= 2; - } - _dispofftime = disptime - _dispontime; - _dispontime *= crtcconst; - _dispofftime *= crtcconst; - - svga->dispontime = (int)(_dispontime * (1 << TIMER_SHIFT)); - svga->dispofftime = (int)(_dispofftime * (1 << TIMER_SHIFT)); -} - - -void -svga_poll(void *p) -{ - svga_t *svga = (svga_t *)p; - uint32_t x; - int wx, wy; - - if (!svga->linepos) { - if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) { - svga->hwcursor_on = 64 - svga->hwcursor_latch.yoff; - svga->hwcursor_oddeven = 0; - } - - if (svga->displine == (svga->hwcursor_latch.y + 1) && svga->hwcursor_latch.ena && - svga->interlace) { - svga->hwcursor_on = 64 - (svga->hwcursor_latch.yoff + 1); - svga->hwcursor_oddeven = 1; - } - - if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena) { - svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; - svga->overlay_oddeven = 0; - } - - if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace) { - svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff; - svga->overlay_oddeven = 1; - } - - svga->vidtime += svga->dispofftime; - svga->cgastat |= 1; - svga->linepos = 1; - - if (svga->dispon) { - svga->hdisp_on=1; - - svga->ma &= svga->vram_display_mask; - if (svga->firstline == 2000) { - svga->firstline = svga->displine; - video_wait_for_buffer(); - } - - if (svga->hwcursor_on || svga->overlay_on) { - svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = - svga->interlace ? 3 : 2; - } - - if (!svga->override) - svga->render(svga); - - if (svga->overlay_on) { - if (!svga->override) - svga->overlay_draw(svga, svga->displine); - svga->overlay_on--; - if (svga->overlay_on && svga->interlace) - svga->overlay_on--; - } - - if (svga->hwcursor_on) { - if (!svga->override) - svga->hwcursor_draw(svga, svga->displine); - svga->hwcursor_on--; - if (svga->hwcursor_on && svga->interlace) - svga->hwcursor_on--; - } - - if (svga->lastline < svga->displine) - svga->lastline = svga->displine; - } - - svga->displine++; - if (svga->interlace) - svga->displine++; - if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines) - svga->cgastat &= ~8; - svga->vslines++; - if (svga->displine > 1500) - svga->displine = 0; - } else { - svga->vidtime += svga->dispontime; - - if (svga->dispon) - svga->cgastat &= ~1; - svga->hdisp_on = 0; - - svga->linepos = 0; - if (svga->sc == (svga->crtc[11] & 31)) - svga->con = 0; - if (svga->dispon) { - if (svga->linedbl && !svga->linecountff) { - svga->linecountff = 1; - svga->ma = svga->maback; - } else if (svga->sc == svga->rowcount) { - svga->linecountff = 0; - svga->sc = 0; - - svga->maback += (svga->rowoffset << 3); - if (svga->interlace) - svga->maback += (svga->rowoffset << 3); - svga->maback &= svga->vram_display_mask; - svga->ma = svga->maback; - } else { - svga->linecountff = 0; - svga->sc++; - svga->sc &= 31; - svga->ma = svga->maback; - } - } - svga->vc++; - svga->vc &= 2047; - - if (svga->vc == svga->split) { - svga->ma = svga->maback = 0; - svga->sc = 0; - if (svga->attrregs[0x10] & 0x20) - svga->scrollcache = 0; - } - if (svga->vc == svga->dispend) { - if (svga->vblank_start) - svga->vblank_start(svga); - svga->dispon=0; - if (svga->crtc[10] & 0x20) - svga->cursoron = 0; - else - svga->cursoron = svga->blink & 16; - - if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15)) - svga->fullchange = 2; - svga->blink++; - - for (x = 0; x < ((svga->vram_mask + 1) >> 12); x++) { - if (svga->changedvram[x]) - svga->changedvram[x]--; - } - if (svga->fullchange) - svga->fullchange--; - } - if (svga->vc == svga->vsyncstart) { - svga->dispon = 0; - svga->cgastat |= 8; - x = svga->hdisp; - - if (svga->interlace && !svga->oddeven) - svga->lastline++; - if (svga->interlace && svga->oddeven) - svga->firstline--; - - wx = x; - wy = svga->lastline - svga->firstline; - - if (!svga->override) - svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga); - - svga->firstline = 2000; - svga->lastline = 0; - - svga->firstline_draw = 2000; - svga->lastline_draw = 0; - - svga->oddeven ^= 1; - - changeframecount = svga->interlace ? 3 : 2; - svga->vslines = 0; - - if (svga->interlace && svga->oddeven) - svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1); - else - svga->ma = svga->maback = svga->ma_latch; - svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf]; - - svga->ma <<= 2; - svga->maback <<= 2; - svga->ca <<= 2; - - svga->video_res_x = wx; - svga->video_res_y = wy + 1; - if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/ - svga->video_res_x /= (svga->seqregs[1] & 1) ? 8 : 9; - svga->video_res_y /= (svga->crtc[9] & 31) + 1; - svga->video_bpp = 0; - } else { - if (svga->crtc[9] & 0x80) - svga->video_res_y /= 2; - if (!(svga->crtc[0x17] & 2)) - svga->video_res_y *= 4; - else if (!(svga->crtc[0x17] & 1)) - svga->video_res_y *= 2; - svga->video_res_y /= (svga->crtc[9] & 31) + 1; - if (svga->lowres) - svga->video_res_x /= 2; - - svga->video_bpp = svga->bpp; - } - } - if (svga->vc == svga->vtotal) { - svga->vc = 0; - svga->sc = svga->crtc[8] & 0x1f; - svga->dispon = 1; - svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0; - svga->scrollcache = svga->attrregs[0x13] & 7; - svga->linecountff = 0; - - svga->hwcursor_on = 0; - svga->hwcursor_latch = svga->hwcursor; - - svga->overlay_on = 0; - svga->overlay_latch = svga->overlay; - } - if (svga->sc == (svga->crtc[10] & 31)) - svga->con = 1; - } -} - - -int -svga_init(svga_t *svga, void *p, int memsize, - void (*recalctimings_ex)(struct svga_t *svga), - uint8_t (*video_in) (uint16_t addr, void *p), - void (*video_out)(uint16_t addr, uint8_t val, void *p), - void (*hwcursor_draw)(struct svga_t *svga, int displine), - void (*overlay_draw)(struct svga_t *svga, int displine)) -{ - int c, d, e; - - svga->p = p; - - for (c = 0; c < 256; c++) { - e = c; - for (d = 0; d < 8; d++) { - svga_rotate[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } - } - svga->readmode = 0; - - svga->attrregs[0x11] = 0; - svga->overscan_color = 0x000000; - - overscan_x = 16; - overscan_y = 32; - - svga->crtc[0] = 63; - svga->crtc[6] = 255; - svga->dispontime = svga->dispofftime = 1000 * (1 << TIMER_SHIFT); - svga->bpp = 8; - svga->vram = malloc(memsize); - svga->vram_max = memsize; - svga->vram_display_mask = svga->vram_mask = memsize - 1; - svga->decode_mask = 0x7fffff; - svga->changedvram = malloc(memsize >> 12); - svga->recalctimings_ex = recalctimings_ex; - svga->video_in = video_in; - svga->video_out = video_out; - svga->hwcursor_draw = hwcursor_draw; - svga->overlay_draw = overlay_draw; - - mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, - svga_read, svga_readw, svga_readl, - svga_write, svga_writew, svga_writel, - NULL, MEM_MAPPING_EXTERNAL, svga); - - timer_add(svga_poll, &svga->vidtime, TIMER_ALWAYS_ENABLED, svga); - - svga_pri = svga; - - svga->ramdac_type = RAMDAC_6BIT; - - return 0; -} - - -void -svga_close(svga_t *svga) -{ - free(svga->changedvram); - free(svga->vram); - - svga_pri = NULL; -} - - -void -svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p) -{ - svga_t *svga = (svga_t *)p; - - int func_select, writemask2 = svga->writemask; - uint32_t write_mask, bit_mask, set_mask, val32 = (uint32_t) val; - - egawrites++; - - cycles -= video_timing_write_b; - - if (!linear) { - addr &= svga->banked_mask; - addr += svga->write_bank; - } - - if (!(svga->gdcreg[6] & 1)) - svga->fullchange = 2; - - if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) { - writemask2 = 1 << (addr & 3); - addr &= ~3; - } else if (svga->chain2_write) { - writemask2 &= ~0xa; - if (addr & 1) - writemask2 <<= 1; - addr &= ~1; - addr <<= 2; - } else - addr <<= 2; - addr &= svga->decode_mask; - - if (addr >= svga->vram_max) - return; - - addr &= svga->vram_mask; - - svga->changedvram[addr >> 12] = changeframecount; - - /* standard VGA latched access */ - func_select = (svga->gdcreg[3] >> 3) & 3; - - switch (svga->writemode) { - case 0: - /* rotate */ - if (svga->gdcreg[3] & 7) - val32 = svga_rotate[svga->gdcreg[3] & 7][val32]; - - /* apply set/reset mask */ - bit_mask = svga->gdcreg[8]; - - val32 |= (val32 << 8); - val32 |= (val32 << 16); - - if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && - (!svga->gdcreg[1] || svga->set_reset_disabled)) { - /* mask data according to sr[2] */ - write_mask = mask16[writemask2 & 0x0f]; - addr >>= 2; - ((uint32_t *)(svga->vram))[addr] &= ~write_mask; - ((uint32_t *)(svga->vram))[addr] |= (val32 & write_mask); - return; - } - - set_mask = mask16[svga->gdcreg[1] & 0x0f]; - val32 = (val32 & ~set_mask) | (mask16[svga->gdcreg[0] & 0x0f] & set_mask); - break; - case 1: - val32 = svga->latch; - - /* mask data according to sr[2] */ - write_mask = mask16[writemask2 & 0x0f]; - addr >>= 2; - ((uint32_t *)(svga->vram))[addr] &= ~write_mask; - ((uint32_t *)(svga->vram))[addr] |= (val32 & write_mask); - return; - case 2: - val32 = mask16[val32 & 0x0f]; - bit_mask = svga->gdcreg[8]; - - if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled)) - func_select = 0; - break; - case 3: - /* rotate */ - if (svga->gdcreg[3] & 7) - val32 = svga_rotate[svga->gdcreg[3] & 7][val]; - - bit_mask = svga->gdcreg[8] & val32; - val32 = mask16[svga->gdcreg[0] & 0x0f]; - break; - default: - if (svga->ven_write) - svga->ven_write(svga, val, addr); - return; - } - - /* apply bit mask */ - bit_mask |= bit_mask << 8; - bit_mask |= bit_mask << 16; - - /* apply logical operation */ - switch(func_select) { - case 0: - default: - /* set */ - val32 &= bit_mask; - val32 |= (svga->latch & ~bit_mask); - break; - case 1: - /* and */ - val32 |= ~bit_mask; - val32 &= svga->latch; - break; - case 2: - /* or */ - val32 &= bit_mask; - val32 |= svga->latch; - break; - case 3: - /* xor */ - val32 &= bit_mask; - val32 ^= svga->latch; - break; - } - - /* mask data according to sr[2] */ - write_mask = mask16[writemask2 & 0x0f]; - addr >>= 2; - ((uint32_t *)(svga->vram))[addr] = (((uint32_t *)(svga->vram))[addr] & ~write_mask) | (val32 & write_mask); -} - - -uint8_t -svga_read_common(uint32_t addr, uint8_t linear, void *p) -{ - svga_t *svga = (svga_t *)p; - uint32_t latch_addr = 0, ret; - int readplane = svga->readplane; - uint8_t ret8; - - cycles -= video_timing_read_b; - - egareads++; - - if (!linear) { - addr &= svga->banked_mask; - addr += svga->read_bank; - - latch_addr = (addr << 2) & svga->decode_mask; - } - - if (svga->chain4 || svga->fb_only) { - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - return svga->vram[addr & svga->vram_mask]; - } else if (svga->chain2_read) { - readplane = (readplane & 2) | (addr & 1); - addr &= ~1; - addr <<= 2; - } else - addr <<= 2; - - addr &= svga->decode_mask; - - /* standard VGA latched access */ - if (linear) { - if (addr >= svga->vram_max) - return 0xff; - - addr &= svga->vram_mask; - - svga->latch = ((uint32_t *)(svga->vram))[addr >> 2]; - } else { - if (latch_addr > svga->vram_max) - svga->latch = 0xffffffff; - else { - latch_addr &= svga->vram_mask; - svga->latch = ((uint32_t *)(svga->vram))[latch_addr >> 2]; - } - - if (addr >= svga->vram_max) - return 0xff; - - addr &= svga->vram_mask; - } - - if (!(svga->gdcreg[5] & 8)) { - /* read mode 0 */ - return svga->vram[addr | readplane]; - } else { - /* read mode 1 */ - ret = (svga->latch ^ mask16[svga->colourcompare & 0x0f]) & mask16[svga->colournocare & 0x0f]; - ret8 = (ret & 0xff); - ret8 |= ((ret >> 24) & 0xff); - ret8 |= ((ret >> 16) & 0xff); - ret8 |= ((ret >> 8) & 0xff); - return(~ret8); - } -} - - -void -svga_write(uint32_t addr, uint8_t val, void *p) -{ - svga_write_common(addr, val, 0, p); -} - - -void -svga_write_linear(uint32_t addr, uint8_t val, void *p) -{ - svga_write_common(addr, val, 1, p); -} - - -uint8_t -svga_read(uint32_t addr, void *p) -{ - return svga_read_common(addr, 0, p); -} - - -uint8_t -svga_read_linear(uint32_t addr, void *p) -{ - return svga_read_common(addr, 1, p); -} - - -void -svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga) -{ - int y_add = (enable_overscan) ? overscan_y : 0; - int x_add = (enable_overscan) ? 16 : 0; - uint32_t *p; - int i, j; - - svga->frames++; - - if ((xsize > 2032) || (ysize > 2032)) { - x_add = 0; - y_add = 0; - suppress_overscan = 1; - } else - suppress_overscan = 0; - - if (y1 > y2) { - video_blit_memtoscreen(32, 0, 0, 0, xsize + x_add, ysize + y_add); - return; - } - - if ((wx != xsize) || ((wy + 1) != ysize) || video_force_resize_get()) { - /* Screen res has changed.. fix up, and let them know. */ - xsize = wx; - ysize = wy + 1; - if (xsize < 64) - xsize = 640; - if (ysize < 32) - ysize = 200; - - set_screen_size(xsize+x_add,ysize+y_add); - - if (video_force_resize_get()) - video_force_resize_set(0); - } - - if (enable_overscan && !suppress_overscan) { - if ((wx >= 160) && ((wy + 1) >= 120)) { - /* Draw (overscan_size - scroll size) lines of overscan on top. */ - for (i = 0; i < (y_add >> 1); i++) { - p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; - - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga->overscan_color; - } - - /* Draw (overscan_size + scroll size) lines of overscan on the bottom. */ - for (i = 0; i < (y_add >> 1); i++) { - p = &((uint32_t *)buffer32->line[(ysize + (y_add >> 1) + i) & 0x7ff])[32]; - - for (j = 0; j < (xsize + x_add); j++) - p[j] = svga->overscan_color; - } - - for (i = (y_add >> 1); i < (ysize + (y_add >> 1)); i ++) { - p = &((uint32_t *)buffer32->line[i & 0x7ff])[32]; - - for (j = 0; j < 8; j++) { - p[j] = svga->pallook[svga->overscan_color]; - p[xsize + (x_add >> 1) + j] = svga->overscan_color; - } - } - } - } - - video_blit_memtoscreen(32, 0, y1, y2 + y_add, xsize + x_add, ysize + y_add); -} - - -void -svga_writeb_linear(uint32_t addr, uint8_t val, void *p) -{ - svga_t *svga = (svga_t *)p; - - if (!svga->fast) { - svga_write_linear(addr, val, p); - return; - } - - egawrites++; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint8_t *)&svga->vram[addr] = val; -} - - -void -svga_writew_common(uint32_t addr, uint16_t val, uint8_t linear, void *p) -{ - svga_t *svga = (svga_t *)p; - - if (!svga->fast) { - svga_write_common(addr, val, linear, p); - svga_write_common(addr + 1, val >> 8, linear, p); - return; - } - - egawrites += 2; - - cycles -= video_timing_write_w; - - if (!linear) - addr = (addr & svga->banked_mask) + svga->write_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - svga->changedvram[addr >> 12] = changeframecount; - *(uint16_t *)&svga->vram[addr] = val; -} - - -void -svga_writew(uint32_t addr, uint16_t val, void *p) -{ - svga_writew_common(addr, val, 0, p); -} - - -void -svga_writew_linear(uint32_t addr, uint16_t val, void *p) -{ - svga_writew_common(addr, val, 1, p); -} - - -void -svga_writel_common(uint32_t addr, uint32_t val, uint8_t linear, void *p) -{ - svga_t *svga = (svga_t *)p; - - if (!svga->fast) { - svga_write(addr, val, p); - svga_write(addr + 1, val >> 8, p); - svga_write(addr + 2, val >> 16, p); - svga_write(addr + 3, val >> 24, p); - return; - } - - egawrites += 4; - - cycles -= video_timing_write_l; - - if (!linear) - addr = (addr & svga->banked_mask) + svga->write_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return; - addr &= svga->vram_mask; - - svga->changedvram[addr >> 12] = changeframecount; - *(uint32_t *)&svga->vram[addr] = val; -} - - -void -svga_writel(uint32_t addr, uint32_t val, void *p) -{ - svga_writel_common(addr, val, 0, p); -} - - -void -svga_writel_linear(uint32_t addr, uint32_t val, void *p) -{ - svga_writel_common(addr, val, 1, p); -} - - -uint8_t -svga_readb_linear(uint32_t addr, void *p) -{ - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read_linear(addr, p); - - egareads++; - - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xff; - - return *(uint8_t *)&svga->vram[addr & svga->vram_mask]; -} - - -uint16_t -svga_readw_common(uint32_t addr, uint8_t linear, void *p) -{ - svga_t *svga = (svga_t *)p; - - if (!svga->fast) - return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8); - - egareads += 2; - - cycles -= video_timing_read_w; - - if (!linear) - addr = (addr & svga->banked_mask) + svga->read_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xffff; - - return *(uint16_t *)&svga->vram[addr & svga->vram_mask]; -} - - -uint16_t -svga_readw(uint32_t addr, void *p) -{ - return svga_readw_common(addr, 0, p); -} - - -uint16_t -svga_readw_linear(uint32_t addr, void *p) -{ - return svga_readw_common(addr, 1, p); -} - - -uint32_t -svga_readl_common(uint32_t addr, uint8_t linear, void *p) -{ - svga_t *svga = (svga_t *)p; - - if (!svga->fast) { - return svga_read_common(addr, linear, p) | (svga_read_common(addr + 1, linear, p) << 8) | - (svga_read_common(addr + 2, linear, p) << 16) | (svga_read_common(addr + 3, linear, p) << 24); - } - - egareads += 4; - - cycles -= video_timing_read_l; - - if (!linear) - addr = (addr & svga->banked_mask) + svga->read_bank; - addr &= svga->decode_mask; - if (addr >= svga->vram_max) - return 0xffffffff; - - return *(uint32_t *)&svga->vram[addr & svga->vram_mask]; -} - - -uint32_t -svga_readl(uint32_t addr, void *p) -{ - return svga_readl_common(addr, 0, p); -} - - -uint32_t -svga_readl_linear(uint32_t addr, void *p) -{ - return svga_readl_common(addr, 1, p); -} - - -void -svga_add_status_info(char *s, int max_len, void *p) -{ - svga_t *svga = (svga_t *)p; - char temps[128]; - - if (svga->chain4) - strcpy(temps, "SVGA chained (possibly mode 13h)\n"); - else - strcpy(temps, "SVGA unchained (possibly mode-X)\n"); - strncat(s, temps, max_len); - - if (!svga->video_bpp) - strcpy(temps, "SVGA in text mode\n"); - else - sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp); - strncat(s, temps, max_len); - - sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y); - strncat(s, temps, max_len); - - sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames); - svga->frames = 0; - strncat(s, temps, max_len); -} diff --git a/src/video/video - Cópia.c b/src/video/video - Cópia.c deleted file mode 100644 index 32574e37b..000000000 --- a/src/video/video - Cópia.c +++ /dev/null @@ -1,818 +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. - * - * Main video-rendering module. - * - * Video timing settings - - * - * 8-bit - 1mb/sec - * B = 8 ISA clocks - * W = 16 ISA clocks - * L = 32 ISA clocks - * - * Slow 16-bit - 2mb/sec - * B = 6 ISA clocks - * W = 8 ISA clocks - * L = 16 ISA clocks - * - * Fast 16-bit - 4mb/sec - * B = 3 ISA clocks - * W = 3 ISA clocks - * L = 6 ISA clocks - * - * Slow VLB/PCI - 8mb/sec (ish) - * B = 4 bus clocks - * W = 8 bus clocks - * L = 16 bus clocks - * - * Mid VLB/PCI - - * B = 4 bus clocks - * W = 5 bus clocks - * L = 10 bus clocks - * - * Fast VLB/PCI - - * B = 3 bus clocks - * W = 3 bus clocks - * L = 4 bus clocks - * - * Version: @(#)video.c 1.0.26 2018/09/19 - * - * Authors: Sarah Walker, - * Miran Grca, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - */ -#include -#include -#include -#include -#include -#include -#include "../86box.h" -#include "../cpu/cpu.h" -#include "../machine/machine.h" -#include "../io.h" -#include "../mem.h" -#include "../rom.h" -#include "../config.h" -#include "../timer.h" -#include "../plat.h" -#include "video.h" -#include "vid_svga.h" - - -bitmap_t *screen = NULL, - *buffer = NULL, - *buffer32 = NULL; -uint8_t fontdat[2048][8]; /* IBM CGA font */ -uint8_t fontdatm[2048][16]; /* IBM MDA font */ -uint8_t fontdatw[512][32]; /* Wyse700 font */ -uint8_t fontdat8x12[256][16]; /* MDSI Genius font */ -dbcs_font_t *fontdatksc5601 = NULL; /* Korean KSC-5601 font */ -dbcs_font_t *fontdatksc5601_user = NULL; /* Korean KSC-5601 user defined font */ -uint32_t pal_lookup[256]; -int xsize = 1, - ysize = 1; -int cga_palette = 0; -uint32_t *video_6to8 = NULL, - *video_15to32 = NULL, - *video_16to32 = NULL; -int egareads = 0, - egawrites = 0, - changeframecount = 2; -uint8_t rotatevga[8][256]; -int frames = 0; -int fullchange = 0; -uint8_t edatlookup[4][4]; -int overscan_x = 0, - overscan_y = 0; -int video_timing_read_b = 0, - video_timing_read_w = 0, - video_timing_read_l = 0; -int video_timing_write_b = 0, - video_timing_write_w = 0, - video_timing_write_l = 0; -int video_res_x = 0, - video_res_y = 0, - video_bpp = 0; -static int video_force_resize; -int invert_display = 0; -int video_grayscale = 0; -int video_graytype = 0; -static int vid_type; -static const video_timings_t *vid_timings; - - -PALETTE cgapal = { - {0,0,0}, {0,42,0}, {42,0,0}, {42,21,0}, - {0,0,0}, {0,42,42}, {42,0,42}, {42,42,42}, - {0,0,0}, {21,63,21}, {63,21,21}, {63,63,21}, - {0,0,0}, {21,63,63}, {63,21,63}, {63,63,63}, - - {0,0,0}, {0,0,42}, {0,42,0}, {0,42,42}, - {42,0,0}, {42,0,42}, {42,21,00}, {42,42,42}, - {21,21,21}, {21,21,63}, {21,63,21}, {21,63,63}, - {63,21,21}, {63,21,63}, {63,63,21}, {63,63,63}, - - {0,0,0}, {0,21,0}, {0,0,42}, {0,42,42}, - {42,0,21}, {21,10,21}, {42,0,42}, {42,0,63}, - {21,21,21}, {21,63,21}, {42,21,42}, {21,63,63}, - {63,0,0}, {42,42,0}, {63,21,42}, {41,41,41}, - - {0,0,0}, {0,42,42}, {42,0,0}, {42,42,42}, - {0,0,0}, {0,42,42}, {42,0,0}, {42,42,42}, - {0,0,0}, {0,63,63}, {63,0,0}, {63,63,63}, - {0,0,0}, {0,63,63}, {63,0,0}, {63,63,63}, -}; -PALETTE cgapal_mono[6] = { - { /* 0 - green, 4-color-optimized contrast. */ - {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x17,0x05}, - {0x01,0x1a,0x06},{0x02,0x28,0x09},{0x02,0x2c,0x0a}, - {0x03,0x39,0x0d},{0x03,0x3c,0x0e},{0x00,0x07,0x01}, - {0x01,0x13,0x04},{0x01,0x1f,0x07},{0x01,0x23,0x08}, - {0x02,0x31,0x0b},{0x02,0x35,0x0c},{0x05,0x3f,0x11},{0x0d,0x3f,0x17}, - }, - { /* 1 - green, 16-color-optimized contrast. */ - {0x00,0x00,0x00},{0x00,0x0d,0x03},{0x01,0x15,0x05}, - {0x01,0x17,0x05},{0x01,0x21,0x08},{0x01,0x24,0x08}, - {0x02,0x2e,0x0b},{0x02,0x31,0x0b},{0x01,0x22,0x08}, - {0x02,0x28,0x09},{0x02,0x30,0x0b},{0x02,0x32,0x0c}, - {0x03,0x39,0x0d},{0x03,0x3b,0x0e},{0x09,0x3f,0x14},{0x0d,0x3f,0x17}, - }, - { /* 2 - amber, 4-color-optimized contrast. */ - {0x00,0x00,0x00},{0x15,0x05,0x00},{0x20,0x0b,0x00}, - {0x24,0x0d,0x00},{0x33,0x18,0x00},{0x37,0x1b,0x00}, - {0x3f,0x26,0x01},{0x3f,0x2b,0x06},{0x0b,0x02,0x00}, - {0x1b,0x08,0x00},{0x29,0x11,0x00},{0x2e,0x14,0x00}, - {0x3b,0x1e,0x00},{0x3e,0x21,0x00},{0x3f,0x32,0x0a},{0x3f,0x38,0x0d}, - }, - { /* 3 - amber, 16-color-optimized contrast. */ - {0x00,0x00,0x00},{0x15,0x05,0x00},{0x1e,0x09,0x00}, - {0x21,0x0b,0x00},{0x2b,0x12,0x00},{0x2f,0x15,0x00}, - {0x38,0x1c,0x00},{0x3b,0x1e,0x00},{0x2c,0x13,0x00}, - {0x32,0x17,0x00},{0x3a,0x1e,0x00},{0x3c,0x1f,0x00}, - {0x3f,0x27,0x01},{0x3f,0x2a,0x04},{0x3f,0x36,0x0c},{0x3f,0x38,0x0d}, - }, - { /* 4 - grey, 4-color-optimized contrast. */ - {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x15,0x17,0x18}, - {0x18,0x1a,0x1b},{0x24,0x25,0x25},{0x27,0x28,0x28}, - {0x33,0x34,0x32},{0x37,0x38,0x35},{0x09,0x0a,0x0b}, - {0x11,0x12,0x13},{0x1c,0x1e,0x1e},{0x20,0x22,0x22}, - {0x2c,0x2d,0x2c},{0x2f,0x30,0x2f},{0x3c,0x3c,0x38},{0x3f,0x3f,0x3b}, - }, - { /* 5 - grey, 16-color-optimized contrast. */ - {0x00,0x00,0x00},{0x0e,0x0f,0x10},{0x13,0x14,0x15}, - {0x15,0x17,0x18},{0x1e,0x20,0x20},{0x20,0x22,0x22}, - {0x29,0x2a,0x2a},{0x2c,0x2d,0x2c},{0x1f,0x21,0x21}, - {0x23,0x25,0x25},{0x2b,0x2c,0x2b},{0x2d,0x2e,0x2d}, - {0x34,0x35,0x33},{0x37,0x37,0x34},{0x3e,0x3e,0x3a},{0x3f,0x3f,0x3b}, - } -}; - - -const uint32_t shade[5][256] = -{ - {0}, // RGB Color (unused) - {0}, // RGB Grayscale (unused) - { // Amber monitor - 0x000000, 0x060000, 0x090000, 0x0d0000, 0x100000, 0x120100, 0x150100, 0x170100, 0x1a0100, 0x1c0100, 0x1e0200, 0x210200, 0x230200, 0x250300, 0x270300, 0x290300, - 0x2b0400, 0x2d0400, 0x2f0400, 0x300500, 0x320500, 0x340500, 0x360600, 0x380600, 0x390700, 0x3b0700, 0x3d0700, 0x3f0800, 0x400800, 0x420900, 0x440900, 0x450a00, - 0x470a00, 0x480b00, 0x4a0b00, 0x4c0c00, 0x4d0c00, 0x4f0d00, 0x500d00, 0x520e00, 0x530e00, 0x550f00, 0x560f00, 0x581000, 0x591000, 0x5b1100, 0x5c1200, 0x5e1200, - 0x5f1300, 0x601300, 0x621400, 0x631500, 0x651500, 0x661600, 0x671600, 0x691700, 0x6a1800, 0x6c1800, 0x6d1900, 0x6e1a00, 0x701a00, 0x711b00, 0x721c00, 0x741c00, - 0x751d00, 0x761e00, 0x781e00, 0x791f00, 0x7a2000, 0x7c2000, 0x7d2100, 0x7e2200, 0x7f2300, 0x812300, 0x822400, 0x832500, 0x842600, 0x862600, 0x872700, 0x882800, - 0x8a2900, 0x8b2900, 0x8c2a00, 0x8d2b00, 0x8e2c00, 0x902c00, 0x912d00, 0x922e00, 0x932f00, 0x953000, 0x963000, 0x973100, 0x983200, 0x993300, 0x9b3400, 0x9c3400, - 0x9d3500, 0x9e3600, 0x9f3700, 0xa03800, 0xa23900, 0xa33a00, 0xa43a00, 0xa53b00, 0xa63c00, 0xa73d00, 0xa93e00, 0xaa3f00, 0xab4000, 0xac4000, 0xad4100, 0xae4200, - 0xaf4300, 0xb14400, 0xb24500, 0xb34600, 0xb44700, 0xb54800, 0xb64900, 0xb74a00, 0xb94a00, 0xba4b00, 0xbb4c00, 0xbc4d00, 0xbd4e00, 0xbe4f00, 0xbf5000, 0xc05100, - 0xc15200, 0xc25300, 0xc45400, 0xc55500, 0xc65600, 0xc75700, 0xc85800, 0xc95900, 0xca5a00, 0xcb5b00, 0xcc5c00, 0xcd5d00, 0xce5e00, 0xcf5f00, 0xd06000, 0xd26101, - 0xd36201, 0xd46301, 0xd56401, 0xd66501, 0xd76601, 0xd86701, 0xd96801, 0xda6901, 0xdb6a01, 0xdc6b01, 0xdd6c01, 0xde6d01, 0xdf6e01, 0xe06f01, 0xe17001, 0xe27201, - 0xe37301, 0xe47401, 0xe57501, 0xe67602, 0xe77702, 0xe87802, 0xe97902, 0xeb7a02, 0xec7b02, 0xed7c02, 0xee7e02, 0xef7f02, 0xf08002, 0xf18103, 0xf28203, 0xf38303, - 0xf48403, 0xf58503, 0xf68703, 0xf78803, 0xf88903, 0xf98a04, 0xfa8b04, 0xfb8c04, 0xfc8d04, 0xfd8f04, 0xfe9005, 0xff9105, 0xff9205, 0xff9305, 0xff9405, 0xff9606, - 0xff9706, 0xff9806, 0xff9906, 0xff9a07, 0xff9b07, 0xff9d07, 0xff9e08, 0xff9f08, 0xffa008, 0xffa109, 0xffa309, 0xffa409, 0xffa50a, 0xffa60a, 0xffa80a, 0xffa90b, - 0xffaa0b, 0xffab0c, 0xffac0c, 0xffae0d, 0xffaf0d, 0xffb00e, 0xffb10e, 0xffb30f, 0xffb40f, 0xffb510, 0xffb610, 0xffb811, 0xffb912, 0xffba12, 0xffbb13, 0xffbd14, - 0xffbe14, 0xffbf15, 0xffc016, 0xffc217, 0xffc317, 0xffc418, 0xffc619, 0xffc71a, 0xffc81b, 0xffca1c, 0xffcb1d, 0xffcc1e, 0xffcd1f, 0xffcf20, 0xffd021, 0xffd122, - 0xffd323, 0xffd424, 0xffd526, 0xffd727, 0xffd828, 0xffd92a, 0xffdb2b, 0xffdc2c, 0xffdd2e, 0xffdf2f, 0xffe031, 0xffe133, 0xffe334, 0xffe436, 0xffe538, 0xffe739 - }, - { // Green monitor - 0x000000, 0x000400, 0x000700, 0x000900, 0x000b00, 0x000d00, 0x000f00, 0x001100, 0x001300, 0x001500, 0x001600, 0x001800, 0x001a00, 0x001b00, 0x001d00, 0x001e00, - 0x002000, 0x002100, 0x002300, 0x002400, 0x002601, 0x002701, 0x002901, 0x002a01, 0x002b01, 0x002d01, 0x002e01, 0x002f01, 0x003101, 0x003201, 0x003301, 0x003401, - 0x003601, 0x003702, 0x003802, 0x003902, 0x003b02, 0x003c02, 0x003d02, 0x003e02, 0x004002, 0x004102, 0x004203, 0x004303, 0x004403, 0x004503, 0x004703, 0x004803, - 0x004903, 0x004a03, 0x004b04, 0x004c04, 0x004d04, 0x004e04, 0x005004, 0x005104, 0x005205, 0x005305, 0x005405, 0x005505, 0x005605, 0x005705, 0x005806, 0x005906, - 0x005a06, 0x005b06, 0x005d06, 0x005e07, 0x005f07, 0x006007, 0x006107, 0x006207, 0x006308, 0x006408, 0x006508, 0x006608, 0x006708, 0x006809, 0x006909, 0x006a09, - 0x006b09, 0x016c0a, 0x016d0a, 0x016e0a, 0x016f0a, 0x01700b, 0x01710b, 0x01720b, 0x01730b, 0x01740c, 0x01750c, 0x01760c, 0x01770c, 0x01780d, 0x01790d, 0x017a0d, - 0x017b0d, 0x017b0e, 0x017c0e, 0x017d0e, 0x017e0f, 0x017f0f, 0x01800f, 0x018110, 0x028210, 0x028310, 0x028410, 0x028511, 0x028611, 0x028711, 0x028812, 0x028912, - 0x028a12, 0x028a13, 0x028b13, 0x028c13, 0x028d14, 0x028e14, 0x038f14, 0x039015, 0x039115, 0x039215, 0x039316, 0x039416, 0x039417, 0x039517, 0x039617, 0x039718, - 0x049818, 0x049918, 0x049a19, 0x049b19, 0x049c19, 0x049c1a, 0x049d1a, 0x049e1b, 0x059f1b, 0x05a01b, 0x05a11c, 0x05a21c, 0x05a31c, 0x05a31d, 0x05a41d, 0x06a51e, - 0x06a61e, 0x06a71f, 0x06a81f, 0x06a920, 0x06aa20, 0x07aa21, 0x07ab21, 0x07ac21, 0x07ad22, 0x07ae22, 0x08af23, 0x08b023, 0x08b024, 0x08b124, 0x08b225, 0x09b325, - 0x09b426, 0x09b526, 0x09b527, 0x0ab627, 0x0ab728, 0x0ab828, 0x0ab929, 0x0bba29, 0x0bba2a, 0x0bbb2a, 0x0bbc2b, 0x0cbd2b, 0x0cbe2c, 0x0cbf2c, 0x0dbf2d, 0x0dc02d, - 0x0dc12e, 0x0ec22e, 0x0ec32f, 0x0ec42f, 0x0fc430, 0x0fc530, 0x0fc631, 0x10c731, 0x10c832, 0x10c932, 0x11c933, 0x11ca33, 0x11cb34, 0x12cc35, 0x12cd35, 0x12cd36, - 0x13ce36, 0x13cf37, 0x13d037, 0x14d138, 0x14d139, 0x14d239, 0x15d33a, 0x15d43a, 0x16d43b, 0x16d53b, 0x17d63c, 0x17d73d, 0x17d83d, 0x18d83e, 0x18d93e, 0x19da3f, - 0x19db40, 0x1adc40, 0x1adc41, 0x1bdd41, 0x1bde42, 0x1cdf43, 0x1ce043, 0x1de044, 0x1ee145, 0x1ee245, 0x1fe346, 0x1fe446, 0x20e447, 0x20e548, 0x21e648, 0x22e749, - 0x22e74a, 0x23e84a, 0x23e94b, 0x24ea4c, 0x25ea4c, 0x25eb4d, 0x26ec4e, 0x27ed4e, 0x27ee4f, 0x28ee50, 0x29ef50, 0x29f051, 0x2af152, 0x2bf153, 0x2cf253, 0x2cf354, - 0x2df455, 0x2ef455, 0x2ff556, 0x2ff657, 0x30f758, 0x31f758, 0x32f859, 0x32f95a, 0x33fa5a, 0x34fa5b, 0x35fb5c, 0x36fc5d, 0x37fd5d, 0x38fd5e, 0x38fe5f, 0x39ff60 - }, - { // White monitor - 0x000000, 0x010102, 0x020203, 0x020304, 0x030406, 0x040507, 0x050608, 0x060709, 0x07080a, 0x08090c, 0x080a0d, 0x090b0e, 0x0a0c0f, 0x0b0d10, 0x0c0e11, 0x0d0f12, - 0x0e1013, 0x0f1115, 0x101216, 0x111317, 0x121418, 0x121519, 0x13161a, 0x14171b, 0x15181c, 0x16191d, 0x171a1e, 0x181b1f, 0x191c20, 0x1a1d21, 0x1b1e22, 0x1c1f23, - 0x1d2024, 0x1e2125, 0x1f2226, 0x202327, 0x212428, 0x222529, 0x22262b, 0x23272c, 0x24282d, 0x25292e, 0x262a2f, 0x272b30, 0x282c30, 0x292d31, 0x2a2e32, 0x2b2f33, - 0x2c3034, 0x2d3035, 0x2e3136, 0x2f3237, 0x303338, 0x313439, 0x32353a, 0x33363b, 0x34373c, 0x35383d, 0x36393e, 0x373a3f, 0x383b40, 0x393c41, 0x3a3d42, 0x3b3e43, - 0x3c3f44, 0x3d4045, 0x3e4146, 0x3f4247, 0x404348, 0x414449, 0x42454a, 0x43464b, 0x44474c, 0x45484d, 0x46494d, 0x474a4e, 0x484b4f, 0x484c50, 0x494d51, 0x4a4e52, - 0x4b4f53, 0x4c5054, 0x4d5155, 0x4e5256, 0x4f5357, 0x505458, 0x515559, 0x52565a, 0x53575b, 0x54585b, 0x55595c, 0x565a5d, 0x575b5e, 0x585c5f, 0x595d60, 0x5a5e61, - 0x5b5f62, 0x5c6063, 0x5d6164, 0x5e6265, 0x5f6366, 0x606466, 0x616567, 0x626668, 0x636769, 0x64686a, 0x65696b, 0x666a6c, 0x676b6d, 0x686c6e, 0x696d6f, 0x6a6e70, - 0x6b6f70, 0x6c7071, 0x6d7172, 0x6f7273, 0x707374, 0x707475, 0x717576, 0x727677, 0x747778, 0x757879, 0x767979, 0x777a7a, 0x787b7b, 0x797c7c, 0x7a7d7d, 0x7b7e7e, - 0x7c7f7f, 0x7d8080, 0x7e8181, 0x7f8281, 0x808382, 0x818483, 0x828584, 0x838685, 0x848786, 0x858887, 0x868988, 0x878a89, 0x888b89, 0x898c8a, 0x8a8d8b, 0x8b8e8c, - 0x8c8f8d, 0x8d8f8e, 0x8e908f, 0x8f9190, 0x909290, 0x919391, 0x929492, 0x939593, 0x949694, 0x959795, 0x969896, 0x979997, 0x989a98, 0x999b98, 0x9a9c99, 0x9b9d9a, - 0x9c9e9b, 0x9d9f9c, 0x9ea09d, 0x9fa19e, 0xa0a29f, 0xa1a39f, 0xa2a4a0, 0xa3a5a1, 0xa4a6a2, 0xa6a7a3, 0xa7a8a4, 0xa8a9a5, 0xa9aaa5, 0xaaaba6, 0xabaca7, 0xacada8, - 0xadaea9, 0xaeafaa, 0xafb0ab, 0xb0b1ac, 0xb1b2ac, 0xb2b3ad, 0xb3b4ae, 0xb4b5af, 0xb5b6b0, 0xb6b7b1, 0xb7b8b2, 0xb8b9b2, 0xb9bab3, 0xbabbb4, 0xbbbcb5, 0xbcbdb6, - 0xbdbeb7, 0xbebfb8, 0xbfc0b8, 0xc0c1b9, 0xc1c2ba, 0xc2c3bb, 0xc3c4bc, 0xc5c5bd, 0xc6c6be, 0xc7c7be, 0xc8c8bf, 0xc9c9c0, 0xcacac1, 0xcbcbc2, 0xccccc3, 0xcdcdc3, - 0xcecec4, 0xcfcfc5, 0xd0d0c6, 0xd1d1c7, 0xd2d2c8, 0xd3d3c9, 0xd4d4c9, 0xd5d5ca, 0xd6d6cb, 0xd7d7cc, 0xd8d8cd, 0xd9d9ce, 0xdadacf, 0xdbdbcf, 0xdcdcd0, 0xdeddd1, - 0xdfded2, 0xe0dfd3, 0xe1e0d4, 0xe2e1d4, 0xe3e2d5, 0xe4e3d6, 0xe5e4d7, 0xe6e5d8, 0xe7e6d9, 0xe8e7d9, 0xe9e8da, 0xeae9db, 0xebeadc, 0xecebdd, 0xedecde, 0xeeeddf, - 0xefeedf, 0xf0efe0, 0xf1f0e1, 0xf2f1e2, 0xf3f2e3, 0xf4f3e3, 0xf6f3e4, 0xf7f4e5, 0xf8f5e6, 0xf9f6e7, 0xfaf7e8, 0xfbf8e9, 0xfcf9e9, 0xfdfaea, 0xfefbeb, 0xfffcec - } -}; - - -static struct { - int x, y, y1, y2, w, h; - int busy; - int buffer_in_use; - - thread_t *blit_thread; - event_t *wake_blit_thread; - event_t *blit_complete; - event_t *buffer_not_in_use; -} blit_data; - - -static void (*blit_func)(int x, int y, int y1, int y2, int w, int h); - - -static -void blit_thread(void *param) -{ - while (1) { - thread_wait_event(blit_data.wake_blit_thread, -1); - thread_reset_event(blit_data.wake_blit_thread); - - if (blit_func) - blit_func(blit_data.x, blit_data.y, - blit_data.y1, blit_data.y2, - blit_data.w, blit_data.h); - - blit_data.busy = 0; - thread_set_event(blit_data.blit_complete); - } -} - - -void -video_setblit(void(*blit)(int,int,int,int,int,int)) -{ - blit_func = blit; -} - - -void -video_blit_complete(void) -{ - blit_data.buffer_in_use = 0; - - thread_set_event(blit_data.buffer_not_in_use); -} - - -void -video_wait_for_blit(void) -{ - while (blit_data.busy) - thread_wait_event(blit_data.blit_complete, -1); - thread_reset_event(blit_data.blit_complete); -} - - -void -video_wait_for_buffer(void) -{ - while (blit_data.buffer_in_use) - thread_wait_event(blit_data.buffer_not_in_use, -1); - thread_reset_event(blit_data.buffer_not_in_use); -} - - -void -video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h) -{ - if (h <= 0) return; - - video_wait_for_blit(); - - blit_data.busy = 1; - blit_data.buffer_in_use = 1; - blit_data.x = x; - blit_data.y = y; - blit_data.y1 = y1; - blit_data.y2 = y2; - blit_data.w = w; - blit_data.h = h; - - thread_set_event(blit_data.wake_blit_thread); -} - - -void -video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h) -{ - int yy, xx; - - if (h <= 0) return; - - for (yy = 0; yy < h; yy++) - { - if ((y + yy) >= 0 && (y + yy) < buffer->h) - { - for (xx = 0; xx < w; xx++) - *(uint32_t *) &(buffer32->line[y + yy][(x + xx) << 2]) = pal_lookup[buffer->line[y + yy][x + xx]]; - } - } - - video_blit_memtoscreen(x, y, y1, y2, w, h); -} - - -void -cgapal_rebuild(void) -{ - int c; - - /* We cannot do this (yet) if we have not been enabled yet. */ - if (video_6to8 == NULL) return; - - for (c=0; c<256; c++) { - pal_lookup[c] = makecol(video_6to8[cgapal[c].r], - video_6to8[cgapal[c].g], - video_6to8[cgapal[c].b]); - } - - if ((cga_palette > 1) && (cga_palette < 8)) { - if (vid_cga_contrast != 0) { - for (c=0; c<16; c++) { - pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], - video_6to8[cgapal_mono[cga_palette - 2][c].g], - video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], - video_6to8[cgapal_mono[cga_palette - 2][c].g], - video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], - video_6to8[cgapal_mono[cga_palette - 2][c].g], - video_6to8[cgapal_mono[cga_palette - 2][c].b]); - pal_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette - 2][c].r], - video_6to8[cgapal_mono[cga_palette - 2][c].g], - video_6to8[cgapal_mono[cga_palette - 2][c].b]); - } - } else { - for (c=0; c<16; c++) { - pal_lookup[c] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], - video_6to8[cgapal_mono[cga_palette - 1][c].g], - video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c+16] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], - video_6to8[cgapal_mono[cga_palette - 1][c].g], - video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c+32] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], - video_6to8[cgapal_mono[cga_palette - 1][c].g], - video_6to8[cgapal_mono[cga_palette - 1][c].b]); - pal_lookup[c+48] = makecol(video_6to8[cgapal_mono[cga_palette - 1][c].r], - video_6to8[cgapal_mono[cga_palette - 1][c].g], - video_6to8[cgapal_mono[cga_palette - 1][c].b]); - } - } - } - - if (cga_palette == 8) - pal_lookup[0x16] = makecol(video_6to8[42],video_6to8[42],video_6to8[0]); -} - - -void -video_inform(int type, const video_timings_t *ptr) -{ - vid_type = type; - vid_timings = ptr; -} - - -int -video_get_type(void) -{ - return vid_type; -} - - -void -video_update_timing(void) -{ - if (!vid_timings) - pclog("WARNING: vid_timings is NULL\n"); - - if (vid_timings->type == VIDEO_ISA) { - video_timing_read_b = ISA_CYCLES(vid_timings->read_b); - video_timing_read_w = ISA_CYCLES(vid_timings->read_w); - video_timing_read_l = ISA_CYCLES(vid_timings->read_l); - video_timing_write_b = ISA_CYCLES(vid_timings->write_b); - video_timing_write_w = ISA_CYCLES(vid_timings->write_w); - video_timing_write_l = ISA_CYCLES(vid_timings->write_l); - } else { - video_timing_read_b = (int)(bus_timing * vid_timings->read_b); - video_timing_read_w = (int)(bus_timing * vid_timings->read_w); - video_timing_read_l = (int)(bus_timing * vid_timings->read_l); - video_timing_write_b = (int)(bus_timing * vid_timings->write_b); - video_timing_write_w = (int)(bus_timing * vid_timings->write_w); - video_timing_write_l = (int)(bus_timing * vid_timings->write_l); - } - - if (cpu_16bitbus) { - video_timing_read_l = video_timing_read_w * 2; - video_timing_write_l = video_timing_write_w * 2; - } -} - - -int -calc_6to8(int c) -{ - int ic, i8; - double d8; - - ic = c; - if (ic == 64) - ic = 63; - else - ic &= 0x3f; - d8 = (ic / 63.0) * 255.0; - i8 = (int) d8; - - return(i8 & 0xff); -} - - -int -calc_15to32(int c) -{ - int b, g, r; - double db, dg, dr; - - b = (c & 31); - g = ((c >> 5) & 31); - r = ((c >> 10) & 31); - db = (((double) b) / 31.0) * 255.0; - dg = (((double) g) / 31.0) * 255.0; - dr = (((double) r) / 31.0) * 255.0; - b = (int) db; - g = ((int) dg) << 8; - r = ((int) dr) << 16; - - return(b | g | r); -} - - -int -calc_16to32(int c) -{ - int b, g, r; - double db, dg, dr; - - b = (c & 31); - g = ((c >> 5) & 63); - r = ((c >> 11) & 31); - db = (((double) b) / 31.0) * 255.0; - dg = (((double) g) / 63.0) * 255.0; - dr = (((double) r) / 31.0) * 255.0; - b = (int) db; - g = ((int) dg) << 8; - r = ((int) dr) << 16; - - return(b | g | r); -} - - -void -hline(bitmap_t *b, int x1, int y, int x2, uint32_t col) -{ - if (y < 0 || y >= buffer->h) - return; - - if (b == buffer) - memset(&b->line[y][x1], col, x2 - x1); - else - memset(&((uint32_t *)b->line[y])[x1], col, (x2 - x1) * 4); -} - - -void -blit(bitmap_t *src, bitmap_t *dst, int x1, int y1, int x2, int y2, int xs, int ys) -{ -} - - -void -stretch_blit(bitmap_t *src, bitmap_t *dst, int x1, int y1, int xs1, int ys1, int x2, int y2, int xs2, int ys2) -{ -} - - -void -rectfill(bitmap_t *b, int x1, int y1, int x2, int y2, uint32_t col) -{ -} - - -void -set_palette(PALETTE p) -{ -} - - -void -destroy_bitmap(bitmap_t *b) -{ - if (b->dat != NULL) - free(b->dat); - free(b); -} - - -bitmap_t * -create_bitmap(int x, int y) -{ - bitmap_t *b = malloc(sizeof(bitmap_t) + (y * sizeof(uint8_t *))); - int c; - - b->dat = malloc(x * y * 4); - for (c = 0; c < y; c++) - b->line[c] = b->dat + (c * x * 4); - b->w = x; - b->h = y; - - return(b); -} - - -void -video_init(void) -{ - int c, d, e; - - /* Account for overscan. */ - buffer32 = create_bitmap(2048, 2048); - - buffer = create_bitmap(2048, 2048); - for (c = 0; c < 64; c++) { - cgapal[c + 64].r = (((c & 4) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 64].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 64].b = (((c & 1) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - if ((c & 0x17) == 6) - cgapal[c + 64].g >>= 1; - } - for (c = 0; c < 64; c++) { - cgapal[c + 128].r = (((c & 4) ? 2 : 0) | ((c & 0x20) ? 1 : 0)) * 21; - cgapal[c + 128].g = (((c & 2) ? 2 : 0) | ((c & 0x10) ? 1 : 0)) * 21; - cgapal[c + 128].b = (((c & 1) ? 2 : 0) | ((c & 0x08) ? 1 : 0)) * 21; - } - - for (c = 0; c < 256; c++) { - e = c; - for (d = 0; d < 8; d++) { - rotatevga[d][c] = e; - e = (e >> 1) | ((e & 1) ? 0x80 : 0); - } - } - for (c = 0; c < 4; c++) { - for (d = 0; d < 4; d++) { - edatlookup[c][d] = 0; - if (c & 1) edatlookup[c][d] |= 1; - if (d & 1) edatlookup[c][d] |= 2; - if (c & 2) edatlookup[c][d] |= 0x10; - if (d & 2) edatlookup[c][d] |= 0x20; - } - } - - video_6to8 = malloc(4 * 256); - for (c = 0; c < 256; c++) - video_6to8[c] = calc_6to8(c); - video_15to32 = malloc(4 * 65536); -#if 0 - for (c = 0; c < 65536; c++) - video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19); -#endif - for (c = 0; c < 65536; c++) - video_15to32[c] = calc_15to32(c); - - video_16to32 = malloc(4 * 65536); -#if 0 - for (c = 0; c < 65536; c++) - video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19); -#endif - for (c = 0; c < 65536; c++) - video_16to32[c] = calc_16to32(c); - - blit_data.wake_blit_thread = thread_create_event(); - blit_data.blit_complete = thread_create_event(); - blit_data.buffer_not_in_use = thread_create_event(); - blit_data.blit_thread = thread_create(blit_thread, NULL); -} - - -void -video_close(void) -{ - thread_kill(blit_data.blit_thread); - thread_destroy_event(blit_data.buffer_not_in_use); - thread_destroy_event(blit_data.blit_complete); - thread_destroy_event(blit_data.wake_blit_thread); - - free(video_6to8); - free(video_15to32); - free(video_16to32); - - destroy_bitmap(buffer); - destroy_bitmap(buffer32); - - if (fontdatksc5601) { - free(fontdatksc5601); - fontdatksc5601 = NULL; - } - - if (fontdatksc5601_user) { - free(fontdatksc5601_user); - fontdatksc5601_user = NULL; - } -} - - -uint8_t -video_force_resize_get(void) -{ - return video_force_resize; -} - - -void -video_force_resize_set(uint8_t res) -{ - video_force_resize = res; -} - - -void -loadfont(wchar_t *s, int format) -{ - FILE *f; - int c,d; - - f = rom_fopen(s, L"rb"); - if (f == NULL) - return; - - switch (format) { - case 0: /* MDA */ - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d] = fgetc(f); - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d+8] = fgetc(f); - (void)fseek(f, 4096+2048, SEEK_SET); - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); - break; - - case 1: /* PC200 */ - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d] = fgetc(f); - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdatm[c][d+8] = fgetc(f); - (void)fseek(f, 4096, SEEK_SET); - for (c=0; c<256; c++) { - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); - for (d=0; d<8; d++) (void)fgetc(f); - } - break; - - default: - case 2: /* CGA */ - for (c=0; c<256; c++) - for (d=0; d<8; d++) - fontdat[c][d] = fgetc(f); - break; - - case 3: /* Wyse 700 */ - for (c=0; c<512; c++) - for (d=0; d<32; d++) - fontdatw[c][d] = fgetc(f); - break; - - case 4: /* MDSI Genius */ - for (c=0; c<256; c++) - for (d=0; d<16; d++) - fontdat8x12[c][d] = fgetc(f); - break; - - case 5: /* Toshiba 3100e */ - for (d = 0; d < 2048; d += 512) /* Four languages... */ - { - for (c = d; c < d+256; c++) - { - fread(&fontdatm[c][8], 1, 8, f); - } - for (c = d+256; c < d+512; c++) - { - fread(&fontdatm[c][8], 1, 8, f); - } - for (c = d; c < d+256; c++) - { - fread(&fontdatm[c][0], 1, 8, f); - } - for (c = d+256; c < d+512; c++) - { - fread(&fontdatm[c][0], 1, 8, f); - } - fseek(f, 4096, SEEK_CUR); /* Skip blank section */ - for (c = d; c < d+256; c++) - { - fread(&fontdat[c][0], 1, 8, f); - } - for (c = d+256; c < d+512; c++) - { - fread(&fontdat[c][0], 1, 8, f); - } - } - break; - - case 6: /* Korean KSC-5601 */ - if (!fontdatksc5601) - fontdatksc5601 = malloc(16384 * sizeof(dbcs_font_t)); - - if (!fontdatksc5601_user) - fontdatksc5601_user = malloc(192 * sizeof(dbcs_font_t)); - - for (c = 0; c < 16384; c++) - { - for (d = 0; d < 32; d++) - fontdatksc5601[c].chr[d]=getc(f); - } - break; - } - - (void)fclose(f); -} - - -uint32_t -video_color_transform(uint32_t color) -{ - uint8_t *clr8 = (uint8_t *) &color; - /* if (!video_grayscale && !invert_display) - return color; */ - if (video_grayscale) { - if (video_graytype) { - if (video_graytype == 1) - color = ((54 * (uint32_t)clr8[2]) + (183 * (uint32_t)clr8[1]) + (18 * (uint32_t)clr8[0])) / 255; - else - color = ((uint32_t)clr8[2] + (uint32_t)clr8[1] + (uint32_t)clr8[0]) / 3; - } else - color = ((76 * (uint32_t)clr8[2]) + (150 * (uint32_t)clr8[1]) + (29 * (uint32_t)clr8[0])) / 255; - switch (video_grayscale) { - case 2: case 3: case 4: - color = (uint32_t) shade[video_grayscale][color]; - break; - default: - clr8[3] = 0; - clr8[0] = color; - clr8[1] = clr8[2] = clr8[0]; - break; - } - } - if (invert_display) - color ^= 0x00ffffff; - return color; -} - -void -video_transform_copy(uint32_t *dst, uint32_t *src, int len) -{ - int i; - - for (i = 0; i < len; i++) { - *dst = video_color_transform(*src); - dst++; - src++; - } -} diff --git a/src/video/video - Cópia.h b/src/video/video - Cópia.h deleted file mode 100644 index 78742a226..000000000 --- a/src/video/video - Cópia.h +++ /dev/null @@ -1,283 +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. - * - * Definitions for the video controller module. - * - * Version: @(#)video.h 1.0.35 2018/09/19 - * - * Authors: Sarah Walker, - * Miran Grca, - * Fred N. van Kempen, - * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2017,2018 Fred N. van Kempen. - */ -#ifndef EMU_VIDEO_H -# define EMU_VIDEO_H - - -#define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) -#define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16)) - - -enum { - GFX_NONE = 0, - GFX_INTERNAL, - GFX_CGA, - GFX_COMPAQ_CGA, /* Compaq CGA */ - GFX_COMPAQ_CGA_2, /* Compaq CGA 2 */ - GFX_COLORPLUS, /* Plantronics ColorPlus */ - GFX_WY700, /* Wyse 700 */ - GFX_MDA, - GFX_GENIUS, /* MDSI Genius */ - GFX_HERCULES, - GFX_HERCULESPLUS, - GFX_INCOLOR, /* Hercules InColor */ - GFX_EGA, /* Using IBM EGA BIOS */ - GFX_COMPAQ_EGA, /* Compaq EGA */ - GFX_SUPER_EGA, /* Using Chips & Technologies SuperEGA BIOS */ - GFX_VGA, /* IBM VGA */ - GFX_TVGA, /* Using Trident TVGA8900D BIOS */ - GFX_ET4000_ISA, /* Tseng ET4000 */ - GFX_ET4000_MCA, /* Tseng ET4000 */ - GFX_TGKOREANVGA, /*Trigem Korean VGA(Tseng ET4000AX)*/ - GFX_ET4000W32_CARDEX_VLB, /* Tseng ET4000/W32p (Cardex) VLB */ - GFX_ET4000W32_CARDEX_PCI, /* Tseng ET4000/W32p (Cardex) PCI */ -#if defined(DEV_BRANCH) && defined(USE_STEALTH32) - GFX_ET4000W32_VLB, /* Tseng ET4000/W32p (Diamond Stealth 32) VLB */ - GFX_ET4000W32_PCI, /* Tseng ET4000/W32p (Diamond Stealth 32) PCI */ -#endif - GFX_BAHAMAS64_VLB, /* S3 Vision864 (Paradise Bahamas 64) VLB */ - GFX_BAHAMAS64_PCI, /* S3 Vision864 (Paradise Bahamas 64) PCI */ - GFX_N9_9FX_VLB, /* S3 764/Trio64 (Number Nine 9FX) VLB */ - GFX_N9_9FX_PCI, /* S3 764/Trio64 (Number Nine 9FX) PCI */ - GFX_TGUI9400CXI, /* Trident TGUI9400CXi VLB */ - GFX_TGUI9440_VLB, /* Trident TGUI9440AGi VLB */ - GFX_TGUI9440_PCI, /* Trident TGUI9440AGi PCI */ - GFX_ATIKOREANVGA, /*ATI Korean VGA (28800-5)*/ - GFX_VGA88, /* ATI VGA-88 (18800-1) */ - GFX_VGAEDGE16, /* ATI VGA Edge-16 (18800-1) */ - GFX_VGACHARGER, /* ATI VGA Charger (28800-5) */ -#if defined(DEV_BRANCH) && defined(USE_VGAWONDER) - GFX_VGAWONDER, /* Compaq ATI VGA Wonder (18800) */ -#endif - GFX_VGAWONDERXL, /* Compaq ATI VGA Wonder XL (28800-5) */ -#if defined(DEV_BRANCH) && defined(USE_XL24) - GFX_VGAWONDERXL24, /* Compaq ATI VGA Wonder XL24 (28800-6) */ -#endif - GFX_MACH64GX_ISA, /* ATI Graphics Pro Turbo (Mach64) ISA */ - GFX_MACH64GX_VLB, /* ATI Graphics Pro Turbo (Mach64) VLB */ - GFX_MACH64GX_PCI, /* ATI Graphics Pro Turbo (Mach64) PCI */ - GFX_MACH64VT2, /* ATI Mach64 VT2 */ - GFX_CL_GD5424_ISA, /* Cirrus Logic CL-GD 5424 ISA */ - GFX_CL_GD5424_VLB, /* Cirrus Logic CL-GD 5424 VLB */ - GFX_CL_GD5426_VLB, /* Diamond SpeedStar PRO (Cirrus Logic CL-GD 5426) VLB */ - GFX_CL_GD5428_ISA, /* Cirrus Logic CL-GD 5428 ISA */ - GFX_CL_GD5428_VLB, /* Cirrus Logic CL-GD 5428 VLB */ - GFX_CL_GD5429_ISA, /* Cirrus Logic CL-GD 5429 ISA */ - GFX_CL_GD5429_VLB, /* Cirrus Logic CL-GD 5429 VLB */ - GFX_CL_GD5430_VLB, /* Diamond SpeedStar PRO SE (Cirrus Logic CL-GD 5430) VLB */ - GFX_CL_GD5430_PCI, /* Cirrus Logic CL-GD 5430 PCI */ - GFX_CL_GD5434_ISA, /* Cirrus Logic CL-GD 5434 ISA */ - GFX_CL_GD5434_VLB, /* Cirrus Logic CL-GD 5434 VLB */ - GFX_CL_GD5434_PCI, /* Cirrus Logic CL-GD 5434 PCI */ - GFX_CL_GD5436_PCI, /* Cirrus Logic CL-GD 5436 PCI */ - GFX_CL_GD5440_PCI, /* Cirrus Logic CL-GD 5440 PCI */ - GFX_CL_GD5446_PCI, /* Cirrus Logic CL-GD 5446 PCI */ - GFX_CL_GD5446_STB_PCI, /* STB Nitro 64V (Cirrus Logic CL-GD 5446) PCI */ - GFX_CL_GD5480_PCI, /* Cirrus Logic CL-GD 5480 PCI */ - GFX_EXPERTCOLOR_VLB, /* S3 Vision868 (ExpertColor DSV3868P CF55) VLB */ - GFX_EXPERTCOLOR_PCI, /* S3 Vision868 (ExpertColor DSV3868P CF55) PCI */ - GFX_OTI037C, /* Oak OTI-037C */ - GFX_OTI067, /* Oak OTI-067 */ - GFX_OTI077, /* Oak OTI-077 */ - GFX_PVGA1A, /* Paradise PVGA1A Standalone */ - GFX_WD90C11, /* Paradise WD90C11-LR Standalone */ - GFX_WD90C30, /* Paradise WD90C30-LR Standalone */ - GFX_PHOENIX_VISION864_VLB, /* S3 Vision864 (Phoenix) VLB */ - GFX_PHOENIX_VISION864_PCI, /* S3 Vision864 (Phoenix) PCI */ - GFX_PHOENIX_TRIO32_VLB, /* S3 732/Trio32 (Phoenix) VLB */ - GFX_PHOENIX_TRIO32_PCI, /* S3 732/Trio32 (Phoenix) PCI */ - GFX_PHOENIX_TRIO64_VLB, /* S3 764/Trio64 (Phoenix) VLB */ - GFX_PHOENIX_TRIO64_PCI, /* S3 764/Trio64 (Phoenix) PCI */ - GFX_STEALTH64_VLB, /* S3 Trio64 (Diamond Stealth 64) VLB */ - GFX_STEALTH64_PCI, /* S3 Trio64 (Diamond Stealth 64) PCI */ -#if defined(DEV_BRANCH) && defined(USE_TI) - GFX_TICF62011, /* TI CF62011 */ -#endif - GFX_VIRGE_VLB, /* S3 Virge VLB */ - GFX_VIRGE_PCI, /* S3 Virge PCI */ - GFX_VIRGEDX_VLB, /* S3 Virge/DX VLB */ - GFX_VIRGEDX_PCI, /* S3 Virge/DX PCI */ - GFX_VIRGEDX4_VLB, /* S3 Virge/DX (VBE 2.0) VLB */ - GFX_VIRGEDX4_PCI, /* S3 Virge/DX (VBE 2.0) PCI */ - GFX_VIRGEVX_VLB, /* S3 Virge/VX VLB */ - GFX_VIRGEVX_PCI, /* S3 Virge/VX PCI */ - - GFX_MAX -}; - -enum { - FULLSCR_SCALE_FULL = 0, - FULLSCR_SCALE_43, - FULLSCR_SCALE_SQ, - FULLSCR_SCALE_INT, - FULLSCR_SCALE_KEEPRATIO -}; - - -#ifdef __cplusplus -extern "C" { -#endif - - -enum { - VIDEO_ISA = 0, - VIDEO_MCA, - VIDEO_BUS -}; - -#define VIDEO_FLAG_TYPE_CGA 0 -#define VIDEO_FLAG_TYPE_MDA 1 -#define VIDEO_FLAG_TYPE_SPECIAL 2 -#define VIDEO_FLAG_TYPE_MASK 3 - -typedef struct { - int type; - int write_b, write_w, write_l; - int read_b, read_w, read_l; -} video_timings_t; - -typedef struct { - int w, h; - uint8_t *dat; - uint8_t *line[2048]; -} bitmap_t; - -typedef struct { - uint8_t r, g, b; -} rgb_t; - -typedef struct { - uint8_t chr[32]; -} dbcs_font_t; - -typedef rgb_t PALETTE[256]; - - -extern int gfx_present[GFX_MAX]; -extern int egareads, - egawrites; -extern int changeframecount; - -extern bitmap_t *screen, - *buffer, - *buffer32; -extern PALETTE cgapal, - cgapal_mono[6]; -extern uint32_t pal_lookup[256]; -extern int video_fullscreen, - video_fullscreen_scale, - video_fullscreen_first; -extern int fullchange; -extern uint8_t fontdat[2048][8]; -extern uint8_t fontdatm[2048][16]; -extern dbcs_font_t *fontdatksc5601; -extern dbcs_font_t *fontdatksc5601_user; -extern uint32_t *video_6to8, - *video_15to32, - *video_16to32; -extern int xsize,ysize; -extern int enable_overscan; -extern int overscan_x, - overscan_y; -extern int force_43; -extern int video_timing_read_b, - video_timing_read_w, - video_timing_read_l; -extern int video_timing_write_b, - video_timing_write_w, - video_timing_write_l; -extern int video_res_x, - video_res_y, - video_bpp; -extern int vid_resize; -extern int cga_palette; -extern int vid_cga_contrast; -extern int video_grayscale; -extern int video_graytype; - -extern float cpuclock; -extern int emu_fps, - frames; -extern int readflash; - - -/* Function handler pointers. */ -extern void (*video_recalctimings)(void); - - -/* Table functions. */ -extern int video_card_available(int card); -extern char *video_card_getname(int card); -#ifdef EMU_DEVICE_H -extern const device_t *video_card_getdevice(int card); -#endif -extern int video_card_has_config(int card); -extern int video_card_getid(char *s); -extern int video_old_to_new(int card); -extern int video_new_to_old(int card); -extern char *video_get_internal_name(int card); -extern int video_get_video_from_internal_name(char *s); -extern int video_is_mda(void); -extern int video_is_cga(void); -extern int video_is_ega_vga(void); -extern void video_inform(int type, const video_timings_t *ptr); -extern int video_get_type(void); - - -extern void video_setblit(void(*blit)(int,int,int,int,int,int)); -extern void video_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h); -extern void video_blit_memtoscreen_8(int x, int y, int y1, int y2, int w, int h); -extern void video_blit_complete(void); -extern void video_wait_for_blit(void); -extern void video_wait_for_buffer(void); - -extern bitmap_t *create_bitmap(int w, int h); -extern void destroy_bitmap(bitmap_t *b); -extern void cgapal_rebuild(void); -extern void hline(bitmap_t *b, int x1, int y, int x2, uint32_t col); -extern void updatewindowsize(int x, int y); - -extern void video_init(void); -extern void video_close(void); -extern void video_font_reset(void); -extern void video_reset(int card); -extern uint8_t video_force_resize_get(void); -extern void video_force_resize_set(uint8_t res); -extern void video_update_timing(void); - -extern void loadfont(wchar_t *s, int format); - -extern int get_actual_size_x(void); -extern int get_actual_size_y(void); - -#ifdef ENABLE_VRAM_DUMP -extern void svga_dump_vram(void); -#endif - -extern uint32_t video_color_transform(uint32_t color); -extern void video_transform_copy(uint32_t *dst, uint32_t *src, int len); - -#ifdef __cplusplus -} -#endif - - -#endif /*EMU_VIDEO_H*/ diff --git a/src/win/Makefile.mingw$ b/src/win/Makefile.mingw$ deleted file mode 100644 index 682df0cab..000000000 --- a/src/win/Makefile.mingw$ +++ /dev/null @@ -1,644 +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. -# -# Makefile for Win32 (MinGW32) environment. -# -# Version: @(#)Makefile.mingw 1.0.123 2018/08/02 -# -# Authors: Miran Grca, -# Fred N. van Kempen, -# - -# Various compile-time options. -ifndef STUFF -STUFF := -endif - -# Add feature selections here. -ifndef EXTRAS -EXTRAS := -endif - -ifndef DEV_BUILD -DEV_BUILD := n -endif - -ifeq ($(DEV_BUILD), y) - ifndef DEBUG - DEBUG := y - endif - ifndef DEV_BRANCH - DEV_BRANCH := y - endif - ifndef AMD_K - AMD_K := y - endif - ifndef CRASHDUMP - CRASHDUMP := y - endif - ifndef D2D - D2D := y - endif - ifndef I686 - I686 := y - endif - ifndef LASERXT - LASERXT := y - endif - ifndef MRTHOR - MRTHOR := y - endif - ifndef PAS16 - PAS16 := y - endif - ifndef PORTABLE3 - PORTABLE3 := y - endif - ifndef STEALTH32 - STEALTH32 := y - endif - ifndef VNC - VNC := y - endif - ifndef XL24 - XL24 := y - endif -else - ifndef DEBUG - DEBUG := n - endif - ifndef DEV_BRANCH - DEV_BRANCH := n - endif - ifndef AMD_K - AMD_K := n - endif - ifndef CRASHDUMP - CRASHDUMP := n - endif - ifndef D2D - D2D := n - endif - ifndef I686 - I686 := n - endif - ifndef LASERXT - LASERXT := n - endif - ifndef MRTHOR - MRTHOR := n - endif - ifndef PAS16 - PAS16 := n - endif - ifndef PORTABLE3 - PORTABLE3 := n - endif - ifndef STEALTH32 - STEALTH32 := n - endif - ifndef VGAWONDER - VGAWONDER := n - endif - ifndef VNC - VNC := n - endif - ifndef XL24 - XL24 := n - endif -endif - -# Defaults for several build options (possibly defined in a chained file.) -ifndef AUTODEP -AUTODEP := n -endif -ifndef OPTIM -OPTIM := n -endif -ifndef RELEASE -RELEASE := n -endif -ifndef X64 -X64 := n -endif -ifndef USB -USB := n -endif -ifndef RDP -RDP := n -endif -ifndef OPENAL -OPENAL := y -endif -ifndef FLUIDSYNTH -FLUIDSYNTH := y -endif -ifndef MUNT -MUNT := y -endif -ifndef DYNAREC -DYNAREC := y -endif - - -# Name of the executable. -ifndef PROG - PROG := 86Box -endif - - -######################################################################### -# Nothing should need changing from here on.. # -######################################################################### -VPATH := $(EXPATH) . cpu \ - cdrom disk floppy game machine \ - sound \ - sound/munt sound/munt/c_interface sound/munt/sha1 \ - sound/munt/srchelper \ - sound/resid-fp \ - scsi video network network/slirp win -ifeq ($(X64), y) -CPP := g++ -m64 -CC := gcc -m64 -else -CPP := g++ -m32 -CC := gcc -m32 -endif -WINDRES := windres -DEPS = -MMD -MF $*.d -c $< -DEPFILE := win/.depends - -# Set up the correct toolchain flags. -OPTS := $(EXTRAS) $(STUFF) -ifdef EXFLAGS -OPTS += $(EXFLAGS) -endif -ifdef EXINC -OPTS += -I$(EXINC) -endif -ifeq ($(X64), y) - ifeq ($(OPTIM), y) - DFLAGS := -march=corei7 - else - DFLAGS := - endif -else - ifeq ($(OPTIM), y) - DFLAGS := -march=corei7 - else - DFLAGS := -march=i686 - endif -endif -ifeq ($(DEBUG), y) - DFLAGS += -ggdb -DDEBUG - AOPTIM := - ifndef COPTIM - COPTIM := -Og - endif -else - DFLAGS += -g0 - ifeq ($(OPTIM), y) - AOPTIM := -mtune=corei7 - ifndef COPTIM -# COPTIM := -O3 -flto - COPTIM := -O3 - endif - else - ifndef COPTIM - COPTIM := -O3 - endif - endif -endif -AFLAGS := -msse2 -mfpmath=sse -RFLAGS := --input-format=rc -O coff -ifeq ($(RELEASE), y) -OPTS += -DRELEASE_BUILD -RFLAGS += -DRELEASE_BUILD -endif -ifeq ($(VRAMDUMP), y) -OPTS += -DENABLE_VRAM_DUMP -RFLAGS += -DENABLE_VRAM_DUMP -endif -ifeq ($(X64), y) -PLATCG := codegen_x86-64.o -CGOPS := codegen_ops_x86-64.h -VCG := vid_voodoo_codegen_x86-64.h -else -PLATCG := codegen_x86.o -CGOPS := codegen_ops_x86.h -VCG := vid_voodoo_codegen_x86.h -endif - - -# Optional modules. -ifeq ($(DYNAREC), y) -OPTS += -DUSE_DYNAREC -RFLAGS += -DUSE_DYNAREC -DYNARECOBJ := 386_dynarec_ops.o \ - codegen.o \ - codegen_ops.o \ - codegen_timing_common.o codegen_timing_486.o \ - codegen_timing_686.o codegen_timing_pentium.o \ - codegen_timing_winchip.o $(PLATCG) -endif - -UIOBJ := win_ui.o win_stbar.o \ - win_ddraw.o win_d2d.o win_d3d.o win_sdl.o \ - win_dialog.o win_about.o \ - win_settings.o win_devconf.o win_snd_gain.o \ - win_new_floppy.o win_jsconf.o - -ifeq ($(OPENAL), y) -OPTS += -DUSE_OPENAL -endif -ifeq ($(FLUIDSYNTH), y) -OPTS += -DUSE_FLUIDSYNTH -FSYNTHOBJ := midi_fluidsynth.o -endif - -ifeq ($(MUNT), y) -OPTS += -DUSE_MUNT -MUNTOBJ := midi_mt32.o \ - Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \ - LA32FloatWaveGenerator.o LA32WaveGenerator.o \ - MidiStreamParser.o Part.o Partial.o PartialManager.o \ - Poly.o ROMInfo.o SampleRateConverter_dummy.o Synth.o \ - Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o -endif - -ifeq ($(D2D), y) -OPTS += -DUSE_D2D -RFLAGS += -DUSE_D2D -D2DLIB := -ld2d1 -endif - -ifeq ($(VNC), y) -OPTS += -DUSE_VNC -RFLAGS += -DUSE_VNC - ifneq ($(VNC_PATH), ) - OPTS += -I$(VNC_PATH)\INCLUDE - VNCLIB := -L$(VNC_PATH)\LIB - endif -VNCLIB += -lvncserver -VNCOBJ := vnc.o vnc_keymap.o -endif - -ifeq ($(RDP), y) -OPTS += -DUSE_RDP -RFLAGS += -DUSE_RDP - ifneq ($(RDP_PATH), ) - OPTS += -I$(RDP_PATH)\INCLUDE - RDPLIB := -L$(RDP_PATH)\LIB - endif -RDPLIB += -lrdp -RDPOBJ := rdp.o -endif - -# Options for the DEV branch. -ifeq ($(DEV_BRANCH), y) -OPTS += -DDEV_BRANCH -DEVBROBJ := - -ifeq ($(AMD_K), y) -OPTS += -DUSE_AMD_K -endif - -ifeq ($(CRASHDUMPOBJ), y) -OPTS += -DUSE_CRASHDUMP -DEVBROBJ += win_crashdump.o -endif - -ifeq ($(I686), y) -OPTS += -DUSE_I686 -endif - -ifeq ($(LASERXT), y) -OPTS += -DUSE_LASERXT -DEVBROBJ += m_xt_laserxt.o -endif - -ifeq ($(MRTHOR), y) -OPTS += -DUSE_MRTHOR -endif - -ifeq ($(PAS16), y) -OPTS += -DUSE_PAS16 -DEVBROBJ += snd_pas16.o -endif - -ifeq ($(PORTABLE3), y) -OPTS += -DUSE_PORTABLE3 -endif - -ifeq ($(STEALTH32), y) -OPTS += -DUSE_STEALTH32 -DEVBROBJ += vid_icd2061.o -endif - -ifeq ($(VGAWONDER), y) -OPTS += -DUSE_VGAWONDER -endif - -ifeq ($(XL24), y) -OPTS += -DUSE_XL24 -endif - -endif - - -# Options for works-in-progress. -ifndef SERIAL -SERIAL := serial.o -endif - - -# Final versions of the toolchain flags. -CFLAGS := $(OPTS) $(DFLAGS) $(COPTIM) $(AOPTIM) \ - $(AFLAGS) -m32 -fomit-frame-pointer -mstackrealign -Wall \ - -fno-strict-aliasing - - -######################################################################### -# Create the (final) list of objects to build. # -######################################################################### -MAINOBJ := pc.o config.o random.o timer.o io.o dma.o nmi.o pic.o \ - pit.o ppi.o pci.o mca.o mcr.o mem.o memregs.o rom.o \ - device.o nvr.o nvr_at.o nvr_ps2.o $(VNCOBJ) $(RDPOBJ) - -INTELOBJ := intel.o \ - intel_flash.o \ - intel_sio.o intel_piix.o - -CPUOBJ := cpu.o cpu_table.o \ - 808x.o 386.o 386_dynarec.o \ - x86seg.o x87.o \ - $(DYNARECOBJ) - -MCHOBJ := machine.o machine_table.o \ - m_xt.o m_xt_compaq.o \ - m_xt_t1000.o m_xt_t1000_vid.o \ - m_xt_xi8088.o \ - m_pcjr.o \ - m_amstrad.o \ - m_europc.o \ - m_olivetti_m24.o m_tandy.o \ - m_at.o \ - m_at_ali1429.o m_at_commodore.o \ - m_at_neat.o m_at_headland.o \ - m_at_t3100e.o m_at_t3100e_vid.o \ - m_ps1.o m_ps1_hdc.o \ - m_ps2_isa.o m_ps2_mca.o \ - m_at_opti495.o m_at_scat.o \ - m_at_compaq.o m_at_wd76c10.o \ - m_at_sis_85c471.o m_at_sis_85c496.o \ - m_at_4x0.o - -DEVOBJ := bugger.o lpt.o $(SERIAL) \ - sio_fdc37c66x.o sio_fdc37c669.o sio_fdc37c93x.o \ - sio_pc87306.o sio_w83877f.o sio_um8669f.o \ - keyboard.o \ - keyboard_xt.o keyboard_at.o \ - gameport.o \ - joystick_standard.o joystick_ch_flightstick_pro.o \ - joystick_sw_pad.o joystick_tm_fcs.o \ - mouse.o \ - mouse_bus.o \ - mouse_serial.o mouse_ps2.o - -FDDOBJ := fdd.o fdc.o fdi2raw.o \ - fdd_common.o fdd_86f.o \ - fdd_fdi.o fdd_imd.o fdd_img.o fdd_json.o \ - fdd_td0.o - -HDDOBJ := hdd.o \ - hdd_image.o hdd_table.o \ - hdc.o \ - hdc_mfm_xt.o hdc_mfm_at.o \ - hdc_xta.o \ - hdc_esdi_at.o hdc_esdi_mca.o \ - hdc_xtide.o hdc_ide.o - -CDROMOBJ := cdrom.o \ - cdrom_dosbox.o cdrom_image.o cdrom_null.o - -ZIPOBJ := zip.o - -ifeq ($(USB), y) -USBOBJ := usb.o -endif - -SCSIOBJ := scsi.o \ - scsi_bus.o scsi_device.o \ - scsi_disk.o \ - scsi_x54x.o \ - scsi_aha154x.o scsi_buslogic.o \ - scsi_ncr5380.o scsi_ncr53c810.o - -NETOBJ := network.o \ - net_pcap.o \ - net_slirp.o \ - bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o \ - ip_input.o queue.o tcp_input.o debug.o ip_output.o \ - sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o \ - net_dp8390.o \ - net_3c503.o net_ne2000.o \ - net_wd8003.o - -SNDOBJ := sound.o \ - openal.o \ - snd_opl.o snd_dbopl.o \ - dbopl.o nukedopl.o \ - snd_resid.o \ - convolve.o convolve-sse.o envelope.o extfilt.o \ - filter.o pot.o sid.o voice.o wave6581__ST.o \ - wave6581_P_T.o wave6581_PS_.o wave6581_PST.o \ - wave8580__ST.o wave8580_P_T.o wave8580_PS_.o \ - wave8580_PST.o wave.o \ - midi.o midi_system.o \ - snd_speaker.o \ - snd_pssj.o \ - snd_lpt_dac.o snd_lpt_dss.o \ - snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \ - snd_cms.o \ - snd_gus.o \ - snd_sb.o snd_sb_dsp.o \ - snd_emu8k.o snd_mpu401.o \ - snd_sn76489.o snd_ssi2001.o \ - snd_wss.o \ - snd_ym7128.o - -VIDOBJ := video.o \ - vid_table.o \ - vid_cga.o vid_cga_comp.o \ - vid_compaq_cga.o \ - vid_mda.o \ - vid_hercules.o vid_herculesplus.o vid_incolor.o \ - vid_colorplus.o \ - vid_genius.o \ - vid_wy700.o \ - vid_ega.o vid_ega_render.o \ - vid_svga.o vid_svga_render.o \ - vid_vga.o \ - vid_ati_eeprom.o \ - vid_ati18800.o vid_ati28800.o \ - vid_ati_mach64.o vid_ati68860_ramdac.o \ - vid_ics2595.o \ - vid_cl54xx.o \ - vid_et4000.o vid_sc1502x_ramdac.o \ - vid_et4000w32.o vid_stg_ramdac.o \ - vid_oak_oti.o \ - vid_paradise.o \ - vid_ti_cf62011.o \ - vid_tvga.o \ - vid_tgui9440.o vid_tkd8001_ramdac.o \ - vid_s3.o vid_s3_virge.o \ - vid_sdac_ramdac.o \ - vid_voodoo.o - -PLATOBJ := win.o \ - win_dynld.o win_thread.o \ - win_cdrom.o win_keyboard.o \ - win_mouse.o win_joystick.o win_midi.o - -OBJ := $(MAINOBJ) $(INTELOBJ) $(CPUOBJ) $(MCHOBJ) $(DEVOBJ) \ - $(FDDOBJ) $(CDROMOBJ) $(ZIPOBJ) $(HDDOBJ) \ - $(USBOBJ) $(NETOBJ) $(SCSIOBJ) $(SNDOBJ) $(VIDOBJ) \ - $(PLATOBJ) $(UIOBJ) $(FSYNTHOBJ) $(MUNTOBJ) \ - $(DEVBROBJ) -ifdef EXOBJ -OBJ += $(EXOBJ) -endif - -LIBS := -mwindows \ - -lopenal.dll \ - -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 \ - -lcomctl32 -lwinmm -ifeq ($(D2D), y) -LIBS += $(D2DLIB) -endif -ifeq ($(VNC), y) -LIBS += $(VNCLIB) -lws2_32 -endif -ifeq ($(RDP), y) -LIBS += $(RDPLIB) -endif -LIBS += -lpng -lz -lwsock32 -liphlpapi -LIBS += -static -lstdc++ -lgcc -ifneq ($(X64), y) -LIBS += -Wl,--large-address-aware -endif - - -# Build module rules. -ifeq ($(AUTODEP), y) -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) $(DEPS) -c $< - -%.o: %.cc - @echo $< - @$(CPP) $(CFLAGS) $(DEPS) -c $< - -%.o: %.cpp - @echo $< - @$(CPP) $(CFLAGS) $(DEPS) -c $< -else -%.o: %.c - @echo $< - @$(CC) $(CFLAGS) -c $< - -%.o: %.cc - @echo $< - @$(CPP) $(CFLAGS) -c $< - -%.o: %.cpp - @echo $< - @$(CPP) $(CFLAGS) -c $< - -%.d: %.c $(wildcard $*.d) - @echo $< - @$(CC) $(CFLAGS) $(DEPS) -E $< >NUL - -%.d: %.cc $(wildcard $*.d) - @echo $< - @$(CPP) $(CFLAGS) $(DEPS) -E $< >NUL - -%.d: %.cpp $(wildcard $*.d) - @echo $< - @$(CPP) $(CFLAGS) $(DEPS) -E $< >NUL -endif - - -all: $(PROG).exe pcap_if.exe - - -86Box.res: 86Box.rc - @echo Processing $< - @$(WINDRES) $(RFLAGS) $(EXTRAS) -i $< -o 86Box.res - -$(PROG).exe: $(OBJ) 86Box.res - @echo Linking $(PROG).exe .. - @$(CC) -m32 -o $(PROG).exe $(OBJ) 86Box.res $(LIBS) -ifneq ($(DEBUG), y) - @strip $(PROG).exe -endif - -pcap_if.res: pcap_if.rc - @echo Processing $< - @$(WINDRES) $(RFLAGS) -i $< -o pcap_if.res - -pcap_if.exe: pcap_if.o win_dynld.o pcap_if.res - @echo Linking pcap_if.exe .. - @$(CC) -m32 -o pcap_if.exe pcap_if.o win_dynld.o pcap_if.res -ifneq ($(DEBUG), y) - @strip pcap_if.exe -endif - -hello.exe: hello.o - $(CXX) $(LDFLAGS) -o hello.exe hello.o $(LIBS) -ifneq ($(DEBUG), y) - @strip hello.exe -endif - - -clean: - @echo Cleaning objects.. - @-rm -f *.o 2>NUL - @-rm -f *.res 2>NUL - -clobber: clean - @echo Cleaning executables.. - @-rm -f *.d 2>NUL - @-rm -f *.exe 2>NUL -# @-rm -f $(DEPFILE) 2>NUL - -ifneq ($(AUTODEP), y) -depclean: - @-rm -f $(DEPFILE) 2>NUL - @echo Creating dependencies.. - @echo # Run "make depends" to re-create this file. >$(DEPFILE) - -depends: DEPOBJ=$(OBJ:%.o=%.d) -depends: depclean $(OBJ:%.o=%.d) - @-cat $(DEPOBJ) >>$(DEPFILE) - @-rm -f $(DEPOBJ) - -$(DEPFILE): -endif - - -# Module dependencies. -ifeq ($(AUTODEP), y) -#-include $(OBJ:%.o=%.d) (better, but sloooowwwww) --include *.d -else -include $(wildcard $(DEPFILE)) -endif - - -# End of Makefile.mingw.