Fixed AHA and BusLogic mailbox processing so that an outgoing mailbox is not marked as free until it's been completely processed and correctly implemented the AHA-1542C/CF Shadow RAM - the AHA-1542C/CF should be fully working now.
This commit is contained in:
@@ -43,7 +43,7 @@
|
||||
|
||||
|
||||
#define SCSI_DELAY_TM 1 /* was 50 */
|
||||
#define AHA_RESET_DURATION_US UINT64_C(5000)
|
||||
#define AHA_RESET_DURATION_US UINT64_C(50000)
|
||||
|
||||
|
||||
#define ROM_SIZE 16384 /* one ROM is 16K */
|
||||
@@ -422,8 +422,12 @@ typedef struct {
|
||||
int MbiActive[256];
|
||||
int PendingInterrupt;
|
||||
int Lock;
|
||||
uint8_t shadow_ram[128];
|
||||
event_t *evt;
|
||||
uint8_t MailboxIsBIOS;
|
||||
uint8_t shram_mode;
|
||||
uint8_t last_mb;
|
||||
uint8_t ToRaise;
|
||||
} aha_t;
|
||||
|
||||
|
||||
@@ -471,37 +475,27 @@ aha_log(const char *fmt, ...)
|
||||
static void
|
||||
aha_mem_write(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
rom_t *rom = (rom_t *)priv;
|
||||
aha_t *dev = (aha_t *)priv;
|
||||
|
||||
if ((addr & rom->mask) >= 0x3F80)
|
||||
rom->rom[addr & rom->mask] = val;
|
||||
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)
|
||||
{
|
||||
rom_t *rom = (rom_t *)priv;
|
||||
aha_t *dev = (aha_t *)priv;
|
||||
rom_t *rom = &dev->bios;
|
||||
|
||||
return(rom->rom[addr & rom->mask]);
|
||||
}
|
||||
addr &= 0x3fff;
|
||||
|
||||
if ((addr >= dev->rom_shram) && (dev->shram_mode & 2))
|
||||
return dev->shadow_ram[addr & (dev->rom_shramsz - 1)];
|
||||
|
||||
static uint16_t
|
||||
aha_mem_readw(uint32_t addr, void *priv)
|
||||
{
|
||||
rom_t *rom = (rom_t *)priv;
|
||||
|
||||
return(*(uint16_t *)&rom->rom[addr & rom->mask]);
|
||||
}
|
||||
|
||||
|
||||
static uint32_t
|
||||
aha_mem_readl(uint32_t addr, void *priv)
|
||||
{
|
||||
rom_t *rom = (rom_t *)priv;
|
||||
|
||||
return(*(uint32_t *)&rom->rom[addr & rom->mask]);
|
||||
return(rom->rom[addr]);
|
||||
}
|
||||
|
||||
|
||||
@@ -511,19 +505,9 @@ aha154x_shram(aha_t *dev, uint8_t cmd)
|
||||
/* If not supported, give up. */
|
||||
if (dev->rom_shram == 0x0000) return(0x04);
|
||||
|
||||
switch(cmd) {
|
||||
case 0x00: /* disable, make it look like ROM */
|
||||
memset(&dev->bios.rom[dev->rom_shram], 0xFF, dev->rom_shramsz);
|
||||
break;
|
||||
|
||||
case 0x02: /* clear it */
|
||||
memset(&dev->bios.rom[dev->rom_shram], 0x00, dev->rom_shramsz);
|
||||
break;
|
||||
|
||||
case 0x03: /* enable, clear for use */
|
||||
memset(&dev->bios.rom[dev->rom_shram], 0x00, dev->rom_shramsz);
|
||||
break;
|
||||
}
|
||||
/* Bit 0 = Shadow RAM write enable;
|
||||
Bit 1 = Shadow RAM read enable. */
|
||||
dev->shram_mode = cmd;
|
||||
|
||||
/* Firmware expects 04 status. */
|
||||
return(0x04);
|
||||
@@ -533,6 +517,7 @@ aha154x_shram(aha_t *dev, uint8_t cmd)
|
||||
static uint8_t
|
||||
aha154x_eeprom(aha_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8_t *bufp)
|
||||
{
|
||||
FILE *f;
|
||||
uint8_t r = 0xff;
|
||||
|
||||
aha_log("%s: EEPROM cmd=%02x, arg=%02x len=%d, off=%02x\n",
|
||||
@@ -547,6 +532,14 @@ aha154x_eeprom(aha_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint8
|
||||
/* Write data to the EEPROM. */
|
||||
memcpy(&dev->nvr[off], bufp, len);
|
||||
r = 0;
|
||||
|
||||
f = nvr_fopen(dev->nvr_path, L"wb");
|
||||
if (f)
|
||||
{
|
||||
fwrite(dev->nvr, 1, NVR_SIZE, f);
|
||||
fclose(f);
|
||||
f = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == 0x23) {
|
||||
@@ -650,6 +643,8 @@ aha_reset(aha_t *dev)
|
||||
dev->MailboxOutInterrupts = 0;
|
||||
dev->PendingInterrupt = 0;
|
||||
dev->Lock = 0;
|
||||
dev->shram_mode = 0;
|
||||
dev->last_mb = 0;
|
||||
|
||||
ClearIntr(dev);
|
||||
}
|
||||
@@ -738,6 +733,12 @@ aha_ccb(aha_t *dev)
|
||||
/* Rewrite the CCB up to the CDB. */
|
||||
aha_log("CCB rewritten to the CDB (pointer %08X)\n", CCBPointer);
|
||||
DMAPageWrite(CCBPointer, (char *)CmdBlock, 18);
|
||||
|
||||
dev->ToRaise = INTR_HACC | INTR_ANY;
|
||||
if (dev->MailboxOutInterrupts)
|
||||
{
|
||||
dev->ToRaise |= INTR_MBOA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -792,9 +793,10 @@ aha_mbi(aha_t *dev)
|
||||
if (dev->MailboxInPosCur >= dev->MailboxCount)
|
||||
dev->MailboxInPosCur = 0;
|
||||
|
||||
RaiseIntr(dev, 0, INTR_MBIF | INTR_ANY);
|
||||
|
||||
while (dev->Interrupt) {
|
||||
dev->ToRaise = INTR_MBIF | INTR_ANY;
|
||||
if (dev->MailboxOutInterrupts)
|
||||
{
|
||||
dev->ToRaise |= INTR_MBOA;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1273,33 +1275,28 @@ aha_do_mail(aha_t *dev)
|
||||
|
||||
/* Check the next mailbox. */
|
||||
aha_mbo_adv(dev);
|
||||
} while ((mb32.u.out.ActionCode == MBO_FREE) && (MailboxCur != dev->MailboxOutPosCur));
|
||||
|
||||
if (mb32.u.out.ActionCode != MBO_FREE) {
|
||||
/* We got the mailbox, mark it as free in the guest. */
|
||||
aha_log("aha_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset);
|
||||
DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, sizeof(CmdStatus));
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev->MailboxOutInterrupts) {
|
||||
RaiseIntr(dev, 0, INTR_MBOA | INTR_ANY);
|
||||
|
||||
while (dev->Interrupt) {
|
||||
}
|
||||
}
|
||||
} while ((mb32.u.out.ActionCode != MBO_START) && (mb32.u.out.ActionCode != MBO_ABORT) && (MailboxCur != dev->MailboxOutPosCur));
|
||||
|
||||
if (mb32.u.out.ActionCode == MBO_START) {
|
||||
aha_log("Start Mailbox Command\n");
|
||||
aha_req_setup(dev, mb32.CCBPointer, &mb32);
|
||||
} else if (mb32.u.out.ActionCode == MBO_ABORT) {
|
||||
} else if (!dev->MailboxIsBIOS && (mb32.u.out.ActionCode == MBO_ABORT)) {
|
||||
aha_log("Abort Mailbox Command\n");
|
||||
aha_req_abort(dev, mb32.CCBPointer);
|
||||
} else {
|
||||
aha_log("Invalid action code: %02X\n", mb32.u.out.ActionCode);
|
||||
}
|
||||
|
||||
if ((mb32.u.out.ActionCode == MBO_START) || (mb32.u.out.ActionCode == MBO_ABORT)) {
|
||||
/* We got the mailbox, mark it as free in the guest. */
|
||||
aha_log("aha_do_mail(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset);
|
||||
DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, sizeof(CmdStatus));
|
||||
|
||||
RaiseIntr(dev, 0, dev->ToRaise);
|
||||
|
||||
while (dev->Interrupt) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1320,14 +1317,6 @@ aha_cmd_thread(void *priv)
|
||||
aha_do_mail(dev);
|
||||
}
|
||||
|
||||
if (!dev->MailboxCount)
|
||||
{
|
||||
thread_destroy_event(dev->evt);
|
||||
dev->evt = NULL;
|
||||
poll_tid = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
thread_destroy_event(dev->evt);
|
||||
dev->evt = poll_tid = NULL;
|
||||
|
||||
@@ -1344,7 +1333,6 @@ aha_read(uint16_t port, void *priv)
|
||||
switch (port & 3) {
|
||||
case 0:
|
||||
default:
|
||||
pclog("Read status: %02X\n", dev->Interrupt);
|
||||
ret = dev->Status;
|
||||
break;
|
||||
|
||||
@@ -1359,7 +1347,6 @@ aha_read(uint16_t port, void *priv)
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pclog("Read interrupt: %02X\n", dev->Interrupt);
|
||||
ret = dev->Interrupt;
|
||||
break;
|
||||
|
||||
@@ -1665,7 +1652,8 @@ aha_0x01:
|
||||
* and expects a 0x04 back in the INTR
|
||||
* register. --FvK
|
||||
*/
|
||||
dev->Interrupt = aha154x_shram(dev,val);
|
||||
/* dev->Interrupt = aha154x_shram(dev,val); */
|
||||
dev->Interrupt = aha154x_shram(dev, dev->CmdBuf[0]);
|
||||
break;
|
||||
|
||||
case CMD_BIOS_MBINIT: /* BIOS Mailbox Initialization */
|
||||
@@ -1943,9 +1931,9 @@ aha_setbios(aha_t *dev)
|
||||
|
||||
/* Map this system into the memory map. */
|
||||
mem_mapping_add(&dev->bios.mapping, dev->rom_addr, size,
|
||||
aha_mem_read, aha_mem_readw, aha_mem_readl,
|
||||
aha_mem_read, NULL, NULL, /* aha_mem_readw, aha_mem_readl, */
|
||||
aha_mem_write, NULL, NULL,
|
||||
dev->bios.rom, MEM_MAPPING_EXTERNAL, &dev->bios);
|
||||
dev->bios.rom, MEM_MAPPING_EXTERNAL, dev);
|
||||
mem_mapping_disable(&dev->bios.mapping);
|
||||
|
||||
/*
|
||||
@@ -1967,6 +1955,8 @@ aha_setbios(aha_t *dev)
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1980,47 +1970,15 @@ aha_setbios(aha_t *dev)
|
||||
dev->fwl = '0';
|
||||
if (dev->rom_fwhigh != 0x0000) {
|
||||
/* Read firmware version from the BIOS. */
|
||||
dev->fwh = dev->bios.rom[dev->rom_fwhigh];
|
||||
dev->fwl = dev->bios.rom[dev->rom_fwhigh+1];
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a checksum on the ROM.
|
||||
*
|
||||
* The BIOS ROMs on the 154xC(F) boards will always fail
|
||||
* the checksum, because they are incomplete: on the real
|
||||
* boards, a shadow RAM and some other (config) registers
|
||||
* are mapped into its space. It is assumed that boards
|
||||
* have logic that automatically generate a "fixup" byte
|
||||
* at the end of the data to 'make up' for this.
|
||||
*
|
||||
* We emulated some of those in the patch routine, so now
|
||||
* it is time to "fix up" the BIOS image so that the main
|
||||
* (system) BIOS considers it valid.
|
||||
*/
|
||||
again:
|
||||
mask = 0;
|
||||
for (temp=0; temp<ROM_SIZE; temp++)
|
||||
mask += dev->bios.rom[temp];
|
||||
mask &= 0xff;
|
||||
if (mask != 0x00) {
|
||||
dev->bios.rom[temp-1] += (256 - mask);
|
||||
goto again;
|
||||
dev->fwh = dev->bios.rom[dev->rom_fwhigh] + 0x30;
|
||||
dev->fwl = dev->bios.rom[dev->rom_fwhigh+1] + 0x30;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the board's EEPROM (NVR.) */
|
||||
static void
|
||||
aha_setnvr(aha_t *dev)
|
||||
aha_initnvr(aha_t *dev)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
/* Initialize the on-board EEPROM. */
|
||||
dev->nvr[0] = dev->HostID; /* SCSI ID 7 */
|
||||
dev->nvr[0] |= (0x10 | 0x20 | 0x40);
|
||||
@@ -2035,6 +1993,33 @@ aha_setnvr(aha_t *dev)
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the board's EEPROM (NVR.) */
|
||||
static void
|
||||
aha_setnvr(aha_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(device_t *info)
|
||||
@@ -2085,12 +2070,10 @@ aha_init(device_t *info)
|
||||
case AHA_154xC:
|
||||
strcpy(dev->name, "AHA-154xC");
|
||||
dev->bios_path = L"roms/scsi/adaptec/aha1542c102.bin";
|
||||
dev->nvr_path = L"aha1540c.nvr";
|
||||
dev->nvr_path = L"aha1542c.nvr";
|
||||
dev->bid = 'D';
|
||||
#if 0
|
||||
dev->rom_shram = 0x3F80; /* shadow RAM address base */
|
||||
dev->rom_shramsz = 128; /* size of shadow RAM */
|
||||
#endif
|
||||
dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */
|
||||
dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */
|
||||
break;
|
||||
@@ -2098,12 +2081,10 @@ aha_init(device_t *info)
|
||||
case AHA_154xCF:
|
||||
strcpy(dev->name, "AHA-154xCF");
|
||||
dev->bios_path = L"roms/scsi/adaptec/aha1542cf211.bin";
|
||||
dev->nvr_path = L"aha1540cf.nvr";
|
||||
dev->nvr_path = L"aha1542cf.nvr";
|
||||
dev->bid = 'E';
|
||||
#if 0
|
||||
dev->rom_shram = 0x3F80; /* shadow RAM address base */
|
||||
dev->rom_shramsz = 128; /* size of shadow RAM */
|
||||
#endif
|
||||
dev->rom_ioaddr = 0x3F7E; /* [2:0] idx into addr table */
|
||||
dev->rom_fwhigh = 0x0022; /* firmware version (hi/lo) */
|
||||
break;
|
||||
|
||||
@@ -511,6 +511,7 @@ typedef struct {
|
||||
uint8_t SCAMData[65536];
|
||||
event_t *evt;
|
||||
int scan_restart;
|
||||
uint8_t ToRaise;
|
||||
} Buslogic_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -937,9 +938,9 @@ BuslogicMailboxIn(Buslogic_t *bl)
|
||||
if (bl->MailboxInPosCur >= bl->MailboxCount)
|
||||
bl->MailboxInPosCur = 0;
|
||||
|
||||
BuslogicRaiseInterrupt(bl, 0, INTR_MBIF | INTR_ANY);
|
||||
|
||||
while (bl->Interrupt) {
|
||||
bl->ToRaise = INTR_MBIF | INTR_ANY;
|
||||
if (bl->MailboxOutInterrupts) {
|
||||
bl->ToRaise |= INTR_MBOA;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2512,23 +2513,6 @@ BuslogicProcessMailbox(Buslogic_t *bl)
|
||||
Outgoing = BuslogicMailboxOut(bl, &mb32);
|
||||
}
|
||||
|
||||
if (mb32.u.out.ActionCode != MBO_FREE) {
|
||||
/* We got the mailbox, mark it as free in the guest. */
|
||||
pclog("BuslogicProcessMailbox(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset);
|
||||
DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, sizeof(CmdStatus));
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bl->MailboxOutInterrupts) {
|
||||
BuslogicRaiseInterrupt(bl, 0, INTR_MBOA | INTR_ANY);
|
||||
|
||||
while (bl->Interrupt) {
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
pclog("BuslogicProcessMailbox(): Outgoing mailbox action code: %i\n", mb32.u.out.ActionCode);
|
||||
#endif
|
||||
@@ -2543,6 +2527,17 @@ BuslogicProcessMailbox(Buslogic_t *bl)
|
||||
pclog("Invalid action code: %02X\n", mb32.u.out.ActionCode);
|
||||
}
|
||||
|
||||
if ((mb32.u.out.ActionCode == MBO_START) || (mb32.u.out.ActionCode == MBO_ABORT)) {
|
||||
/* We got the mailbox, mark it as free in the guest. */
|
||||
pclog("BuslogicProcessMailbox(): Writing %i bytes at %08X\n", sizeof(CmdStatus), Outgoing + CodeOffset);
|
||||
DMAPageWrite(Outgoing + CodeOffset, (char *)&CmdStatus, sizeof(CmdStatus));
|
||||
|
||||
BuslogicRaiseInterrupt(bl, 0, bl->ToRaise);
|
||||
|
||||
while (bl->Interrupt) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance to the next mailbox. */
|
||||
if (! bl->LocalRAM.structured.autoSCSIData.fAggressiveRoundRobinMode)
|
||||
BuslogicMailboxOutAdvance(bl);
|
||||
|
||||
Reference in New Issue
Block a user