Added some things that were missing from the DMA controller;

Fixed a link-breaking bug in cdrom.c;
The AHA-154x now supports commands 0x28 (GET EXTENDED BIOS INFO) and 0x29 (UNLOCK MAILBOX) and no longer reports a firmware revision with scatter/gather bug;
The BusLogic now supports command 0x20 (RESET);
Fixed the GPIO register mapping on the National Semiconductors PC87306 Super I/O chip.
This commit is contained in:
OBattler
2017-01-26 17:20:55 +01:00
parent 89840c7fc9
commit d4afd7c2c3
7 changed files with 188 additions and 77 deletions

View File

@@ -2,7 +2,7 @@ VPATH = . dosbox lzf resid-fp slirp
CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign -g
DFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o buslogic.o cdrom.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
@@ -33,8 +33,8 @@ LIBS = -mwindows -lwinmm -lopenal.dll -lopenal -lddraw -ldinput8 -ldxguid -ld3d9
86Box.exe: $(OBJ) $(DBOBJ) $(LZFOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(DBOBJ) $(LZFOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "86Box.exe" $(LIBS)
sleep 10
strip "86Box.exe"
sleep 10
a.exe: strip "86Box.exe"
a.exe: sleep 10
all : 86Box.exe

View File

@@ -516,6 +516,7 @@ typedef struct __attribute__((packed)) Buslogic_t
int MailboxOutInterrupts;
int MbiActive[256];
int PendingInterrupt;
int Lock;
} Buslogic_t;
int scsi_model = 1;
@@ -600,6 +601,7 @@ static void BuslogicReset(Buslogic_t *Buslogic)
Buslogic->MailboxInPosCur = 0;
Buslogic->MailboxOutInterrupts = 0;
Buslogic->PendingInterrupt = 0;
Buslogic->Lock = 0;
BuslogicInOperation = 0;
BuslogicClearInterrupt(Buslogic);
@@ -1136,6 +1138,7 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
case 0x04:
case 0x0A:
case 0x0B:
case 0x20:
case 0x23:
case 0x84:
case 0x85:
@@ -1183,8 +1186,11 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Buslogic->CmdParamLeft = scsi_model ? sizeof(MailboxInitExtended_t) : 0;
break;
case 0x28:
case 0x29:
Buslogic->CmdParamLeft = scsi_model ? 0 : 2;
break;
case 0x28:
case 0x86: //Valid only for PCI
case 0x95: //Valid only for PCI
Buslogic->CmdParamLeft = 0;
@@ -1230,8 +1236,8 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
case 0x04:
Buslogic->DataBuf[0] = 0x41;
Buslogic->DataBuf[1] = scsi_model ? 0x41 : 0x30;
Buslogic->DataBuf[2] = scsi_model ? '5' : '3';
Buslogic->DataBuf[3] = scsi_model ? '0' : '1';
Buslogic->DataBuf[2] = '5';
Buslogic->DataBuf[3] = '0';
Buslogic->DataReplyLeft = 4;
break;
@@ -1363,6 +1369,18 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
Buslogic->DataReplyLeft = 1;
break;
case 0x20:
Buslogic->DataReplyLeft = 0;
if (scsi_model)
{
BuslogicResetControl(Buslogic, 1);
}
else
{
Buslogic->Status |= STAT_INVCMD;
}
break;
case 0x21:
if (Buslogic->CmdParam == 1)
Buslogic->CmdParamLeft = Buslogic->CmdBuf[0];
@@ -1397,6 +1415,43 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
picintc(1 << Buslogic->Irq);
break;
case 0x28:
if (!scsi_model)
{
Buslogic->DataBuf[0] = 0x08;
Buslogic->DataBuf[1] = Buslogic->Lock;
Buslogic->DataReplyLeft = 2;
}
else
{
Buslogic->DataReplyLeft = 0;
Buslogic->Status |= STAT_INVCMD;
}
break;
case 0x29:
if (!scsi_model)
{
if (Buslogic->CmdBuf[1] = Buslogic->Lock)
{
if (Buslogic->CmdBuf[0] & 1)
{
Buslogic->Lock = 1;
}
else
{
Buslogic->Lock = 0;
}
}
Buslogic->DataReplyLeft = 0;
}
else
{
Buslogic->DataReplyLeft = 0;
Buslogic->Status |= STAT_INVCMD;
}
break;
case 0x81:
{
if (scsi_model)
@@ -1546,8 +1601,8 @@ void BuslogicWrite(uint16_t Port, uint8_t Val, void *p)
default:
case 0x22: //undocumented
case 0x28: //only for the Adaptec 154xC series
case 0x29: //only for the Adaptec 154xC series
// case 0x28: //only for the Adaptec 154xC series
// case 0x29: //only for the Adaptec 154xC series
case 0x86: //PCI only, not ISA
case 0x95: //PCI only, not ISA
Buslogic->DataReplyLeft = 0;

View File

@@ -2322,7 +2322,7 @@ void cdrom_command(uint8_t id, uint8_t *cdb)
if (cdb[3] == 1)
{
cdbufferb[1] = cdrom_drives[id].handler->getcurrentsubchannel(id, &cdbufferb[5], msf);
if (((cdbufferb[1] == 0x13) && !completed) || (cd_status == CD_STATUS_DATA_ONLY))
if (((cdbufferb[1] == 0x13) && !completed) || (cdrom[id].cd_status == CD_STATUS_DATA_ONLY))
{
cdbufferb[1] = 0x15;
}

145
src/dma.c
View File

@@ -66,18 +66,23 @@ uint8_t dma_read(uint16_t addr, void *priv)
case 8: /*Status register*/
temp = dma.stat;
dma.stat = 0;
dma.stat &= 0xf0;
return temp;
case 0xd:
case 0xd: /*Temporary register*/
return dmaregs[addr & 0xd];
case 0xf: /*Mask register*/
return dma16.m;
default:
return 0;
}
// printf("Bad DMA read %04X %04X:%04X\n",addr,CS,pc);
return dmaregs[addr & 0xf];
}
void dma_write(uint16_t addr, uint8_t val, void *priv)
{
int channel = val & 3;
// printf("Write DMA %04X %02X %04X:%04X\n",addr,val,CS,pc);
dmaregs[addr & 0xf] = val;
switch (addr & 0xf)
@@ -103,13 +108,29 @@ void dma_write(uint16_t addr, uint8_t val, void *priv)
dma.command = val;
return;
case 9: /*Request register*/
if (val & 4)
{
dma.request |= (1 << (channel + 4));
if (dma.command & 1)
{
dma.request |= (1 << channel);
}
}
else
{
dma.request &= ~(1 << (channel + 4));
}
return;
case 0xa: /*Mask*/
if (val & 4) dma.m |= (1 << (val & 3));
else dma.m &= ~(1 << (val & 3));
return;
case 0xb: /*Mode*/
dma.mode[val & 3] = val;
dma.mode[val & 3] = val & 0xfc;
dma.stat &= ~(1 << (val & 3));
return;
case 0xc: /*Clear FF*/
@@ -135,7 +156,7 @@ void dma_write(uint16_t addr, uint8_t val, void *priv)
uint8_t dma16_read(uint16_t addr, void *priv)
{
uint8_t temp;
// printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc);
// printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,cpu_state.pc);
addr >>= 1;
switch (addr & 0xf)
{
@@ -153,15 +174,24 @@ uint8_t dma16_read(uint16_t addr, void *priv)
case 8: /*Status register*/
temp = dma16.stat;
dma16.stat = 0;
dma16.stat &= 0xf0;
return temp;
case 0xd: /*Temporary register*/
return dma16regs[addr & 0xd];
case 0xf: /*Mask register*/
return dma16.m;
default:
return 0;
}
return dma16regs[addr & 0xf];
}
void dma16_write(uint16_t addr, uint8_t val, void *priv)
{
// printf("Write dma16 %04X %02X %04X:%04X\n",addr,val,CS,pc);
int channel = val & 3;
// printf("Write dma16 %04X %02X %04X:%04X\n",addr,val,CS,cpu_state.pc);
addr >>= 1;
dma16regs[addr & 0xf] = val;
switch (addr & 0xf)
@@ -183,6 +213,22 @@ void dma16_write(uint16_t addr, uint8_t val, void *priv)
return;
case 8: /*Control register*/
dma16.command = val;
return;
case 9: /*Request register*/
if (val & 4)
{
dma16.request |= (1 << (channel + 4));
if (dma16.command & 1)
{
dma16.request |= (1 << channel);
}
}
else
{
dma16.request &= ~(1 << (channel + 4));
}
return;
case 0xa: /*Mask*/
@@ -191,7 +237,8 @@ void dma16_write(uint16_t addr, uint8_t val, void *priv)
return;
case 0xb: /*Mode*/
dma16.mode[val & 3] = val;
dma16.mode[val & 3] = val & 0xfc;
dma16.stat &= ~(1 << (val & 3));
return;
case 0xc: /*Clear FF*/
@@ -217,6 +264,7 @@ void dma16_write(uint16_t addr, uint8_t val, void *priv)
void dma_page_write(uint16_t addr, uint8_t val, void *priv)
{
// printf("Write dma16 Page %04X %02X %04X:%04X\n",addr,val,CS,cpu_state.pc);
dmapages[addr & 0xf] = val;
switch (addr & 0xf)
{
@@ -249,6 +297,7 @@ void dma_page_write(uint16_t addr, uint8_t val, void *priv)
uint8_t dma_page_read(uint16_t addr, void *priv)
{
// printf("Read DMA Page %04X %04X:%04X\n",addr,cs>>4,cpu_state.pc);
return dmapages[addr & 0xf];
}
@@ -357,6 +406,35 @@ DMA * get_dma_controller(int channel)
}
}
int dma_tc(DMA *dma_controller, int channel)
{
if (dma_controller->command & 1)
{
/* Memory to memory command */
dma_controller->stat |= (1 << 0);
dma_controller->stat |= (1 << 1);
dma_controller->request &= ~(1 << 0);
dma_controller->request &= ~(1 << 1);
}
else
{
dma_controller->stat |= (1 << channel);
dma_controller->request &= ~(1 << channel);
}
if (dma_controller->mode[channel] & 0x10) /*Auto-init*/
{
// pclog("DMA read auto-init\n");
dma_controller->cc[channel] = dma_controller->cb[channel] & 0xffff;
dma_controller->ac[channel] = dma_controller->ab[channel] & 0xffff;
}
else
{
dma_controller->cc[channel] &= 0xffff;
dma_controller->m |= (1 << channel);
}
}
int dma_channel_read(int channel)
{
uint16_t temp;
@@ -438,18 +516,7 @@ int dma_channel_read(int channel)
if ((dma_controller->cc[real_channel] < 0) || mem_over)
{
tc = 1;
if (dma_controller->mode[real_channel] & 0x10) /*Auto-init*/
{
// pclog("DMA read auto-init\n");
dma_controller->cc[real_channel] = dma_controller->cb[real_channel] & 0xffff;
dma_controller->ac[real_channel] = dma_controller->ab[real_channel] & 0xffff;
}
else
{
dma_controller->cc[real_channel] &= 0xffff;
dma_controller->m |= (1 << real_channel);
}
dma_controller->stat |= (1 << real_channel);
dma_tc(dma_controller, real_channel);
}
if (tc)
@@ -540,18 +607,7 @@ int dma_channel_write(int channel, uint16_t val)
if ((dma_controller->cc[real_channel] < 0) || mem_over)
{
tc = 1;
if (dma_controller->mode[real_channel] & 0x10) /*Auto-init*/
{
// pclog("DMA write auto-init\n");
dma_controller->cc[real_channel] = dma_controller->cb[real_channel] & 0xffff;
dma_controller->ac[real_channel] = dma_controller->ab[real_channel] & 0xffff;
}
else
{
dma_controller->cc[real_channel] &= 0xffff;
dma_controller->m |= (1 << real_channel);
}
dma_controller->stat |= (1 << real_channel);
dma_tc(dma_controller, real_channel);
}
// if (dma_is_masked(channel))
@@ -565,38 +621,17 @@ int dma_channel_write(int channel, uint16_t val)
return 0;
}
#if 0
static uint32_t PageLengthReadWrite(uint32_t PhysAddress, uint32_t TotalSize)
{
uint32_t LengthSize;
uint32_t Page;
Page = PhysAddress & 4095;
if ((Page + TotalSize - 1) >= 4096)
{
TotalSize = 4096 - Page;
}
return TotalSize;
}
#endif
//DMA Bus Master Page Read/Write
void DMAPageRead(uint32_t PhysAddress, void *DataRead, uint32_t TotalSize)
{
// uint32_t PageLen = PageLengthReadWrite(PhysAddress, TotalSize);
memcpy(DataRead, &ram[PhysAddress], TotalSize);
// DataRead -= PageLen;
DataRead -= TotalSize;
}
void DMAPageWrite(uint32_t PhysAddress, const void *DataWrite, uint32_t TotalSize)
{
// uint32_t PageLen = PageLengthReadWrite(PhysAddress, TotalSize);
mem_invalidate_range(PhysAddress, PhysAddress + TotalSize - 1);
memcpy(&ram[PhysAddress], DataWrite, TotalSize);
// DataWrite -= PageLen;
DataWrite -= TotalSize;
}

View File

@@ -308,6 +308,7 @@ typedef struct DMA
uint8_t page[4];
uint8_t stat;
uint8_t command;
uint8_t request;
} DMA;
DMA dma,dma16;

View File

@@ -170,14 +170,21 @@ void pc87306_write(uint16_t port, uint8_t val, void *priv)
if (tries)
{
if (pc87306_curreg <= 28) valxor = val ^ pc87306_regs[pc87306_curreg];
if (pc87306_curreg == 0xF) pc87306_gpio_remove();
if ((pc87306_curreg <= 28) && (pc87306_curreg != 8))
tries = 0;
if ((pc87306_curreg <= 28) && (pc87306_curreg != 8) && (pc87306_curreg != 0x18))
{
if (pc87306_curreg == 0)
{
val &= 0x5f;
}
if ((pc87306_curreg == 0x0F) || (pc87306_curreg == 0x12))
{
pc87306_gpio_remove();
}
pc87306_regs[pc87306_curreg] = val;
// pclog("Register %02X set to: %02X (was: %02X)\n", pc87306_curreg, val, pc87306_regs[pc87306_curreg]);
goto process_value;
}
tries = 0;
if ((pc87306_curreg <= 28) && (pc87306_curreg != 8)) goto process_value;
}
else
{
@@ -270,6 +277,7 @@ process_value:
fdc_update_densel_polarity((val & 0x40) ? 1 : 0);
break;
case 0xF:
case 0x12:
pc87306_gpio_init();
break;
case 0x1C:
@@ -342,7 +350,15 @@ void pc87306_gpio_remove()
void pc87306_gpio_init()
{
io_sethandler(pc87306_regs[0xF] << 2, 0x0002, pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, NULL);
if ((pc87306_regs[0x12]) & 0x10)
{
io_sethandler(pc87306_regs[0xF] << 2, 0x0001, pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, NULL);
}
if ((pc87306_regs[0x12]) & 0x20)
{
io_sethandler((pc87306_regs[0xF] << 2) + 1, 0x0001, pc87306_gpio_read, NULL, NULL, pc87306_gpio_write, NULL, NULL, NULL);
}
}
void pc87306_init()

View File

@@ -26,6 +26,7 @@ static uint8_t card_piix[256], card_piix_ide[256];
void piix_write(int func, int addr, uint8_t val, void *priv)
{
uint16_t old_base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8);
// pclog("piix_write: func=%d addr=%02x val=%02x %04x:%08x\n", func, addr, val, CS, pc);
if (func > 1)
return;
@@ -83,10 +84,13 @@ void piix_write(int func, int addr, uint8_t val, void *priv)
if (addr == 4 || (addr & ~3) == 0x20) /*Bus master base address*/
{
uint16_t base = (card_piix_ide[0x20] & 0xf0) | (card_piix_ide[0x21] << 8);
io_removehandler(0, 0x10000, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL);
io_removehandler(old_base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL);
pclog("Setting PIIX IDE bus master to new base address: %04X\n", base);
if (card_piix_ide[0x04] & 1)
{
io_sethandler(base, 0x10, piix_bus_master_read, NULL, NULL, piix_bus_master_write, NULL, NULL, NULL);
}
}
// pclog("PIIX write %02X %02X\n", addr, val);
}
else