From 6dbdc0483fd6c033220f2342015b61bb9e5675cc Mon Sep 17 00:00:00 2001 From: OBattler Date: Thu, 17 Aug 2017 23:16:26 +0200 Subject: [PATCH] The RTL8029AS Expansion ROM BAR PCI registers are now implemented correctly; The BusLogic BT-958D PCI SCSI controller now optionally uses a BIOS (supports up to eight SCSI hard disks, up to 8 GB each); Fixed some BusLogic commands; The BusLogic SCSI controllers now use 15 as the host adapter ID. --- src/NETWORK/net_ne2000.c | 37 +++++--- src/scsi_buslogic.c | 194 ++++++++++++++++++++++++++++++--------- 2 files changed, 176 insertions(+), 55 deletions(-) diff --git a/src/NETWORK/net_ne2000.c b/src/NETWORK/net_ne2000.c index 0b3a04de8..c77b1c745 100644 --- a/src/NETWORK/net_ne2000.c +++ b/src/NETWORK/net_ne2000.c @@ -217,6 +217,7 @@ typedef struct { uint8_t eeprom[128]; /* for RTL8029AS */ rom_t bios_rom; int card; /* PCI card slot */ + int has_bios; } nic_t; @@ -1426,19 +1427,23 @@ nic_update_bios(nic_t *dev) int reg_bios_enable; reg_bios_enable = 1; + + if (!dev->has_bios) { + return; + } + + if (PCI && dev->is_pci) { + reg_bios_enable = dev->pci_bar[1].addr_regs[0] & 0x01; + } /* PCI BIOS stuff, just enable_disable. */ - if ((dev->bios_addr > 0) && reg_bios_enable) { - mem_mapping_enable(&dev->bios_rom.mapping); + if (reg_bios_enable) { mem_mapping_set_addr(&dev->bios_rom.mapping, dev->bios_addr, dev->bios_size); nelog(1, "%s: BIOS now at: %06X\n", dev->name, dev->bios_addr); } else { nelog(1, "%s: BIOS disabled\n", dev->name); mem_mapping_disable(&dev->bios_rom.mapping); - dev->bios_addr = 0; - if (dev->is_pci) - dev->pci_bar[1].addr = 0; } } @@ -1527,7 +1532,7 @@ nic_pci_read(int func, int addr, void *priv) ret = dev->pci_bar[1].addr_regs[0] & 0x01; break; case 0x31: /* PCI_ROMBAR 15:11 */ - ret = (dev->pci_bar[1].addr_regs[1] & dev->bios_mask) | 0x18; + ret = (dev->pci_bar[1].addr_regs[1] & dev->bios_mask); break; case 0x32: /* PCI_ROMBAR 23:16 */ ret = dev->pci_bar[1].addr_regs[2]; @@ -1632,9 +1637,8 @@ nic_pci_write(int func, int addr, uint8_t val, void *priv) case 0x33: /* PCI_ROMBAR */ dev->pci_bar[1].addr_regs[addr & 3] = val; dev->pci_bar[1].addr_regs[1] &= dev->bios_mask; - dev->pci_bar[1].addr &= 0xffffe000; + dev->pci_bar[1].addr &= 0xffffe001; dev->bios_addr = dev->pci_bar[1].addr; - dev->pci_bar[1].addr |= 0x1801; nic_update_bios(dev); return; @@ -1917,10 +1921,19 @@ nic_init(int board) dev->base_irq = 10; } else { dev->base_address = device_get_config_hex16("base"); - dev->bios_addr = device_get_config_hex20("bios_addr"); dev->base_irq = device_get_config_int("irq"); } + dev->bios_addr = device_get_config_hex20("bios_addr"); + if (dev->bios_addr) + { + dev->has_bios = 1; + } + else + { + dev->has_bios = 0; + } + /* See if we have a local MAC address configured. */ mac = device_get_config_mac("mac", -1); @@ -1962,11 +1975,13 @@ nic_init(int board) if (dev->bios_addr > 0) { dev->pci_bar[1].addr = 0x000F8000; dev->pci_bar[1].addr_regs[1] = dev->bios_mask; - dev->pci_bar[1].addr |= 0x1801; } else { dev->pci_bar[1].addr = 0; + dev->bios_size = 0; } + mem_mapping_disable(&dev->bios_rom.mapping); + /* Initialize the RTL8029 EEPROM. */ memset(dev->eeprom, 0x00, sizeof(dev->eeprom)); dev->eeprom[0x76] = @@ -2225,7 +2240,6 @@ static device_config_t ne2000_config[] = static device_config_t rtl8029as_config[] = { -#if 1 /* * WTF. * Even though it is PCI, the user should still have control @@ -2252,7 +2266,6 @@ static device_config_t rtl8029as_config[] = } }, }, -#endif { "mac", "MAC Address", CONFIG_MAC, "", -1 }, diff --git a/src/scsi_buslogic.c b/src/scsi_buslogic.c index 25ad0e928..7b2c1b21f 100644 --- a/src/scsi_buslogic.c +++ b/src/scsi_buslogic.c @@ -10,7 +10,7 @@ * 0 - BT-542B ISA; * 1 - BT-958 PCI (but BT-542B ISA on non-PCI machines) * - * Version: @(#)scsi_buslogic.c 1.0.5 2017/08/15 + * Version: @(#)scsi_buslogic.c 1.0.6 2017/08/17 * * Authors: TheCollector1995, * Miran Grca, @@ -513,7 +513,10 @@ typedef struct { mem_mapping_t mmio_mapping; int chip; int Card; - int has_bios; + int has_bios; + uint32_t bios_addr, + bios_size, + bios_mask; } Buslogic_t; #pragma pack(pop) @@ -580,12 +583,12 @@ BuslogicInterrupt(Buslogic_t *bl, int set) if (set) { picint(1 << bl->Irq); - //pclog("Interrupt Set\n"); + /* pclog("Interrupt Set\n"); */ } else { picintc(1 << bl->Irq); - //pclog("Interrupt Cleared\n"); + /* pclog("Interrupt Cleared\n"); */ } } } @@ -594,13 +597,13 @@ BuslogicInterrupt(Buslogic_t *bl, int set) static void BuslogicClearInterrupt(Buslogic_t *bl) { - //pclog("Buslogic: Lowering Interrupt 0x%02X\n", bl->Interrupt); + /* pclog("Buslogic: Lowering Interrupt 0x%02X\n", bl->Interrupt); */ bl->Interrupt = 0; - //pclog("Lowering IRQ %i\n", bl->Irq); + /* pclog("Lowering IRQ %i\n", bl->Irq); */ BuslogicInterrupt(bl, 0); if (bl->PendingInterrupt) { bl->Interrupt = bl->PendingInterrupt; - //pclog("Buslogic: Raising Interrupt 0x%02X (Pending)\n", bl->Interrupt); + /* pclog("Buslogic: Raising Interrupt 0x%02X (Pending)\n", bl->Interrupt); */ if (bl->MailboxOutInterrupts || !(bl->Interrupt & INTR_MBOA)) { if (bl->IrqEnabled) BuslogicInterrupt(bl, 1); } @@ -611,7 +614,7 @@ BuslogicClearInterrupt(Buslogic_t *bl) static void BuslogicReset(Buslogic_t *bl) { - //pclog("BuslogicReset()\n"); + /* pclog("BuslogicReset()\n"); */ BuslogicCallback = 0; BuslogicResetCallback = 0; bl->Geometry = 0x80; @@ -636,7 +639,7 @@ BuslogicReset(Buslogic_t *bl) static void BuslogicResetControl(Buslogic_t *bl, uint8_t Reset) { - //pclog("BuslogicResetControl()\n"); + /* pclog("BuslogicResetControl()\n"); */ BuslogicReset(bl); if (Reset) { bl->Status |= STAT_STST; @@ -1108,11 +1111,10 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf uint8_t cdrom_id, cdrom_phase; uint32_t i; uint8_t temp_cdb[12]; - uint8_t last_id = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7; DataInBuf[0] = DataInBuf[1] = 0; - if ((ESCSICmd->TargetId > last_id) || (ESCSICmd->LogicalUnit > 7)) { + if ((ESCSICmd->TargetId > 15) || (ESCSICmd->LogicalUnit > 7)) { DataInBuf[2] = CCB_INVALID_CCB; DataInBuf[3] = SCSI_STATUS_OK; return; @@ -1128,7 +1130,7 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf if (SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].LunType == SCSI_NONE) { SpecificLog("SCSI Target ID %i and LUN %i have no device attached\n",ESCSICmd->TargetId,ESCSICmd->LogicalUnit); BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - //BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, 0, 0); + /* BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, 0, 0); */ DataInBuf[2] = CCB_SELECTION_TIMEOUT; DataInBuf[3] = SCSI_STATUS_OK; } else { @@ -1203,7 +1205,7 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf pclog("SCSI Status: %s, Sense: %02X, ASC: %02X, ASCQ: %02X\n", (SCSIStatus == SCSI_STATUS_OK) ? "OK" : "CHECK CONDITION", shdc[hdc_id].sense[2], shdc[hdc_id].sense[12], shdc[hdc_id].sense[13]); BuslogicSCSIBIOSDataBufferFree(ESCSICmd, ESCSICmd->TargetId, ESCSICmd->LogicalUnit); - //BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, (SCSIStatus != SCSI_STATUS_OK), 1); + /* BuslogicSCSIBIOSSenseBufferFree(ESCSICmd, Id, Lun, (SCSIStatus != SCSI_STATUS_OK), 1); */ pclog("BIOS Request complete\n"); @@ -1288,7 +1290,7 @@ BuslogicSCSIBIOSRequestSetup(Buslogic_t *bl, uint8_t *CmdBuf, uint8_t *DataInBuf } } - //BuslogicInOperation = (SCSIDevices[Id][Lun].LunType == SCSI_DISK) ? 0x13 : 3; + /* BuslogicInOperation = (SCSIDevices[Id][Lun].LunType == SCSI_DISK) ? 0x13 : 3; */ pclog("SCSI (%i:%i) -> %i\n", ESCSICmd->TargetId, ESCSICmd->LogicalUnit, SCSIDevices[ESCSICmd->TargetId][ESCSICmd->LogicalUnit].LunType); bl->DataReplyLeft = DataReply; @@ -1961,6 +1963,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) char aModelName[] = "542B "; /* Trailing \0 is fine, that's the filler anyway. */ int cCharsToTransfer; uint16_t cyl = 0; + uint8_t temp = 0; pclog("Buslogic: Write Port 0x%02X, Value %02X\n", Port, Val); @@ -2113,9 +2116,15 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) BiosCmd = (BIOSCMD *)bl->CmdBuf; cyl = ((BiosCmd->cylinder & 0xff) << 8) | ((BiosCmd->cylinder >> 8) & 0xff); - BiosCmd->cylinder = cyl; + BiosCmd->cylinder = cyl; + if (bl->chip == CHIP_BUSLOGIC_PCI) + { + temp = BiosCmd->id; + BiosCmd->id = BiosCmd->lun; + BiosCmd->lun = temp; + } SpecificLog("C: %04X, H: %02X, S: %02X\n", BiosCmd->cylinder, BiosCmd->head, BiosCmd->sector); - bl->DataBuf[0] = HACommand03Handler((bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7, BiosCmd); + bl->DataBuf[0] = HACommand03Handler(15, BiosCmd); SpecificLog("BIOS Completion/Status Code %x\n", bl->DataBuf[0]); bl->DataReplyLeft = 1; break; @@ -2164,14 +2173,13 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x0A: memset(bl->DataBuf, 0, 8); - for (i=0; i<7; i++) { + for (i=0; i<8; i++) { bl->DataBuf[i] = 0; for (j=0; j<8; j++) { if (SCSIDevices[i][j].LunType != SCSI_NONE) bl->DataBuf[i] |= (1 << j); } } - bl->DataBuf[7] = 0; bl->DataReplyLeft = 8; break; @@ -2186,7 +2194,8 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) bl->DataBuf[1] = 0; { } - bl->DataBuf[2] = 7; /* HOST ID */ + /* bl->DataBuf[2] = 7; */ /* HOST ID */ + bl->DataBuf[2] = 15; /* HOST ID */ bl->DataReplyLeft = 3; break; @@ -2224,7 +2233,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) Address.lo = bl->CmdBuf[2]; FIFOBuf = ADDR_TO_U32(Address); pclog("Buslogic LocalRAM: Reading 64 bytes at %08X\n", FIFOBuf); - DMAPageRead(FIFOBuf, (char *)&bl->LocalRAM.u8View[64], 64); + DMAPageRead(FIFOBuf, (char *)bl->LocalRAM.u8View, 64); } break; @@ -2239,7 +2248,7 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) Address.lo = bl->CmdBuf[2]; FIFOBuf = ADDR_TO_U32(Address); pclog("Buslogic LocalRAM: Writing 64 bytes at %08X\n", FIFOBuf); - DMAPageWrite(FIFOBuf, (char *)&bl->LocalRAM.u8View[64], 64); + DMAPageWrite(FIFOBuf, (char *)bl->LocalRAM.u8View, 64); } break; @@ -2261,14 +2270,14 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) case 0x23: memset(bl->DataBuf, 0, 8); - for (i = 8; i < 16; i++) { - /* FIXME: Kotori, check this! */ + for (i = 8; i < 15; i++) { bl->DataBuf[i-8] = 0; for (j=0; j<8; j++) { if (SCSIDevices[i][j].LunType != SCSI_NONE) bl->DataBuf[i-8] |= (1<DataBuf[7] = 0; bl->DataReplyLeft = 8; break; @@ -2276,11 +2285,9 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) { uint16_t TargetsPresentMask = 0; - for (i=0; i<16; i++) { - for (j=0; j<8; j++) { - if (SCSIDevices[i][j].LunType != SCSI_NONE) + for (i=0; i<15; i++) { + if (SCSIDevices[i][0].LunType != SCSI_NONE) TargetsPresentMask |= (1 << i); - } } bl->DataBuf[0] = TargetsPresentMask & 0xFF; bl->DataBuf[1] = TargetsPresentMask >> 8; @@ -2420,9 +2427,9 @@ BuslogicWrite(uint16_t Port, uint8_t Val, void *p) ReplyIESI->u16ScatterGatherLimit = 8192; ReplyIESI->cMailbox = bl->MailboxCount; ReplyIESI->uMailboxAddressBase = bl->MailboxOutAddr; + ReplyIESI->fHostWideSCSI = 1; /* This should be set for the BT-542B as well. */ if (bl->chip == CHIP_BUSLOGIC_PCI) { ReplyIESI->fLevelSensitiveInterrupt = 1; - ReplyIESI->fHostWideSCSI = 1; ReplyIESI->fHostUltraSCSI = 1; } memcpy(ReplyIESI->aFirmwareRevision, "21E", sizeof(ReplyIESI->aFirmwareRevision)); @@ -2793,7 +2800,6 @@ BuslogicSCSIRequestSetup(Buslogic_t *bl, uint32_t CCBPointer, Mailbox32_t *Mailb { Req_t *req = &bl->Req; uint8_t Id, Lun; - uint8_t last_id = (bl->chip >= CHIP_BUSLOGIC_ISA) ? 15 : 7; /* Fetch data from the Command Control Block. */ DMAPageRead(CCBPointer, (char *)&req->CmdBlock, sizeof(CCB32)); @@ -2805,7 +2811,7 @@ BuslogicSCSIRequestSetup(Buslogic_t *bl, uint32_t CCBPointer, Mailbox32_t *Mailb Id = req->TargetID; Lun = req->LUN; - if ((Id > last_id) || (Lun > 7)) { + if ((Id > 15) || (Lun > 7)) { BuslogicMailboxInSetup(bl, CCBPointer, &req->CmdBlock, CCB_INVALID_CCB, SCSI_STATUS_OK, MBI_ERROR); return; @@ -3017,6 +3023,29 @@ uint8_t buslogic_pci_regs[256]; bar_t buslogic_pci_bar[3]; +#if 0 +static void +BuslogicBIOSUpdate(Buslogic_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); + pclog("BT-958D: BIOS now at: %06X\n", bl->bios_addr); + } else { + pclog("BT-958D: BIOS disabled\n"); + mem_mapping_disable(&bl->bios.mapping); + } +} +#endif + static uint8_t BuslogicPCIRead(int func, int addr, void *p) { @@ -3032,9 +3061,9 @@ BuslogicPCIRead(int func, int addr, void *p) case 0x03: return 0x10; case 0x04: - return buslogic_pci_regs[0x04]; /*Respond to IO and memory accesses*/ + return buslogic_pci_regs[0x04] & 0x03; /*Respond to IO and memory accesses*/ case 0x05: - return buslogic_pci_regs[0x05]; + return 0; case 0x07: return 2; case 0x08: @@ -3069,14 +3098,23 @@ BuslogicPCIRead(int func, int addr, void *p) return 0x40; case 0x2F: return 0x10; - case 0x30: - return buslogic_pci_bar[2].addr_regs[0] & 0x01; /*BIOS ROM address*/ - case 0x31: - return buslogic_pci_bar[2].addr_regs[1] | 0x18; - case 0x32: +#if 0 + case 0x30: /* PCI_ROMBAR */ + pclog("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 */ + pclog("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] & bl->bios_mask); + break; + case 0x32: /* PCI_ROMBAR 23:16 */ + pclog("BT-958D: BIOS BAR 02 = %02X\n", buslogic_pci_bar[2].addr_regs[2]); return buslogic_pci_bar[2].addr_regs[2]; - case 0x33: + break; + case 0x33: /* PCI_ROMBAR 31:24 */ + pclog("BT-958D: BIOS BAR 03 = %02X\n", buslogic_pci_bar[2].addr_regs[3]); return buslogic_pci_bar[2].addr_regs[3]; + break; +#endif case 0x3C: return bl->Irq; case 0x3D: @@ -3169,7 +3207,20 @@ BuslogicPCIWrite(int func, int addr, uint8_t val, void *p) } } return; - +#if 0 + 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_regs[1] &= bl->bios_mask; + buslogic_pci_bar[2].addr &= 0xffffe001; + bl->bios_addr = buslogic_pci_bar[2].addr; + pclog("BT-958D: BIOS BAR %02X = NOW %02X (%02X)\n", addr & 3, buslogic_pci_bar[2].addr_regs[addr & 3], val); + BuslogicBIOSUpdate(bl); + return; +#endif + case 0x3C: buslogic_pci_regs[addr] = val; if (val != 0xFF) { @@ -3189,6 +3240,30 @@ BuslogicDeviceReset(void *p) } +static void +BuslogicInitializeLocalRAM(Buslogic_t *bl) +{ + memset(bl->LocalRAM.u8View, 0, sizeof(HALocalRAM)); + if (PCI && (bl->chip == CHIP_BUSLOGIC_PCI)) + { + bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 1; + } + else + { + bl->LocalRAM.structured.autoSCSIData.fLevelSensitiveInterrupt = 0; + } + bl->LocalRAM.structured.autoSCSIData.fParityCheckingEnabled = 1; + bl->LocalRAM.structured.autoSCSIData.fExtendedTranslation = 1; + 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.fStrictRoundRobinMode = 0; + bl->LocalRAM.structured.autoSCSIData.u16UltraPermittedMask = ~0; +} + + static void * BuslogicInit(int chip) { @@ -3227,10 +3302,28 @@ BuslogicInit(int chip) } } - if (bl->has_bios && bl->chip == CHIP_BUSLOGIC_ISA) + if (bl->has_bios) { - rom_init(&bl->bios, L"roms/scsi/buslogic/542_470.ROM", 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); - } + bl->bios_size = 0x8000; + + bl->bios_mask = (bl->bios_size >> 8) & 0xff; + bl->bios_mask = (0x100 - bl->bios_mask) & 0xff; + + if(bl->chip == CHIP_BUSLOGIC_ISA) + { + rom_init(&bl->bios, L"roms/scsi/buslogic/542_470.ROM", 0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL); + } + else + { + rom_init(&bl->bios, L"roms/scsi/buslogic/494GNPCI.ROM", 0xd8000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL); + } + } + else + { + bl->bios_size = 0; + + bl->bios_mask = 0; + } pclog("Building SCSI hard disk map...\n"); build_scsi_hd_map(); @@ -3269,18 +3362,33 @@ BuslogicInit(int chip) buslogic_pci_regs[0x05] = 0; buslogic_pci_regs[0x07] = 2; #endif - buslogic_pci_bar[2].addr = 0; + +#if 0 + /* Enable our BIOS space in PCI, if needed. */ + if (bl->has_bios) + { + buslogic_pci_bar[2].addr = 0x000D8000; + } + else + { + buslogic_pci_bar[2].addr = 0; + } +#endif mem_mapping_add(&bl->mmio_mapping, 0xfffd0000, 0x20, mem_read_null, mem_read_nullw, mem_read_nulll, mem_write_null, mem_write_nullw, mem_write_nulll, NULL, MEM_MAPPING_EXTERNAL, bl); mem_mapping_disable(&bl->mmio_mapping); +#if 0 + mem_mapping_disable(&bl->bios.mapping); +#endif } pclog("Buslogic on port 0x%04X\n", bl->Base); BuslogicResetControl(bl, CTRL_HRST); + BuslogicInitializeLocalRAM(bl); return(bl); }