Files
86Box/src/mem/catalyst_flash.c

247 lines
5.5 KiB
C
Raw Normal View History

/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Implementation of the Intel 1 Mbit and 2 Mbit, 8-bit and
* 16-bit flash devices.
*
*
*
2023-01-06 15:36:29 -05:00
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/machine.h>
#include <86box/timer.h>
#include <86box/nvr.h>
#include <86box/plat.h>
2022-09-18 17:18:07 -04:00
#define FLAG_WORD 4
#define FLAG_BXB 2
#define FLAG_INV_A16 1
2022-09-18 17:18:07 -04:00
enum {
BLOCK_MAIN1,
BLOCK_MAIN2,
BLOCK_DATA1,
BLOCK_DATA2,
BLOCK_BOOT,
BLOCKS_NUM
};
2022-09-18 17:18:07 -04:00
enum {
CMD_SET_READ = 0x00,
CMD_READ_SIGNATURE = 0x90,
2022-09-18 17:18:07 -04:00
CMD_ERASE = 0x20,
CMD_ERASE_CONFIRM = 0x20,
CMD_ERASE_VERIFY = 0xA0,
CMD_PROGRAM = 0x40,
CMD_PROGRAM_VERIFY = 0xC0,
2022-09-18 17:18:07 -04:00
CMD_RESET = 0xFF
};
2022-09-18 17:18:07 -04:00
typedef struct flash_t {
2023-06-28 13:46:28 -04:00
uint8_t command;
uint8_t pad;
uint8_t pad0;
uint8_t pad1;
uint8_t *array;
mem_mapping_t mapping;
mem_mapping_t mapping_h[2];
} flash_t;
2022-09-18 17:18:07 -04:00
static char flash_path[1024];
static uint8_t
2023-06-28 13:46:28 -04:00
flash_read(uint32_t addr, void *priv)
{
2023-07-20 18:58:26 -04:00
const flash_t *dev = (flash_t *) priv;
uint8_t ret = 0xff;
addr &= biosmask;
switch (dev->command) {
2022-09-18 17:18:07 -04:00
case CMD_ERASE_VERIFY:
case CMD_PROGRAM_VERIFY:
case CMD_RESET:
case CMD_SET_READ:
ret = dev->array[addr];
break;
case CMD_READ_SIGNATURE:
if (addr == 0x00000)
ret = 0x31; /* CATALYST */
else if (addr == 0x00001)
ret = 0xB4; /* 28F010 */
break;
2023-06-28 13:46:28 -04:00
default:
break;
}
return ret;
}
static uint16_t
2023-06-09 23:46:54 -04:00
flash_readw(uint32_t addr, void *priv)
{
2023-07-20 18:58:26 -04:00
flash_t *dev = (flash_t *) priv;
const uint16_t *q;
addr &= biosmask;
2022-09-18 17:18:07 -04:00
q = (uint16_t *) &(dev->array[addr]);
return *q;
}
static uint32_t
2023-06-09 23:46:54 -04:00
flash_readl(uint32_t addr, void *priv)
{
2023-07-20 18:58:26 -04:00
flash_t *dev = (flash_t *) priv;
const uint32_t *q;
addr &= biosmask;
2022-09-18 17:18:07 -04:00
q = (uint32_t *) &(dev->array[addr]);
return *q;
}
static void
2023-06-09 23:46:54 -04:00
flash_write(uint32_t addr, uint8_t val, void *priv)
{
2023-06-09 23:46:54 -04:00
flash_t *dev = (flash_t *) priv;
addr &= biosmask;
switch (dev->command) {
2022-09-18 17:18:07 -04:00
case CMD_ERASE:
if (val == CMD_ERASE_CONFIRM)
memset(dev->array, 0xff, biosmask + 1);
break;
case CMD_PROGRAM:
dev->array[addr] = val;
break;
default:
dev->command = val;
break;
}
}
static void
2023-06-28 13:46:28 -04:00
flash_writew(UNUSED(uint32_t addr), UNUSED(uint16_t val), UNUSED(void *priv))
{
2023-06-28 13:46:28 -04:00
//
}
static void
2023-06-28 13:46:28 -04:00
flash_writel(UNUSED(uint32_t addr), UNUSED(uint32_t val), UNUSED(void *priv))
{
2023-06-28 13:46:28 -04:00
//
}
static void
catalyst_flash_add_mappings(flash_t *dev)
{
memcpy(dev->array, rom, biosmask + 1);
mem_mapping_add(&dev->mapping, 0xe0000, 0x20000,
2022-09-18 17:18:07 -04:00
flash_read, flash_readw, flash_readl,
flash_write, flash_writew, flash_writel,
dev->array, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev);
mem_mapping_add(&(dev->mapping_h[0]), 0xfffc0000, 0x20000,
2022-09-18 17:18:07 -04:00
flash_read, flash_readw, flash_readl,
flash_write, flash_writew, flash_writel,
dev->array, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev);
mem_mapping_add(&(dev->mapping_h[1]), 0xfffe0000, 0x20000,
2022-09-18 17:18:07 -04:00
flash_read, flash_readw, flash_readl,
flash_write, flash_writew, flash_writel,
dev->array, MEM_MAPPING_EXTERNAL | MEM_MAPPING_ROM | MEM_MAPPING_ROMCS, (void *) dev);
}
static void
catalyst_flash_reset(void *priv)
{
flash_t *dev = (flash_t *) priv;
dev->command = CMD_RESET;
}
static void *
2023-06-28 13:46:28 -04:00
catalyst_flash_init(UNUSED(const device_t *info))
{
2023-06-09 23:46:54 -04:00
FILE *fp;
flash_t *dev;
2025-01-07 00:42:06 -05:00
dev = calloc(1, sizeof(flash_t));
sprintf(flash_path, "%s.bin", machine_get_nvr_name_ex(machine));
mem_mapping_disable(&bios_mapping);
mem_mapping_disable(&bios_high_mapping);
dev->array = (uint8_t *) malloc(0x20000);
memset(dev->array, 0xff, 0x20000);
catalyst_flash_add_mappings(dev);
dev->command = CMD_RESET;
2023-06-09 23:46:54 -04:00
fp = nvr_fopen(flash_path, "rb");
if (fp) {
(void) !fread(dev->array, 0x20000, 1, fp);
fclose(fp);
}
return dev;
}
static void
2023-06-09 23:46:54 -04:00
catalyst_flash_close(void *priv)
{
2023-06-09 23:46:54 -04:00
FILE *fp;
flash_t *dev = (flash_t *) priv;
2023-06-09 23:46:54 -04:00
fp = nvr_fopen(flash_path, "wb");
fwrite(dev->array, 0x20000, 1, fp);
fclose(fp);
free(dev->array);
dev->array = NULL;
free(dev);
}
2022-03-13 09:47:11 -04:00
const device_t catalyst_flash_device = {
2022-09-18 17:18:07 -04:00
.name = "Catalyst 28F010-D Flash BIOS",
2022-03-13 09:47:11 -04:00
.internal_name = "catalyst_flash",
2022-09-18 17:18:07 -04:00
.flags = DEVICE_PCI,
.local = 0,
.init = catalyst_flash_init,
.close = catalyst_flash_close,
.reset = catalyst_flash_reset,
2025-01-07 01:12:42 -05:00
.available = NULL,
2022-03-13 09:47:11 -04:00
.speed_changed = NULL,
2022-09-18 17:18:07 -04:00
.force_redraw = NULL,
.config = NULL
};