From 04494892cc85310a27e4a7de3473bc4d5d2cdeca Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 14:42:13 -0300 Subject: [PATCH 01/16] Make the SB16 OPL remappable by ISAPnP --- src/include/86box/snd_sb.h | 2 ++ src/sound/snd_sb.c | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/include/86box/snd_sb.h b/src/include/86box/snd_sb.h index 221696acc..3bb2a6496 100644 --- a/src/include/86box/snd_sb.h +++ b/src/include/86box/snd_sb.h @@ -126,6 +126,8 @@ typedef struct sb_t int pos; uint8_t pos_regs[8]; + + uint16_t opl_pnp_addr; } sb_t; extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 6b04254a0..db338f74e 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -86,6 +86,7 @@ static uint8_t sb_16_pnp_rom[] = { 0x47, 0x01, 0x00, 0x03, 0x30, 0x03, 0x30, 0x02, /* I/O 0x300-0x330, decodes 16-bit, 48-byte alignment, 2 addresses */ 0x47, 0x01, 0x88, 0x03, 0x88, 0x03, 0x01, 0x04, /* I/O 0x388, decodes 16-bit, 1-byte alignment, 4 addresses */ 0x38, /* end dependent functions */ + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ }; static uint8_t sb_awe32_pnp_rom[] = { @@ -1131,11 +1132,16 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) opl3_write, NULL, NULL, &sb->opl); io_removehandler(addr + 8, 0x0002, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); - io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, - opl3_write, NULL, NULL, &sb->opl); io_removehandler(addr + 4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb); + addr = sb->opl_pnp_addr; + if (addr) { + sb->opl_pnp_addr = 0; + io_removehandler(addr, 0x0004, opl3_read, NULL, NULL, + opl3_write, NULL, NULL, &sb->opl); + } + sb_dsp_setaddr(&sb->dsp, 0); sb_dsp_setirq(&sb->dsp, 0); sb_dsp_setdma8(&sb->dsp, 0); @@ -1161,9 +1167,11 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) mpu401_change_addr(sb->mpu, addr); addr = config->io[2].base; - if (addr != ISAPNP_IO_DISABLED) - io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, + if (addr != ISAPNP_IO_DISABLED) { + sb->opl_pnp_addr = addr; + io_sethandler(addr, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl); + } val = config->irq[0].irq; if (val != ISAPNP_IRQ_DISABLED) From bf12bfb2998ade7fdc846c4764bb41f2179533de Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 14:48:11 -0300 Subject: [PATCH 02/16] Fix DMA channel on AwE32 PnP preferred configuration --- src/sound/snd_sb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index db338f74e..9af43717e 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -98,7 +98,7 @@ static uint8_t sb_awe32_pnp_rom[] = { 0x82, 0x05, 0x00, 0x41, 0x75, 0x64, 0x69, 0x6f, /* ANSI identifier "Audio" */ 0x31, 0x00, /* start dependent functions, preferred */ 0x22, 0x20, 0x00, /* IRQ 5 */ - 0x2a, 0x01, 0x0c, /* DMA 1, compatibility, no count by word, count by byte, is bus master, 8-bit only */ + 0x2a, 0x02, 0x0c, /* DMA 1, compatibility, no count by word, count by byte, is bus master, 8-bit only */ 0x2a, 0x20, 0x16, /* DMA 5, compatibility, count by word, no count by byte, is bus master, 16-bit only */ 0x47, 0x01, 0x20, 0x02, 0x20, 0x02, 0x01, 0x10, /* I/O 0x220, decodes 16-bit, 1-byte alignment, 16 addresses */ 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x01, 0x02, /* I/O 0x330, decodes 16-bit, 1-byte alignment, 2 addresses */ From c6bbfd296ce14ef9663f15e33b9b1f1699115309 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 14:53:26 -0300 Subject: [PATCH 03/16] Switch SB ISAPnP ROMs to character literals on ANSI identifiers --- src/sound/snd_sb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 9af43717e..7ccf4b164 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -74,10 +74,10 @@ static const int sb_pro_mcv_irqs[4] = {7, 5, 3, 3}; static uint8_t sb_16_pnp_rom[] = { 0x0e, 0x8c, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL0028, dummy checksum (filled in by isapnp_add_card) */ 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x82, 0x11, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x53, 0x42, 0x31, 0x36, 0x20, 0x50, 0x6e, 0x50, /* ANSI identifier "Creative SB16 PnP" */ + 0x82, 0x11, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', '1', '6', ' ', 'P', 'n', 'P', /* ANSI identifier */ 0x15, 0x0e, 0x8c, 0x00, 0x31, 0x00, /* logical device CTL0031 */ - 0x82, 0x05, 0x00, 0x41, 0x75, 0x64, 0x69, 0x6f, /* ANSI identifier "Audio" */ + 0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */ 0x30, /* start dependent functions, acceptable */ 0x22, 0xa0, 0x04, /* IRQ 5/7/10 */ 0x2a, 0x0b, 0x08, /* DMA 0/1/3, compatibility, no count by word, count by byte, not bus master, 8-bit only */ @@ -92,10 +92,10 @@ static uint8_t sb_16_pnp_rom[] = { static uint8_t sb_awe32_pnp_rom[] = { 0x0e, 0x8c, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, /* CTL009C, dummy checksum (filled in by isapnp_add_card) */ 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x82, 0x11, 0x00, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x76, 0x65, 0x20, 0x53, 0x42, 0x33, 0x32, 0x20, 0x50, 0x6e, 0x50, /* ANSI identifier "Creative SB32 PnP" */ + 0x82, 0x11, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', '3', '2', ' ', 'P', 'n', 'P', /* ANSI identifier */ 0x16, 0x0e, 0x8c, 0x00, 0x41, 0x00, 0xa9, /* logical device CTL0041, supports vendor-specific registers 0x38/0x3a/0x3c/0x3f */ - 0x82, 0x05, 0x00, 0x41, 0x75, 0x64, 0x69, 0x6f, /* ANSI identifier "Audio" */ + 0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */ 0x31, 0x00, /* start dependent functions, preferred */ 0x22, 0x20, 0x00, /* IRQ 5 */ 0x2a, 0x02, 0x0c, /* DMA 1, compatibility, no count by word, count by byte, is bus master, 8-bit only */ @@ -146,7 +146,7 @@ static uint8_t sb_awe32_pnp_rom[] = { 0x38, /* end dependent functions */ 0x16, 0x0e, 0x8c, 0x00, 0x21, 0x00, 0xa9, /* logical device CTL0021, supports vendor-specific registers 0x38/0x3a/0x3c/0x3f */ - 0x82, 0x09, 0x00, 0x57, 0x61, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, /* ANSI identifier "WaveTable" */ + 0x82, 0x09, 0x00, 'W', 'a', 'v', 'e', 'T', 'a', 'b', 'l', 'e', /* ANSI identifier */ 0x31, 0x00, /* start dependent functions, preferred */ 0x47, 0x01, 0x20, 0x06, 0x20, 0x06, 0x01, 0x04, /* I/O 0x620, decodes 16-bit, 1-byte alignment, 4 addresses */ 0x30, /* start dependent functions, acceptable */ From 966ddba554fd0d738a7d692e57d880ffe7721e43 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 14:54:34 -0300 Subject: [PATCH 04/16] Disable DMA channels when resetting ISAPnP logical devices --- src/device/isapnp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 9b8ab6923..341a9ff7e 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -157,6 +157,16 @@ isapnp_device_config_changed(isapnp_t *dev) } +static void +isapnp_reset_ld_regs(isapnp_device_t *ld) +{ + memset(ld->regs, 0, sizeof(ld->regs)); + + /* DMA disable uses a non-zero value. */ + ld->regs[0x74] = ld->regs[0x75] = ISAPNP_DMA_DISABLED; +} + + static uint8_t isapnp_read_rangecheck(uint16_t addr, void *priv) { @@ -356,9 +366,9 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) while (card) { ld = card->first_ld; while (ld) { - memset(ld->regs, 0, sizeof(ld->regs)); dev->current_ld = ld; dev->current_ld_card = card; + isapnp_reset_ld_regs(ld); isapnp_device_config_changed(dev); ld = ld->next; } @@ -443,6 +453,8 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) dev->current_ld_card = card; dev->current_ld = ld; + isapnp_reset_ld_regs(ld); + /* Logical device just created, no need to signal a change. */ if (!card->first_ld) { card->first_ld = ld; From 885309aa55ea90118c0f61038a1e0388c561724d Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 18:29:18 -0300 Subject: [PATCH 05/16] Add memory range upper limit support to ISAPnP --- src/device/isapnp.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 08290e10b..99717e699 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -130,12 +130,18 @@ isapnp_device_config_changed(isapnp_t *dev) for (i = 0; i < 4; i++) { reg_base = 0x40 + (8 * i); card->config.mem[i].base = (ld->regs[reg_base] << 16) | (ld->regs[reg_base + 1] << 8); - card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8); + if (ld->regs[reg_base + 2] & 0x01) /* upper limit */ + card->config.mem[i].size = ((ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8)) - card->config.mem[i].base - 1; + else /* range length */ + card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8); } for (i = 0; i < 4; i++) { reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i)); card->config.mem32[i].base = (ld->regs[reg_base] << 24) | (ld->regs[reg_base + 1] << 16) | (ld->regs[reg_base + 2] << 8) | ld->regs[reg_base + 3]; - card->config.mem32[i].size = (ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8]; + if (ld->regs[reg_base + 4] & 0x01) /* upper limit */ + card->config.mem32[i].size = ((ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8]) - card->config.mem32[i].base - 1; + else + card->config.mem32[i].size = (ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8]; } for (i = 0; i < 8; i++) { reg_base = 0x60 + (2 * i); From 9f9f5a10260f4519e751a890eb736c136b59a0ad Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 18:29:58 -0300 Subject: [PATCH 06/16] Initial attempt at AHA-1542CP --- src/include/86box/scsi_aha154x.h | 1 + src/include/86box/scsi_x54x.h | 1 + src/scsi/scsi.c | 1 + src/scsi/scsi_aha154x.c | 118 +++++++++++++++++++++++++++++-- src/scsi/scsi_x54x.c | 2 +- 5 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/include/86box/scsi_aha154x.h b/src/include/86box/scsi_aha154x.h index e7b3d62c0..ed9002ae7 100644 --- a/src/include/86box/scsi_aha154x.h +++ b/src/include/86box/scsi_aha154x.h @@ -5,6 +5,7 @@ extern const device_t aha154xa_device; extern const device_t aha154xb_device; extern const device_t aha154xc_device; extern const device_t aha154xcf_device; +extern const device_t aha154xcp_device; extern const device_t aha1640_device; extern void aha_device_reset(void *p); diff --git a/src/include/86box/scsi_x54x.h b/src/include/86box/scsi_x54x.h index 6c8164902..cba887ffa 100644 --- a/src/include/86box/scsi_x54x.h +++ b/src/include/86box/scsi_x54x.h @@ -367,6 +367,7 @@ typedef struct { #define X54X_LBA_BIOS 4 #define X54X_INT_GEOM_WRITABLE 8 #define X54X_MBX_24BIT 16 +#define X54X_ISAPNP 32 typedef struct { /* 32 bytes */ diff --git a/src/scsi/scsi.c b/src/scsi/scsi.c index 06439cfdd..bbf728431 100644 --- a/src/scsi/scsi.c +++ b/src/scsi/scsi.c @@ -61,6 +61,7 @@ static SCSI_CARD scsi_cards[] = { { "aha154xb", &aha154xb_device, }, { "aha154xc", &aha154xc_device, }, { "aha154xcf", &aha154xcf_device, }, + { "aha154xcp", &aha154xcp_device, }, { "bt542b", &buslogic_542b_1991_device, }, { "bt542bh", &buslogic_device, }, { "bt545s", &buslogic_545s_device, }, diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index 8e4bf93be..f0a30d06e 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -38,6 +38,7 @@ #include <86box/plat.h> #include <86box/fdd.h> #include <86box/fdc.h> +#include <86box/isapnp.h> #include <86box/scsi.h> #include <86box/scsi_aha154x.h> #include <86box/scsi_x54x.h> @@ -70,6 +71,45 @@ uint16_t aha_ports[] = { 0x0130, 0x0134, 0x0000, 0x0000 }; +static uint8_t aha1542cp_pnp_rom[] = { + 0x04, 0x90, 0x15, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* ADP1542, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + 0x82, 0x12, 0x00, 'A', 'd', 'a', 'p', 't', 'e', 'c', ' ', 'A', 'H', 'A', '-', '1', '5', '4', '2', 'C', 'P', /* ANSI identifier */ + + 0x15, 0x04, 0x90, 0x15, 0x42, 0x01, /* logical device ADP1542, can participate in boot */ + 0x82, 0x11, 0x00, 'S', 'C', 'S', 'I', ' ', 'H', 'o', 's', 't', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r', /* ANSI identifier */ + 0x1c, 0x41, 0xd0, 0x00, 0xa0, /* compatible device PNP00A0 */ + 0x22, 0x00, 0xde, /* IRQ 9/10/11/12/14/15 */ + 0x2a, 0xe1, 0x3a, /* DMA 0/5/6/7, type A, count by word, count by byte, not bus master, 16-bit only */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x04, 0x04, /* I/O 0x330, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x34, 0x03, 0x34, 0x03, 0x04, 0x04, /* I/O 0x334, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x34, 0x02, 0x34, 0x02, 0x04, 0x04, /* I/O 0x234, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x30, 0x02, 0x30, 0x02, 0x04, 0x04, /* I/O 0x230, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x47, 0x01, 0x34, 0x01, 0x34, 0x01, 0x04, 0x04, /* I/O 0x134, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x31, 0x02, /* start dependent functions, functional */ + 0x47, 0x01, 0x30, 0x01, 0x30, 0x01, 0x04, 0x04, /* I/O 0x130, decodes 16-bit, 4-byte alignment, 4 addresses */ + 0x38, /* end dependent functions */ + 0x81, 0x09, 0x00, 0x66, 0x80, 0x0c, 0xc0, 0x0d, 0x40, 0xff, 0x40, 0x00, /* memory 0xC8000-0xDC000, expansion ROM, shadowable, 8-bit, supports high address, read-cacheable write-through, non-writeable, alignment 0xff4000, 16384 bytes */ + + 0x15, 0x04, 0x90, 0x15, 0x4f, 0x01, /* logical device ADP154F, can participate in boot */ + 0x82, 0x11, 0x00, 'F', 'l', 'o', 'p', 'p', 'y', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'l', 'e', 'r', /* ANSI identifier */ + 0x1c, 0x41, 0xd0, 0x00, 0x07, /* compatible device PNP0007 */ + 0x31, 0x00, /* start dependent functions, preferred */ + 0x4b, 0xf0, 0x03, 0x06, /* fixed I/O 0x3F0, 6 addresses */ + 0x30, /* start dependent functions, acceptable */ + 0x4b, 0x70, 0x03, 0x06, /* fixed I/O 0x370, 6 addresses */ + 0x38, /* end dependent functions */ + 0x22, 0x40, 0x00, /* IRQ 6 */ + 0x2a, 0x04, 0x28, /* DMA 2, type A, no count by word, count by byte, not bus master, 8-bit only */ + + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ +}; + #pragma pack(push,1) typedef struct { @@ -189,7 +229,7 @@ aha154x_eeprom(x54x_t *dev, uint8_t cmd,uint8_t arg,uint8_t len,uint8_t off,uint r = 0; aha_eeprom_save(dev); - + if (dev->type == AHA_154xCF) { if (dev->fdc_address > 0) { fdc_remove(dev->fdc); @@ -597,6 +637,64 @@ aha_mca_feedb(void *priv) } +static void +aha_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + x54x_t *dev = (x54x_t *) priv; + + switch (ld) { + case 0: + if (dev->Base) { + x54x_io_remove(dev, dev->Base, 4); + dev->Base = 0; + } + + dev->Irq = 0; + dev->DmaChannel = ISAPNP_DMA_DISABLED; + dev->rom_addr = 0; + + mem_mapping_disable(&dev->bios.mapping); + + if (config->activate) { + dev->Base = config->io[0].base; + if (dev->Base != ISAPNP_IO_DISABLED) + x54x_io_set(dev, dev->Base, 4); + + dev->Irq = config->irq[0].irq; + dev->DmaChannel = config->dma[0].dma; + + dev->rom_addr = config->mem[0].base; + if (dev->rom_addr) { + mem_mapping_enable(&dev->bios.mapping); + mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, config->mem[0].size); + } + } + + break; + + case 1: + if (dev->fdc_address) { + fdc_remove(dev->fdc); + dev->fdc_address = 0; + } + + fdc_set_irq(dev->fdc, 0); + fdc_set_dma_ch(dev->fdc, ISAPNP_DMA_DISABLED); + + if (config->activate) { + dev->fdc_address = config->io[0].base; + if (dev->fdc_address != ISAPNP_IO_DISABLED) + fdc_set_base(dev->fdc, dev->fdc_address); + + fdc_set_irq(dev->fdc, config->irq[0].irq); + fdc_set_dma_ch(dev->fdc, config->dma[0].dma); + } + + break; + } +} + + /* Initialize the board's ROM BIOS. */ static void aha_setbios(x54x_t *dev) @@ -851,7 +949,7 @@ aha_init(const device_t *info) 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->flags |= X54X_CDROM_BOOT; + dev->flags |= X54X_CDROM_BOOT; 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 */ @@ -863,16 +961,19 @@ aha_init(const device_t *info) case AHA_154xCP: strcpy(dev->name, "AHA-154xCP"); dev->bios_path = L"roms/scsi/adaptec/aha1542cp102.bin"; - dev->nvr_path = L"aha1540cp.nvr"; + dev->nvr_path = L"aha1542cp.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->flags |= X54X_ISAPNP; 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 */ + isapnp_add_card(aha1542cp_pnp_rom, sizeof(aha1542cp_pnp_rom), aha_pnp_config_changed, NULL, NULL, NULL, dev); dev->ha_bps = 10000000.0; /* fast SCSI */ + dev->fdc = device_add(&fdc_at_device); break; case AHA_1640: @@ -900,7 +1001,7 @@ aha_init(const device_t *info) /* Initialize the device. */ x54x_device_reset(dev); - if (!(dev->bus & DEVICE_MCA)) { + if (!(dev->bus & DEVICE_MCA) && !(dev->flags & X54X_ISAPNP)) { /* Register our address space. */ x54x_io_set(dev, dev->Base, 4); @@ -1297,6 +1398,15 @@ const device_t aha154xcf_device = { aha_154xcf_config }; +const device_t aha154xcp_device = { + "Adaptec AHA-154xCP", + DEVICE_ISA | DEVICE_AT, + AHA_154xCP, + aha_init, x54x_close, NULL, + { NULL }, NULL, NULL, + NULL +}; + const device_t aha1640_device = { "Adaptec AHA-1640", DEVICE_MCA, diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index a3e8d2f0d..84769ff7d 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -961,7 +961,7 @@ x54x_scsi_cmd(x54x_t *dev) else dev->callback_sub_phase = 2; - x54x_log("scsi_devices[%02i].Status = %02X\n", id, sd->status); + x54x_log("scsi_devices[%02i].Status = %02X\n", i, sd->status); } From 08ebaaae8437f8912afee27d42de63c99401cc6f Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 18:30:12 -0300 Subject: [PATCH 07/16] Cosmetic fix to Sound Blaster PnP descriptor ROMs --- src/sound/snd_sb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 7ccf4b164..ffc736132 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -94,7 +94,7 @@ static uint8_t sb_awe32_pnp_rom[] = { 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ 0x82, 0x11, 0x00, 'C', 'r', 'e', 'a', 't', 'i', 'v', 'e', ' ', 'S', 'B', '3', '2', ' ', 'P', 'n', 'P', /* ANSI identifier */ - 0x16, 0x0e, 0x8c, 0x00, 0x41, 0x00, 0xa9, /* logical device CTL0041, supports vendor-specific registers 0x38/0x3a/0x3c/0x3f */ + 0x16, 0x0e, 0x8c, 0x00, 0x41, 0x00, 0xa9, /* logical device CTL0041, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */ 0x82, 0x05, 0x00, 'A', 'u', 'd', 'i', 'o', /* ANSI identifier */ 0x31, 0x00, /* start dependent functions, preferred */ 0x22, 0x20, 0x00, /* IRQ 5 */ @@ -145,7 +145,7 @@ static uint8_t sb_awe32_pnp_rom[] = { 0x47, 0x01, 0x88, 0x03, 0x94, 0x03, 0x04, 0x04, /* I/O 0x388-0x394, decodes 16-bit, 4-byte alignment, 4 addresses */ 0x38, /* end dependent functions */ - 0x16, 0x0e, 0x8c, 0x00, 0x21, 0x00, 0xa9, /* logical device CTL0021, supports vendor-specific registers 0x38/0x3a/0x3c/0x3f */ + 0x16, 0x0e, 0x8c, 0x00, 0x21, 0x00, 0xa9, /* logical device CTL0021, supports vendor-specific registers 0x38/0x3A/0x3C/0x3F */ 0x82, 0x09, 0x00, 'W', 'a', 'v', 'e', 'T', 'a', 'b', 'l', 'e', /* ANSI identifier */ 0x31, 0x00, /* start dependent functions, preferred */ 0x47, 0x01, 0x20, 0x06, 0x20, 0x06, 0x01, 0x04, /* I/O 0x620, decodes 16-bit, 1-byte alignment, 4 addresses */ @@ -1144,8 +1144,8 @@ sb_16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) sb_dsp_setaddr(&sb->dsp, 0); sb_dsp_setirq(&sb->dsp, 0); - sb_dsp_setdma8(&sb->dsp, 0); - sb_dsp_setdma16(&sb->dsp, 0); + sb_dsp_setdma8(&sb->dsp, ISAPNP_DMA_DISABLED); + sb_dsp_setdma16(&sb->dsp, ISAPNP_DMA_DISABLED); mpu401_change_addr(sb->mpu, 0); From 1832c0f8ad2707466932e2b5279dbadcd155ffa5 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 20:58:24 -0300 Subject: [PATCH 08/16] Fix ISAPnP memory upper limit support --- src/device/isapnp.c | 227 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 185 insertions(+), 42 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 99717e699..0c6a93973 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -85,6 +85,7 @@ enum { typedef struct _isapnp_device_ { uint8_t number; uint8_t regs[256]; + uint8_t upperlimit; struct _isapnp_device_ *next; } isapnp_device_t; @@ -116,32 +117,28 @@ typedef struct { static void -isapnp_device_config_changed(isapnp_t *dev) +isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld) { /* Ignore device if it hasn't signed up for configuration changes. */ - if (!dev->current_ld_card->config_changed) + if (!card->config_changed) return; /* Populate config structure, performing endianness conversion as needed. */ - isapnp_card_t *card = dev->current_ld_card; - isapnp_device_t *ld = dev->current_ld; card->config.activate = ld->regs[0x30] & 0x01; uint8_t i, reg_base; for (i = 0; i < 4; i++) { reg_base = 0x40 + (8 * i); card->config.mem[i].base = (ld->regs[reg_base] << 16) | (ld->regs[reg_base + 1] << 8); + card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8); if (ld->regs[reg_base + 2] & 0x01) /* upper limit */ - card->config.mem[i].size = ((ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8)) - card->config.mem[i].base - 1; - else /* range length */ - card->config.mem[i].size = (ld->regs[reg_base + 3] << 16) | (ld->regs[reg_base + 4] << 8); + card->config.mem[i].size -= card->config.mem[i].base; } for (i = 0; i < 4; i++) { reg_base = (i == 0) ? 0x76 : (0x80 + (16 * i)); card->config.mem32[i].base = (ld->regs[reg_base] << 24) | (ld->regs[reg_base + 1] << 16) | (ld->regs[reg_base + 2] << 8) | ld->regs[reg_base + 3]; + card->config.mem32[i].size = (ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8]; if (ld->regs[reg_base + 4] & 0x01) /* upper limit */ - card->config.mem32[i].size = ((ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8]) - card->config.mem32[i].base - 1; - else - card->config.mem32[i].size = (ld->regs[reg_base + 5] << 24) | (ld->regs[reg_base + 6] << 16) | (ld->regs[reg_base + 7] << 8) | ld->regs[reg_base + 8]; + card->config.mem32[i].size -= card->config.mem32[i].base; } for (i = 0; i < 8; i++) { reg_base = 0x60 + (2 * i); @@ -170,6 +167,14 @@ isapnp_reset_ld_regs(isapnp_device_t *ld) /* DMA disable uses a non-zero value. */ ld->regs[0x74] = ld->regs[0x75] = ISAPNP_DMA_DISABLED; + + /* Set the upper limit bit on memory ranges which require it. */ + uint8_t i; + for (i = 0; i < 4; i++) + ld->regs[0x42 + (8 * i)] |= !!(ld->upperlimit & (1 << i)); + ld->regs[0x7a] |= !!(ld->upperlimit & (1 << 4)); + for (i = 1; i < 4; i++) + ld->regs[0x84 + (16 * i)] |= !!(ld->upperlimit & (1 << (4 + i))); } @@ -294,6 +299,8 @@ isapnp_read_data(uint16_t addr, void *priv) ret = card->read_vendor_reg(0, dev->reg, card->priv); break; + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: @@ -394,10 +401,8 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) while (card) { ld = card->first_ld; while (ld) { - dev->current_ld = ld; - dev->current_ld_card = card; isapnp_reset_ld_regs(ld); - isapnp_device_config_changed(dev); + isapnp_device_config_changed(card, ld); ld = ld->next; } card = card->next; @@ -476,28 +481,8 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) ld = ld->next; } - if (!ld) { - isapnp_log("ISAPnP: Creating CSN %02X device %02X\n", card->csn, val); - - ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t)); - memset(ld, 0, sizeof(isapnp_device_t)); - - ld->number = val; - - dev->current_ld_card = card; - dev->current_ld = ld; - isapnp_reset_ld_regs(ld); - /* Logical device just created, no need to signal a change. */ - - if (!card->first_ld) { - card->first_ld = ld; - } else { - ld = card->first_ld; - while (ld->next) - ld = ld->next; - ld->next = dev->current_ld; - } - } + if (!ld) + fatal("ISAPnP: CSN %02X has no device %02X\n", card->csn, val); break; @@ -507,7 +492,7 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) isapnp_log("ISAPnP: Activate CSN %02X device %02X\n", dev->current_ld_card->csn, dev->current_ld->number); dev->current_ld->regs[dev->reg] = val & 0x01; - isapnp_device_config_changed(dev); + isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); break; @@ -543,6 +528,8 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) card->write_vendor_reg(0, dev->reg, val, card->priv); break; + case 0x38: case 0x39: case 0x3a: case 0x3b: + case 0x3c: case 0x3d: case 0x3e: case 0x3f: case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: @@ -554,11 +541,20 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) break; default: - if (dev->reg >= 0x38) { + if (dev->reg >= 0x40) { CHECK_CURRENT_LD(); isapnp_log("ISAPnP: Write %02X to register %02X on CSN %02X device %02X\n", val, dev->reg, dev->current_ld_card->csn, dev->current_ld->number); + + switch (dev->reg) { + case 0x42: case 0x4a: case 0x52: case 0x5a: + case 0x7a: case 0x84: case 0x94: case 0xa4: + /* read-only memory range length / upper limit bit */ + val = (val & 0xfe) | (dev->current_ld->regs[dev->reg] & 0x01); + break; + } + dev->current_ld->regs[dev->reg] = val; - isapnp_device_config_changed(dev); + isapnp_device_config_changed(dev->current_ld_card, dev->current_ld); } break; } @@ -639,12 +635,159 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, if (!dev->first_card) { dev->first_card = card; } else { - isapnp_card_t *current_card = dev->first_card; - while (current_card->next) - current_card = current_card->next; - current_card->next = card; + isapnp_card_t *prev_card = dev->first_card; + while (prev_card->next) + prev_card = prev_card->next; + prev_card->next = card; } + /* Parse resources in ROM to allocate logical devices, and determine + which memory ranges use upper limit or range length addressing. */ +#ifdef ENABLE_ISAPNP_LOG + uint16_t vendor = (card->rom[0] << 8) | card->rom[1]; + isapnp_log("ISAPnP: Parsing ROM resources for card %c%c%c%02X%02X (serial %08X)\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[2], card->rom[3], (card->rom[7] << 24) | (card->rom[6] << 16) | (card->rom[5] << 8) | card->rom[4]); +#endif + uint16_t i = 9; + uint8_t ldn = 0, res, in_df = 0; + uint8_t mem_range = 0, mem_range_32 = 0, mem_range_df = 0, mem_range_32_df = 0; + uint32_t len; + isapnp_device_t *ld = NULL, *prev_ld = NULL; + + while (i < card->rom_size) { + if (card->rom[i] & 0x80) { /* large resource */ + res = card->rom[i] & 0x7f; + len = (card->rom[i + 2] << 8) | card->rom[i + 1]; + + switch (res) { + case 0x01: /* memory range */ + case 0x05: /* 32-bit memory range */ + if (res == 0x01) { + if (mem_range > 3) + fatal("ISAPnP: Memory descriptor overflow (%d)\n", mem_range); + + isapnp_log("ISAPnP: >>%s Memory range %d uses upper limit = ", in_df ? ">" : "", mem_range); + res = 1 << mem_range; + mem_range++; + if (!in_df) + mem_range_df++; + } else { + if (mem_range_32 > 3) + fatal("ISAPnP: 32-bit memory descriptor overflow (%d)\n", mem_range_32); + + isapnp_log("ISAPnP: >>%s 32-bit memory range %d uses upper limit = ", in_df ? ">" : "", mem_range_32); + res = 1 << (4 + mem_range_32); + mem_range_32++; + if (!in_df) + mem_range_32_df++; + } + + if (card->rom[i + 3] & 0x4) { + isapnp_log("yes\n"); + ld->upperlimit |= res; + } else { + isapnp_log("no\n"); + ld->upperlimit &= ~res; + } + + break; + +#ifdef ENABLE_ISAPNP_LOG + case 0x02: /* ANSI identifier */ + res = card->rom[i + 3 + len]; + card->rom[i + 3 + len] = '\0'; + isapnp_log("ISAPnP: >%s ANSI identifier: \"%s\"\n", ldn ? ">" : "", &card->rom[i + 3]); + card->rom[i + 3 + len] = res; + break; + + default: + isapnp_log("ISAPnP: >%s%s Large resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, (card->rom[i + 2] << 8) | card->rom[i + 1]); + break; +#endif + } + + i += 3; /* header */ + } else { /* small resource */ + res = (card->rom[i] >> 3) & 0x0f; + len = card->rom[i] & 0x07; + + switch (res) { + case 0x02: +#ifdef ENABLE_ISAPNP_LOG + vendor = (card->rom[i + 1] << 8) | card->rom[i + 2]; + isapnp_log("ISAPnP: > Logical device %02X: %c%c%c%02X%02X\n", ldn, '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[i + 3], card->rom[i + 4]); +#endif + + /* We're done with the previous logical device. */ + if (ld) { + prev_ld = ld; + isapnp_reset_ld_regs(ld); + } + + /* Create logical device. */ + ld = (isapnp_device_t *) malloc(sizeof(isapnp_device_t)); + memset(ld, 0, sizeof(isapnp_device_t)); + + ld->number = ldn++; + + if (prev_ld) + prev_ld->next = ld; + else + card->first_ld = ld; + + /* Start the position counts over. */ + mem_range = mem_range_32 = mem_range_df = mem_range_32_df = 0; + + break; + +#ifdef ENABLE_ISAPNP_LOG + case 0x03: /* compatible device ID */ + vendor = (card->rom[i + 1] << 8) | card->rom[i + 2]; + isapnp_log("ISAPnP: >> Compatible device ID: %c%c%c%02X%02X\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[i + 3], card->rom[i + 4]); + break; +#endif + + case 0x06: /* start dependent functions */ + isapnp_log("ISAPnP: >> Start dependent functions: %s\n", (((len == 0) || (card->rom[i + 1] == 1)) ? "acceptable" : ((card->rom[i + 1] == 0) ? "good" : ((card->rom[i + 1] == 2) ? "sub-optimal" : "unknown priority")))); + + if (in_df) { + /* We're in a dependent function and this is the next one starting. + Walk positions back to the saved values. */ + mem_range = mem_range_df; + mem_range_32 = mem_range_32_df; + } else { + /* Save current positions to restore at the next DF. */ + mem_range_df = mem_range; + mem_range_32_df = mem_range_32; + in_df = 1; + } + + break; + + case 0x07: /* end dependent functions */ + isapnp_log("ISAPnP: >> End dependent functions\n"); + in_df = 0; + break; + +#ifdef ENABLE_ISAPNP_LOG + case 0x0f: /* end tag */ + isapnp_log("ISAPnP: End card resources\n"); + break; + + default: + isapnp_log("ISAPnP: >%s%s Small resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, card->rom[i] & 0x07); + break; +#endif + } + + i++; /* header */ + } + i += len; /* specified length */ + } + + /* We're done with the last logical device. */ + if (ld) + isapnp_reset_ld_regs(ld); + return card; } From d29d51cfd893cff5050fa8d2892779f1c92c1a8e Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 23:24:36 -0300 Subject: [PATCH 09/16] Fix RTL8019AS PnP card ID --- src/network/net_ne2000.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index d655e78c8..f8441fb5c 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -108,7 +108,6 @@ typedef struct { void *pnp_card; uint8_t pnp_activate; uint8_t pnp_csnsav; - uint64_t pnp_id; uint8_t maclocal[6]; /* configured MAC (local) address */ /* RTL8019AS/RTL8029AS registers */ @@ -934,7 +933,6 @@ nic_init(const device_t *info) int i; #endif char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD"; - uint64_t *eeprom_pnp_id; /* Get the desired debug level. */ #ifdef ENABLE_NIC_LOG @@ -1111,10 +1109,6 @@ nic_init(const device_t *info) /* Add device to the PCI bus, keep its slot number. */ dev->card = pci_add_card(PCI_ADD_NORMAL, nic_pci_read, nic_pci_write, dev); - } else { - dev->pnp_id = PNP_DEVID; - dev->pnp_id <<= 32LL; - dev->pnp_id |= PNP_VENDID; } /* Initialize the RTL8029 EEPROM. */ @@ -1134,8 +1128,10 @@ nic_init(const device_t *info) dev->eeprom[0x79] = dev->eeprom[0x7D] = (PCI_VENDID>>8); } else { - eeprom_pnp_id = (uint64_t *) &dev->eeprom[0x12]; - *eeprom_pnp_id = dev->pnp_id; + dev->eeprom[0x12] = PNP_VENDID >> 8; + dev->eeprom[0x13] = PNP_VENDID & 0xff; + dev->eeprom[0x14] = PNP_DEVID >> 8; + dev->eeprom[0x15] = PNP_DEVID & 0xff; /* TAG: Plug and Play Version Number. */ dev->eeprom[0x1B] = 0x0A; /* Item byte */ From ba8cec5e233bb4dd5ea93b049a9d82533835d660 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 20 Mar 2021 23:44:10 -0300 Subject: [PATCH 10/16] Dependent function* --- src/device/isapnp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 0c6a93973..6f869f9d4 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -746,8 +746,8 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, break; #endif - case 0x06: /* start dependent functions */ - isapnp_log("ISAPnP: >> Start dependent functions: %s\n", (((len == 0) || (card->rom[i + 1] == 1)) ? "acceptable" : ((card->rom[i + 1] == 0) ? "good" : ((card->rom[i + 1] == 2) ? "sub-optimal" : "unknown priority")))); + case 0x06: /* start dependent function */ + isapnp_log("ISAPnP: >> Start dependent function: %s\n", (((len == 0) || (card->rom[i + 1] == 1)) ? "acceptable" : ((card->rom[i + 1] == 0) ? "good" : ((card->rom[i + 1] == 2) ? "sub-optimal" : "unknown priority")))); if (in_df) { /* We're in a dependent function and this is the next one starting. @@ -763,8 +763,8 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, break; - case 0x07: /* end dependent functions */ - isapnp_log("ISAPnP: >> End dependent functions\n"); + case 0x07: /* end dependent function */ + isapnp_log("ISAPnP: >> End dependent function\n"); in_df = 0; break; From 99405a41b26aa6c2d04f81938e618487fe45f08f Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sun, 21 Mar 2021 16:59:15 -0300 Subject: [PATCH 11/16] Calculate ISAPnP checksum while parsing the end tag, allowing for ROMs not ending at the end tag checksum --- src/device/isapnp.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index 6f869f9d4..b966d6d93 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -618,14 +618,6 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, card->rom = rom; card->rom_size = rom_size; - - /* Populate descriptor checksum in ROM. */ - uint16_t checksum_offset = card->rom_size - 1; - card->rom[checksum_offset] = 0x00; - for (uint16_t i = 9; i < checksum_offset; i++) - card->rom[checksum_offset] += card->rom[i]; - card->rom[checksum_offset] = -card->rom[checksum_offset]; - card->priv = priv; card->config_changed = config_changed; card->csn_changed = csn_changed; @@ -647,7 +639,7 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, uint16_t vendor = (card->rom[0] << 8) | card->rom[1]; isapnp_log("ISAPnP: Parsing ROM resources for card %c%c%c%02X%02X (serial %08X)\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[2], card->rom[3], (card->rom[7] << 24) | (card->rom[6] << 16) | (card->rom[5] << 8) | card->rom[4]); #endif - uint16_t i = 9; + uint16_t i = 9, j; uint8_t ldn = 0, res, in_df = 0; uint8_t mem_range = 0, mem_range_32 = 0, mem_range_df = 0, mem_range_32_df = 0; uint32_t len; @@ -768,11 +760,17 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, in_df = 0; break; -#ifdef ENABLE_ISAPNP_LOG case 0x0f: /* end tag */ - isapnp_log("ISAPnP: End card resources\n"); + /* Calculate checksum. */ + res = 0x00; + for (j = 9; j <= i; j++) + res += card->rom[j]; + card->rom[i + 1] = -res; + + isapnp_log("ISAPnP: End card resources (checksum %02X)\n", card->rom[i + 1]); break; +#ifdef ENABLE_ISAPNP_LOG default: isapnp_log("ISAPnP: >%s%s Small resource %02X (length %d)\n", ldn ? ">" : "", in_df ? ">" : "", res, card->rom[i] & 0x07); break; From d9f58cfe0d77054a764663350f9c76f2a72ec6e2 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 22 Mar 2021 21:06:42 -0300 Subject: [PATCH 12/16] ISAPnP: Add IRQ type support, limit address register on 10-bit decode, and integrate card reset fix --- src/device/isapnp.c | 110 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 20 deletions(-) diff --git a/src/device/isapnp.c b/src/device/isapnp.c index b966d6d93..939b24df5 100644 --- a/src/device/isapnp.c +++ b/src/device/isapnp.c @@ -85,7 +85,7 @@ enum { typedef struct _isapnp_device_ { uint8_t number; uint8_t regs[256]; - uint8_t upperlimit; + uint8_t mem_upperlimit, irq_types, io_16bit; struct _isapnp_device_ *next; } isapnp_device_t; @@ -171,10 +171,22 @@ isapnp_reset_ld_regs(isapnp_device_t *ld) /* Set the upper limit bit on memory ranges which require it. */ uint8_t i; for (i = 0; i < 4; i++) - ld->regs[0x42 + (8 * i)] |= !!(ld->upperlimit & (1 << i)); - ld->regs[0x7a] |= !!(ld->upperlimit & (1 << 4)); + ld->regs[0x42 + (8 * i)] |= !!(ld->mem_upperlimit & (1 << i)); + ld->regs[0x7a] |= !!(ld->mem_upperlimit & (1 << 4)); for (i = 1; i < 4; i++) - ld->regs[0x84 + (16 * i)] |= !!(ld->upperlimit & (1 << (4 + i))); + ld->regs[0x84 + (16 * i)] |= !!(ld->mem_upperlimit & (1 << (4 + i))); + + /* Set the default IRQ type bits. */ + for (i = 0; i < 2; i++) { + if (ld->irq_types & (0x1 << (4 * i))) + ld->regs[0x70 + (2 * i)] = 0x02; + else if (ld->irq_types & (0x2 << (4 * i))) + ld->regs[0x70 + (2 * i)] = 0x00; + else if (ld->irq_types & (0x4 << (4 * i))) + ld->regs[0x70 + (2 * i)] = 0x03; + else if (ld->irq_types & (0x8 << (4 * i))) + ld->regs[0x70 + (2 * i)] = 0x01; + } } @@ -382,7 +394,7 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) isapnp_t *dev = (isapnp_t *) priv; isapnp_card_t *card; isapnp_device_t *ld; - uint16_t io_addr; + uint16_t io_addr, reset_cards = 0; isapnp_log("ISAPnP: write_data(%02X)\n", val); @@ -401,16 +413,21 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) while (card) { ld = card->first_ld; while (ld) { - isapnp_reset_ld_regs(ld); - isapnp_device_config_changed(card, ld); + if (card->state != PNP_STATE_WAIT_FOR_KEY) { + isapnp_reset_ld_regs(ld); + isapnp_device_config_changed(card, ld); + reset_cards++; + } ld = ld->next; } card = card->next; } - dev->current_ld = NULL; - dev->current_ld_card = NULL; - dev->isolated_card = NULL; + if (reset_cards != 0) { + dev->current_ld = NULL; + dev->current_ld_card = NULL; + dev->isolated_card = NULL; + } } if (val & 0x02) { isapnp_log("ISAPnP: Return to WAIT_FOR_KEY\n"); @@ -551,6 +568,26 @@ isapnp_write_data(uint16_t addr, uint8_t val, void *priv) /* read-only memory range length / upper limit bit */ val = (val & 0xfe) | (dev->current_ld->regs[dev->reg] & 0x01); break; + + case 0x60: case 0x62: case 0x64: case 0x66: case 0x68: case 0x6a: case 0x6c: case 0x6e: + /* discard upper address bits if this I/O range can only decode 10-bit */ + if (!(dev->current_ld->io_16bit & (1 << ((dev->reg >> 1) & 0x07)))) + val &= 0x07; + break; + + case 0x71: case 0x73: + /* limit IRQ types to supported ones */ + if ((val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0c : 0xc0))) /* level, not supported = force edge */ + val &= ~0x01; + else if (!(val & 0x01) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x03 : 0x30))) /* edge, not supported = force level */ + val |= 0x01; + + if ((val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x05 : 0x50))) /* high, not supported = force low */ + val &= ~0x02; + else if (!(val & 0x02) && !(dev->current_ld->irq_types & ((dev->reg == 0x71) ? 0x0a : 0xa0))) /* low, not supported = force high */ + val |= 0x02; + + break; } dev->current_ld->regs[dev->reg] = val; @@ -633,15 +670,15 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, prev_card->next = card; } - /* Parse resources in ROM to allocate logical devices, and determine - which memory ranges use upper limit or range length addressing. */ + /* Parse resources in ROM to allocate logical devices, + and determine the state of read-only register bits. */ #ifdef ENABLE_ISAPNP_LOG uint16_t vendor = (card->rom[0] << 8) | card->rom[1]; isapnp_log("ISAPnP: Parsing ROM resources for card %c%c%c%02X%02X (serial %08X)\n", '@' + ((vendor >> 10) & 0x1f), '@' + ((vendor >> 5) & 0x1f), '@' + (vendor & 0x1f), card->rom[2], card->rom[3], (card->rom[7] << 24) | (card->rom[6] << 16) | (card->rom[5] << 8) | card->rom[4]); #endif uint16_t i = 9, j; uint8_t ldn = 0, res, in_df = 0; - uint8_t mem_range = 0, mem_range_32 = 0, mem_range_df = 0, mem_range_32_df = 0; + uint8_t irq = 0, io = 0, mem_range = 0, mem_range_32 = 0, irq_df = 0, io_df = 0, mem_range_df = 0, mem_range_32_df = 0; uint32_t len; isapnp_device_t *ld = NULL, *prev_ld = NULL; @@ -660,8 +697,6 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, isapnp_log("ISAPnP: >>%s Memory range %d uses upper limit = ", in_df ? ">" : "", mem_range); res = 1 << mem_range; mem_range++; - if (!in_df) - mem_range_df++; } else { if (mem_range_32 > 3) fatal("ISAPnP: 32-bit memory descriptor overflow (%d)\n", mem_range_32); @@ -669,16 +704,14 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, isapnp_log("ISAPnP: >>%s 32-bit memory range %d uses upper limit = ", in_df ? ">" : "", mem_range_32); res = 1 << (4 + mem_range_32); mem_range_32++; - if (!in_df) - mem_range_32_df++; } if (card->rom[i + 3] & 0x4) { isapnp_log("yes\n"); - ld->upperlimit |= res; + ld->mem_upperlimit |= res; } else { isapnp_log("no\n"); - ld->upperlimit &= ~res; + ld->mem_upperlimit &= ~res; } break; @@ -727,7 +760,7 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, card->first_ld = ld; /* Start the position counts over. */ - mem_range = mem_range_32 = mem_range_df = mem_range_32_df = 0; + irq = io = mem_range = mem_range_32 = irq_df = io_df = mem_range_df = mem_range_32_df = 0; break; @@ -738,16 +771,38 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, break; #endif + case 0x04: /* IRQ */ + if (irq > 1) + fatal("ISAPnP: IRQ descriptor overflow (%d)\n", irq); + + if (len == 2) /* default */ + res = 0x01; /* high true edge sensitive */ + else /* specific */ + res = card->rom[i + 3] & 0x0f; + + isapnp_log("ISAPnP: >>%s IRQ index %d interrupt types = %01X\n", in_df ? ">" : "", irq, res); + + ld->irq_types &= ~(0x0f << (4 * irq)); + ld->irq_types |= res << (4 * irq); + + irq++; + + break; + case 0x06: /* start dependent function */ isapnp_log("ISAPnP: >> Start dependent function: %s\n", (((len == 0) || (card->rom[i + 1] == 1)) ? "acceptable" : ((card->rom[i + 1] == 0) ? "good" : ((card->rom[i + 1] == 2) ? "sub-optimal" : "unknown priority")))); if (in_df) { /* We're in a dependent function and this is the next one starting. Walk positions back to the saved values. */ + irq = irq_df; + io = io_df; mem_range = mem_range_df; mem_range_32 = mem_range_32_df; } else { /* Save current positions to restore at the next DF. */ + irq_df = irq; + io_df = io; mem_range_df = mem_range; mem_range_32_df = mem_range_32; in_df = 1; @@ -760,6 +815,21 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size, in_df = 0; break; + case 0x08: /* I/O port */ + if (io > 7) + fatal("ISAPnP: I/O descriptor overflow (%d)\n", io); + + isapnp_log("ISAPnP: >>%s I/O range %d %d-bit decode\n", in_df ? ">" : "", io, (card->rom[i + 1] & 0x01) ? 16 : 10); + + if (card->rom[i + 1] & 0x01) + ld->io_16bit |= 1 << io; + else + ld->io_16bit &= ~(1 << io); + + io++; + + break; + case 0x0f: /* end tag */ /* Calculate checksum. */ res = 0x00; From ac52052cfad5827067ffaf0e894584896b167188 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 22 Mar 2021 21:12:58 -0300 Subject: [PATCH 13/16] Add PCnet-ISA+ PnP network card --- src/device.c | 5 +- src/include/86box/net_pcnet.h | 6 +- src/network/net_pcnet.c | 125 +++++++++++++++++++++++++++++++--- src/network/network.c | 1 + 4 files changed, 122 insertions(+), 15 deletions(-) diff --git a/src/device.c b/src/device.c index 09f522867..8f3e153bc 100644 --- a/src/device.c +++ b/src/device.c @@ -423,8 +423,9 @@ device_get_name(const device_t *d, int bus, char *name) fbus = strstr(tname, sbus); if (fbus == tname) strcat(name, tname + strlen(sbus) + 1); - /* Special case to not strip the "oPCI" from "Ensoniq AudioPCI". */ - else if ((fbus == NULL) || (*(fbus - 1) == 'o')) + /* Special case to not strip the "oPCI" from "Ensoniq AudioPCI" or + the "-ISA" from "AMD PCnet-ISA". */ + else if ((fbus == NULL) || (*(fbus - 1) == 'o') || (*(fbus - 1) == '-')) strcat(name, tname); else { strncat(name, tname, fbus - tname - 1); diff --git a/src/include/86box/net_pcnet.h b/src/include/86box/net_pcnet.h index cab123c83..651a62198 100644 --- a/src/include/86box/net_pcnet.h +++ b/src/include/86box/net_pcnet.h @@ -24,14 +24,16 @@ enum { DEV_AM79C960 = 1, /* PCnet-ISA (ISA, 10 Mbps, NE2100/NE1500T compatible) */ DEV_AM79C960_EB = 2, /* PCnet-ISA (ISA, 10 Mbps, Racal InterLan EtherBlaster compatible) */ DEV_AM79C960_VLB = 3, /* PCnet-VLB (VLB, 10 Mbps, NE2100/NE1500T compatible) */ - DEV_AM79C970A = 4, /* PCnet-PCI II (PCI, 10 Mbps) */ - DEV_AM79C973 = 5 /* PCnet-FAST III (PCI, 10/100 Mbps) */ + DEV_AM79C961 = 4, /* PCnet-ISA+ (ISA, 10 Mbps, NE2100/NE1500T compatible, Plug and Play) */ + DEV_AM79C970A = 5, /* PCnet-PCI II (PCI, 10 Mbps) */ + DEV_AM79C973 = 6 /* PCnet-FAST III (PCI, 10/100 Mbps) */ }; extern const device_t pcnet_am79c960_device; extern const device_t pcnet_am79c960_eb_device; extern const device_t pcnet_am79c960_vlb_device; +extern const device_t pcnet_am79c961_device; extern const device_t pcnet_am79c970a_device; extern const device_t pcnet_am79c973_device; diff --git a/src/network/net_pcnet.c b/src/network/net_pcnet.c index 40d2dec6e..66c77f8fd 100644 --- a/src/network/net_pcnet.c +++ b/src/network/net_pcnet.c @@ -40,6 +40,7 @@ #include <86box/pic.h> #include <86box/random.h> #include <86box/device.h> +#include <86box/isapnp.h> #include <86box/network.h> #include <86box/net_pcnet.h> #include <86box/bswap.h> @@ -80,7 +81,7 @@ typedef struct RTNETETHERHDR #define BCR_LED1 5 #define BCR_LED2 6 #define BCR_LED3 7 -#define BCR_RESERVED8 8 +#define BCR_SWCONFIG 8 #define BCR_FDC 9 /* 10 - 15 = reserved */ #define BCR_IOBASEL 16 /* Reserved */ @@ -189,6 +190,21 @@ typedef struct RTNETETHERHDR #define PHYSADDR(S,A) ((A) | (S)->GCUpperPhys) +static const uint8_t am79c961_pnp_rom[] = { + 0x04, 0x96, 0x55, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, /* ADV55AA, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x00, /* PnP version 1.0, vendor version 0.0 */ + 0x82, 0x1c, 0x00, 'A', 'M', 'D', ' ', 'E', 't', 'h', 'e', 'r', 'n', 'e', 't', ' ', 'N', 'e', 't', 'w', 'o', 'r', 'k', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r', /* ANSI identifier */ + + 0x16, 0x04, 0x96, 0x55, 0xaa, 0x00, 0xbd, /* logical device ADV55AA, supports vendor-specific registers 0x38/0x3A/0x3B/0x3C/0x3D/0x3F */ + 0x1c, 0x41, 0xd0, 0x82, 0x8c, /* compatible device PNP828C */ + 0x47, 0x00, 0x00, 0x02, 0xe0, 0x03, 0x20, 0x18, /* I/O 0x200-0x3E0, decodes 10-bit, 32-byte alignment, 24 addresses */ + 0x2a, 0xe8, 0x02, /* DMA 3/5/6/7, compatibility, no count by word, no count by byte, not bus master, 16-bit only */ + 0x23, 0x38, 0x9e, 0x09, /* IRQ 3/4/5/9/10/11/12/15, low true level sensitive, high true edge sensitive */ + + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ +}; + + typedef struct { mem_mapping_t mmio_mapping; const char *name; @@ -211,7 +227,7 @@ typedef struct { uint32_t GCRDRA; /** Address of the TX descriptor table (ring). Loaded at init. */ uint32_t GCTDRA; - uint8_t aPROM[16]; + uint8_t aPROM[256]; uint16_t aCSR[CSR_MAX_REG]; uint16_t aBCR[BCR_MAX_RAP]; uint16_t aMII[MII_MAX_REG]; @@ -885,6 +901,7 @@ pcnetSoftReset(nic_t *dev) case DEV_AM79C960: case DEV_AM79C960_EB: case DEV_AM79C960_VLB: + case DEV_AM79C961: dev->aCSR[88] = 0x3003; dev->aCSR[89] = 0x0262; break; @@ -1750,10 +1767,6 @@ pcnetHardReset(nic_t *dev) dev->aBCR[BCR_LED1] = 0x0084; dev->aBCR[BCR_LED2] = 0x0088; dev->aBCR[BCR_LED3] = 0x0090; - - /* For ISA PnP cards, BCR8 reports IRQ/DMA (e.g. 0x0035 means IRQ 3, DMA 5). */ - if (dev->is_isa) - dev->aBCR[8] = dev->dma_channel | (dev->base_irq << 4); dev->aBCR[BCR_FDC] = 0x0000; dev->aBCR[BCR_BSBC] = 0x9001; @@ -2227,6 +2240,14 @@ pcnet_bcr_readw(nic_t *dev, uint16_t rap) } else val = 0xffff; break; + + case BCR_SWCONFIG: + if (dev->board == DEV_AM79C961) + val = ((dev->base_irq & 0x0f) << 4) | (dev->dma_channel & 0x07); + else + val = 0xffff; + break; + default: val = rap < BCR_MAX_RAP ? dev->aBCR[rap] : 0; break; @@ -2745,6 +2766,65 @@ pcnet_pci_read(int func, int addr, void *p) return(0); } +static void +pcnet_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) +{ + if (ld) + return; + + nic_t *dev = (nic_t *) priv; + + dev->base_address = 0; + dev->base_irq = 0; + dev->dma_channel = -1; + + if (dev->base_address) { + pcnet_ioremove(dev, dev->base_address, 0x20); + dev->base_address = 0; + } + + if (config->activate) { + dev->base_address = config->io[0].base; + if (dev->base_address != ISAPNP_IO_DISABLED) + pcnet_ioset(dev, dev->base_address, 0x20); + + dev->base_irq = config->irq[0].irq; + dev->dma_channel = config->dma[0].dma; + if (dev->dma_channel == ISAPNP_DMA_DISABLED) + dev->dma_channel = -1; + + /* Update PnP register mirrors in ROM. */ + dev->aPROM[32] = dev->base_address >> 8; + dev->aPROM[33] = dev->base_address; + dev->aPROM[34] = dev->base_irq; + dev->aPROM[35] = (config->irq[0].level << 1) | config->irq[0].type; + dev->aPROM[36] = (dev->dma_channel == -1) ? ISAPNP_DMA_DISABLED : dev->dma_channel; + } +} + +static uint8_t +pcnet_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv) +{ + nic_t *dev = (nic_t *) priv; + + if (!ld && (reg == 0xf0)) + return dev->aPROM[50]; + else + return 0x00; +} + +static void +pcnet_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv) +{ + if (ld) + return; + + nic_t *dev = (nic_t *) priv; + + if (reg == 0xf0) + dev->aPROM[50] = val & 0x1f; +} + /** * Takes down the link temporarily if it's current status is up. * @@ -2942,6 +3022,8 @@ pcnet_init(const device_t *info) dev->aPROM[9] = 0x11; else if (dev->is_vlb) dev->aPROM[9] = 0x10; + else if (dev->board == DEV_AM79C961) + dev->aPROM[9] = 0x01; else dev->aPROM[9] = 0x00; @@ -2981,6 +3063,18 @@ pcnet_init(const device_t *info) /* Add device to the PCI bus, keep its slot number. */ dev->card = pci_add_card(PCI_ADD_NORMAL, pcnet_pci_read, pcnet_pci_write, dev); + } else if (dev->board == DEV_AM79C961) { + dev->dma_channel = -1; + + /* Weird secondary checksum. The datasheet isn't clear on what + role it might play with the PnP register mirrors before it. */ + for (c = 0, checksum = 0; c < 54; c++) + checksum += dev->aPROM[c]; + + dev->aPROM[51] = checksum; + + memcpy(&dev->aPROM[0x40], am79c961_pnp_rom, sizeof(am79c961_pnp_rom)); + isapnp_add_card(&dev->aPROM[0x40], sizeof(am79c961_pnp_rom), pcnet_pnp_config_changed, NULL, pcnet_pnp_read_vendor_reg, pcnet_pnp_write_vendor_reg, dev); } else { dev->base_address = device_get_config_hex16("base"); dev->base_irq = device_get_config_int("irq"); @@ -3164,7 +3258,7 @@ static const device_config_t pcnet_vlb_config[] = }; const device_t pcnet_am79c960_device = { - "AMD Am79c960 (PCnet-ISA) ", + "AMD PCnet-ISA ", DEVICE_AT | DEVICE_ISA, DEV_AM79C960, pcnet_init, pcnet_close, NULL, @@ -3173,7 +3267,7 @@ const device_t pcnet_am79c960_device = { }; const device_t pcnet_am79c960_eb_device = { - "AMD Am79c960EB (PCnet-ISA) ", + "Racal Interlan EtherBlaster", DEVICE_AT | DEVICE_ISA, DEV_AM79C960_EB, pcnet_init, pcnet_close, NULL, @@ -3182,7 +3276,7 @@ const device_t pcnet_am79c960_eb_device = { }; const device_t pcnet_am79c960_vlb_device = { - "AMD Am79c960 (PCnet-VL) ", + "AMD PCnet-VL", DEVICE_VLB, DEV_AM79C960_VLB, pcnet_init, pcnet_close, NULL, @@ -3190,8 +3284,17 @@ const device_t pcnet_am79c960_vlb_device = { pcnet_vlb_config }; +const device_t pcnet_am79c961_device = { + "AMD PCnet-ISA+", + DEVICE_AT | DEVICE_ISA, + DEV_AM79C961, + pcnet_init, pcnet_close, NULL, + { NULL }, NULL, NULL, + pcnet_pci_config +}; + const device_t pcnet_am79c970a_device = { - "AMD Am79c970a (PCnet-PCI II)", + "AMD PCnet-PCI II", DEVICE_PCI, DEV_AM79C970A, pcnet_init, pcnet_close, NULL, @@ -3200,7 +3303,7 @@ const device_t pcnet_am79c970a_device = { }; const device_t pcnet_am79c973_device = { - "AMD Am79c973 (PCnet-FAST)", + "AMD PCnet-FAST III", DEVICE_PCI, DEV_AM79C973, pcnet_init, pcnet_close, NULL, diff --git a/src/network/network.c b/src/network/network.c index be7006b43..b545b08ca 100644 --- a/src/network/network.c +++ b/src/network/network.c @@ -73,6 +73,7 @@ static netcard_t net_cards[] = { { "none", NULL, NULL }, { "3c503", &threec503_device, NULL }, { "pcnetisa", &pcnet_am79c960_device, NULL }, + { "pcnetisaplus", &pcnet_am79c961_device, NULL }, { "ne1k", &ne1000_device, NULL }, { "ne2k", &ne2000_device, NULL }, { "pcnetracal", &pcnet_am79c960_eb_device, NULL }, From 4f0a88849831fd4ec79bc8a8c91092013857b393 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 22 Mar 2021 21:24:48 -0300 Subject: [PATCH 14/16] Integrate OBattler's AHA-1542CP fixes --- src/include/86box/scsi_x54x.h | 10 +- src/scsi/scsi_aha154x.c | 215 ++++++++++++++++++++++++++-------- src/scsi/scsi_x54x.c | 13 +- 3 files changed, 186 insertions(+), 52 deletions(-) diff --git a/src/include/86box/scsi_x54x.h b/src/include/86box/scsi_x54x.h index cba887ffa..5cf541c24 100644 --- a/src/include/86box/scsi_x54x.h +++ b/src/include/86box/scsi_x54x.h @@ -402,7 +402,8 @@ typedef struct { CmdBuf[128], DataBuf[65536], shadow_ram[128], - dma_buffer[128]; + dma_buffer[128], + cmd_33_buf[4096]; /* 16 bytes */ char *fw_rev; /* The 4 bytes of the revision command information + 2 extra bytes for BusLogic */ @@ -416,7 +417,11 @@ typedef struct { rom_ioaddr, /* offset in BIOS of I/O addr */ rom_shram, /* index to shared RAM */ rom_shramsz, /* size of shared RAM */ - rom_fwhigh; /* offset in BIOS of ver ID */ + rom_fwhigh, /* offset in BIOS of ver ID */ + pnp_len, /* length of the PnP ROM */ + pnp_offset, /* offset in the microcode ROM of the PnP ROM */ + cmd_33_len, /* length of the SCSISelect code decompressor program */ + cmd_33_offset; /* offset in the microcode ROM of the SCSISelect code decompressor program */ /* 16 + 20 + 52 = 88 bytes */ volatile int @@ -446,6 +451,7 @@ typedef struct { /* 8 bytes */ wchar_t *bios_path, /* path to BIOS image file */ + *mcode_path, /* path to microcode image file, needed by the AHA-1542CP */ *nvr_path; /* path to NVR image file */ /* 56 bytes */ diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index f0a30d06e..c50881b5c 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -71,44 +71,7 @@ uint16_t aha_ports[] = { 0x0130, 0x0134, 0x0000, 0x0000 }; -static uint8_t aha1542cp_pnp_rom[] = { - 0x04, 0x90, 0x15, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, /* ADP1542, dummy checksum (filled in by isapnp_add_card) */ - 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ - 0x82, 0x12, 0x00, 'A', 'd', 'a', 'p', 't', 'e', 'c', ' ', 'A', 'H', 'A', '-', '1', '5', '4', '2', 'C', 'P', /* ANSI identifier */ - - 0x15, 0x04, 0x90, 0x15, 0x42, 0x01, /* logical device ADP1542, can participate in boot */ - 0x82, 0x11, 0x00, 'S', 'C', 'S', 'I', ' ', 'H', 'o', 's', 't', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r', /* ANSI identifier */ - 0x1c, 0x41, 0xd0, 0x00, 0xa0, /* compatible device PNP00A0 */ - 0x22, 0x00, 0xde, /* IRQ 9/10/11/12/14/15 */ - 0x2a, 0xe1, 0x3a, /* DMA 0/5/6/7, type A, count by word, count by byte, not bus master, 16-bit only */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x47, 0x01, 0x30, 0x03, 0x30, 0x03, 0x04, 0x04, /* I/O 0x330, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x30, /* start dependent functions, acceptable */ - 0x47, 0x01, 0x34, 0x03, 0x34, 0x03, 0x04, 0x04, /* I/O 0x334, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x30, /* start dependent functions, acceptable */ - 0x47, 0x01, 0x34, 0x02, 0x34, 0x02, 0x04, 0x04, /* I/O 0x234, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x30, /* start dependent functions, acceptable */ - 0x47, 0x01, 0x30, 0x02, 0x30, 0x02, 0x04, 0x04, /* I/O 0x230, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x30, /* start dependent functions, acceptable */ - 0x47, 0x01, 0x34, 0x01, 0x34, 0x01, 0x04, 0x04, /* I/O 0x134, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x31, 0x02, /* start dependent functions, functional */ - 0x47, 0x01, 0x30, 0x01, 0x30, 0x01, 0x04, 0x04, /* I/O 0x130, decodes 16-bit, 4-byte alignment, 4 addresses */ - 0x38, /* end dependent functions */ - 0x81, 0x09, 0x00, 0x66, 0x80, 0x0c, 0xc0, 0x0d, 0x40, 0xff, 0x40, 0x00, /* memory 0xC8000-0xDC000, expansion ROM, shadowable, 8-bit, supports high address, read-cacheable write-through, non-writeable, alignment 0xff4000, 16384 bytes */ - - 0x15, 0x04, 0x90, 0x15, 0x4f, 0x01, /* logical device ADP154F, can participate in boot */ - 0x82, 0x11, 0x00, 'F', 'l', 'o', 'p', 'p', 'y', ' ', 'C', 'o', 'n', 't', 'r', 'o', 'l', 'l', 'e', 'r', /* ANSI identifier */ - 0x1c, 0x41, 0xd0, 0x00, 0x07, /* compatible device PNP0007 */ - 0x31, 0x00, /* start dependent functions, preferred */ - 0x4b, 0xf0, 0x03, 0x06, /* fixed I/O 0x3F0, 6 addresses */ - 0x30, /* start dependent functions, acceptable */ - 0x4b, 0x70, 0x03, 0x06, /* fixed I/O 0x370, 6 addresses */ - 0x38, /* end dependent functions */ - 0x22, 0x40, 0x00, /* IRQ 6 */ - 0x2a, 0x04, 0x28, /* DMA 2, type A, no count by word, count by byte, not bus master, 8-bit only */ - - 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ -}; +static uint8_t *aha1542cp_pnp_rom = NULL; #pragma pack(push,1) @@ -349,6 +312,12 @@ aha_param_len(void *p) case CMD_MBENABLE: return 2; + case 0x39: + return 3; + + case 0x40: + return 2; + default: return 0; } @@ -449,17 +418,47 @@ aha_cmds(void *p) } break; - case 0x2C: /* AHA-1542CP sends this */ - dev->DataBuf[0] = 0x00; + case 0x2C: /* Detect termination status */ + /* Bits 7,6 are termination status and must be 1,0 for the BIOS to work. */ + dev->DataBuf[0] = 0x40; dev->DataReplyLeft = 1; break; - case 0x33: /* AHA-1542CP sends this */ + case 0x2D: /* ???? - Returns two bytes according to the microcode */ dev->DataBuf[0] = 0x00; - dev->DataBuf[1] = 0x00; - dev->DataBuf[2] = 0x00; - dev->DataBuf[3] = 0x00; - dev->DataReplyLeft = 256; + dev->DataBuf[0] = 0x00; + dev->DataReplyLeft = 2; + break; + + case 0x33: /* Send the SCSISelect code decompressor program */ + if (dev->cmd_33_len == 0x0000) { + /* If we are on a controller without this command, return invalid command. */ + dev->DataReplyLeft = 0; + dev->Status |= STAT_INVCMD; + break; + } + + /* We have to send (decompressor program length + 2 bytes of little endian size). */ + dev->DataReplyLeft = dev->cmd_33_len + 2; + memset(dev->DataBuf, 0x00, dev->DataReplyLeft); + dev->DataBuf[0] = dev->cmd_33_len & 0xff; + dev->DataBuf[1] = (dev->cmd_33_len >> 8) & 0xff; + memcpy(&(dev->DataBuf[2]), dev->cmd_33_buf, dev->cmd_33_len); + break; + + case 0x39: /* Receive 3 bytes: address high, address low, byte to write to that address. */ + /* Since we are not running the actual microcode, just log the received values + (if logging is enabled) and break. */ + aha_log("aha_cmds(): Command 0x39: %02X -> %02X%02X\n", + dev->CmdBuf[2], dev->CmdBuf[0], dev->CmdBuf[1]); + break; + + case 0x40: /* Receive 2 bytes: address high, address low, then return one byte from that + address. */ + aha_log("aha_cmds(): Command 0x40: %02X%02X\n", + dev->CmdBuf[0], dev->CmdBuf[1]); + dev->DataReplyLeft = 1; + dev->DataBuf[0] = 0xff; break; default: @@ -641,6 +640,7 @@ static void aha_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) { x54x_t *dev = (x54x_t *) priv; + int i; switch (ld) { case 0: @@ -660,18 +660,46 @@ aha_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) if (dev->Base != ISAPNP_IO_DISABLED) x54x_io_set(dev, dev->Base, 4); + /* + * 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); + } + dev->Irq = config->irq[0].irq; dev->DmaChannel = config->dma[0].dma; + dev->nvr[1] = (dev->Irq - 9) | (dev->DmaChannel << 4); + aha_eeprom_save(dev); + dev->rom_addr = config->mem[0].base; if (dev->rom_addr) { mem_mapping_enable(&dev->bios.mapping); + aha_log("SCSI BIOS set to: %08X-%08X\n", dev->rom_addr, dev->rom_addr + config->mem[0].size - 1); mem_mapping_set_addr(&dev->bios.mapping, dev->rom_addr, config->mem[0].size); } } break; +#ifdef AHA1542CP_FDC case 1: if (dev->fdc_address) { fdc_remove(dev->fdc); @@ -691,6 +719,7 @@ aha_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv) } break; +#endif } } @@ -803,6 +832,68 @@ aha_setbios(x54x_t *dev) } +/* Get the SCSISelect code decompressor program from the microcode rom for the + AHA-1542CP. */ +static void +aha_setmcode(x54x_t *dev) +{ + uint32_t temp; + FILE *f; + + /* Only if this device has a BIOS ROM. */ + if (dev->mcode_path == NULL) return; + + /* Open the microcode image file and make sure it exists. */ + aha_log("%s: loading microcode from '%ls'\n", dev->name, dev->bios_path); + if ((f = rom_fopen(dev->mcode_path, L"rb")) == NULL) { + aha_log("%s: microcode 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); + + if (temp < (dev->cmd_33_offset + dev->cmd_33_len - 1)) { + aha_log("%s: microcode ROM size invalid!\n", dev->name); + (void)fclose(f); + return; + } + + /* Allocate the buffer and then read the real PnP ROM into it. */ + if (aha1542cp_pnp_rom != NULL) { + free(aha1542cp_pnp_rom); + aha1542cp_pnp_rom = NULL; + } + aha1542cp_pnp_rom = (uint8_t *) malloc(dev->pnp_len + 7); + fseek(f, dev->pnp_offset, SEEK_SET); + (void)fread(aha1542cp_pnp_rom, dev->pnp_len, 1, f); + memset(&(aha1542cp_pnp_rom[4]), 0x00, 5); + fseek(f, dev->pnp_offset + 4, SEEK_SET); + (void)fread(&(aha1542cp_pnp_rom[9]), dev->pnp_len - 4, 1, f); + /* Even the real AHA-1542CP microcode seem to be flipping bit + 4 to not erroneously indicate there is a range length. */ + aha1542cp_pnp_rom[0x87] |= 0x04; + /* Insert the terminator and the checksum byte that will later + be filled in by the isapnp code. */ + aha1542cp_pnp_rom[dev->pnp_len + 5] = 0x79; + aha1542cp_pnp_rom[dev->pnp_len + 6] = 0x00; + + /* Load the SCSISelect decompression code. */ + fseek(f, dev->cmd_33_offset, SEEK_SET); + (void)fread(dev->cmd_33_buf, dev->cmd_33_len, 1, f); + + (void)fclose(f); +} + + static void aha_initnvr(x54x_t *dev) { @@ -853,6 +944,18 @@ aha_setnvr(x54x_t *dev) } +void +aha1542cp_close(void *priv) +{ + if (aha1542cp_pnp_rom != NULL) { + free(aha1542cp_pnp_rom); + aha1542cp_pnp_rom = NULL; + } + + x54x_close(priv); +} + + /* General initialization routine for all boards. */ static void * aha_init(const device_t *info) @@ -889,6 +992,11 @@ aha_init(const device_t *info) dev->ven_cmds = aha_cmds; dev->get_ven_data = aha_setup_data; + dev->mcode_path = NULL; + dev->cmd_33_len = 0x0000; + dev->cmd_33_offset = 0x0000; + memset(dev->cmd_33_buf, 0x00, 4096); + strcpy(dev->vendor, "Adaptec"); /* Perform per-board initialization. */ @@ -961,19 +1069,30 @@ aha_init(const device_t *info) case AHA_154xCP: strcpy(dev->name, "AHA-154xCP"); dev->bios_path = L"roms/scsi/adaptec/aha1542cp102.bin"; + dev->mcode_path = L"roms/scsi/adaptec/908301-00_f_mcode_17c9.u12"; dev->nvr_path = L"aha1542cp.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->flags |= X54X_CDROM_BOOT; dev->flags |= X54X_ISAPNP; 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 */ - isapnp_add_card(aha1542cp_pnp_rom, sizeof(aha1542cp_pnp_rom), aha_pnp_config_changed, NULL, NULL, NULL, dev); - dev->ha_bps = 10000000.0; /* fast SCSI */ + dev->ha_bps = 10000000.0; /* fast SCSI */ + dev->pnp_len = 0x00be; /* length of the PnP ROM */ + dev->pnp_offset = 0x533d; /* offset of the PnP ROM in the microcode ROM */ + dev->cmd_33_len = 0x06dc; /* length of the SCSISelect code expansion routine returned by + SCSI controller command 0x33 */ + dev->cmd_33_offset = 0x7000; /* offset of the SCSISelect code expansion routine in the + microcode ROM */ + aha_setmcode(dev); + isapnp_add_card(aha1542cp_pnp_rom, dev->pnp_len + 7, aha_pnp_config_changed, NULL, NULL, NULL, dev); +#ifdef AHA1542CP_FDC dev->fdc = device_add(&fdc_at_device); +#endif break; case AHA_1640: @@ -1402,7 +1521,7 @@ const device_t aha154xcp_device = { "Adaptec AHA-154xCP", DEVICE_ISA | DEVICE_AT, AHA_154xCP, - aha_init, x54x_close, NULL, + aha_init, aha1542cp_close, NULL, { NULL }, NULL, NULL, NULL }; diff --git a/src/scsi/scsi_x54x.c b/src/scsi/scsi_x54x.c index 84769ff7d..5a00930aa 100644 --- a/src/scsi/scsi_x54x.c +++ b/src/scsi/scsi_x54x.c @@ -92,6 +92,8 @@ x54x_irq(x54x_t *dev, int set) else pci_clear_irq(dev->pci_slot, PCI_INTA); } else { + x54x_log("%sing IRQ %i\n", set ? "Rais" : "Lower", irq); + if (set) { if (dev->interrupt_type) int_type = dev->interrupt_type(dev); @@ -961,7 +963,7 @@ x54x_scsi_cmd(x54x_t *dev) else dev->callback_sub_phase = 2; - x54x_log("scsi_devices[%02i].Status = %02X\n", i, sd->status); + x54x_log("scsi_devices[%02i].Status = %02X\n", req->TargetID, sd->status); } @@ -1310,7 +1312,7 @@ x54x_cmd_callback(void *priv) period = (1000000.0 / dev->ha_bps) * ((double) dev->temp_period); timer_on(&dev->timer, dev->media_period + period + 10.0, 0); - x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period); + // x54x_log("Temporary period: %lf us (%" PRIi64 " periods)\n", dev->timer.period, dev->temp_period); } @@ -1371,6 +1373,13 @@ x54x_in(uint16_t port, void *priv) break; } +#ifdef ENABLE_X54X_LOG + if (port == 0x0332) + x54x_log("x54x_in(): %04X, %02X, %08X\n", port, ret, dev->DataReplyLeft); + else + x54x_log("x54x_in(): %04X, %02X\n", port, ret); +#endif + return(ret); } From c8de20625191ffea5832c6c11d867d591c9e0d0e Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 22 Mar 2021 21:45:58 -0300 Subject: [PATCH 15/16] Skip adding the AHA-1542CP to ISAPnP if the microcode is missing --- src/scsi/scsi_aha154x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/scsi/scsi_aha154x.c b/src/scsi/scsi_aha154x.c index c50881b5c..17498735a 100644 --- a/src/scsi/scsi_aha154x.c +++ b/src/scsi/scsi_aha154x.c @@ -1089,7 +1089,8 @@ aha_init(const device_t *info) dev->cmd_33_offset = 0x7000; /* offset of the SCSISelect code expansion routine in the microcode ROM */ aha_setmcode(dev); - isapnp_add_card(aha1542cp_pnp_rom, dev->pnp_len + 7, aha_pnp_config_changed, NULL, NULL, NULL, dev); + if (aha1542cp_pnp_rom) + isapnp_add_card(aha1542cp_pnp_rom, dev->pnp_len + 7, aha_pnp_config_changed, NULL, NULL, NULL, dev); #ifdef AHA1542CP_FDC dev->fdc = device_add(&fdc_at_device); #endif From 4803a6ce04ea0ed494a240f84d65e8ce3d58f50a Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Mon, 22 Mar 2021 21:47:03 -0300 Subject: [PATCH 16/16] Switch RTL8019AS to the current ISAPnP ROM style --- src/network/net_ne2000.c | 80 +++++++++------------------------------- 1 file changed, 17 insertions(+), 63 deletions(-) diff --git a/src/network/net_ne2000.c b/src/network/net_ne2000.c index f8441fb5c..64814221c 100644 --- a/src/network/net_ne2000.c +++ b/src/network/net_ne2000.c @@ -68,13 +68,6 @@ #include <86box/isapnp.h> -enum { - PNP_PHASE_WAIT_FOR_KEY = 0, - PNP_PHASE_CONFIG, - PNP_PHASE_ISOLATION, - PNP_PHASE_SLEEP -}; - /* ROM BIOS file paths. */ #define ROM_PATH_NE1000 L"roms/network/ne1000/ne1000.rom" #define ROM_PATH_NE2000 L"roms/network/ne2000/ne2000.rom" @@ -82,13 +75,25 @@ enum { #define ROM_PATH_RTL8029 L"roms/network/rtl8029as/rtl8029as.rom" /* PCI info. */ -#define PNP_VENDID 0x4a8c /* Realtek, Inc */ #define PCI_VENDID 0x10ec /* Realtek, Inc */ -#define PNP_DEVID 0x8019 /* RTL8029AS */ #define PCI_DEVID 0x8029 /* RTL8029AS */ #define PCI_REGSIZE 256 /* size of PCI space */ +static uint8_t rtl8019as_pnp_rom[] = { + 0x4a, 0x8c, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, /* RTL8019, dummy checksum (filled in by isapnp_add_card) */ + 0x0a, 0x10, 0x10, /* PnP version 1.0, vendor version 1.0 */ + 0x82, 0x22, 0x00, 'R', 'E', 'A', 'L', 'T', 'E', 'K', ' ', 'P', 'L', 'U', 'G', ' ', '&', ' ', 'P', 'L', 'A', 'Y', ' ', 'E', 'T', 'H', 'E', 'R', 'N', 'E', 'T', ' ', 'C', 'A', 'R', 'D', 0x00, /* ANSI identifier */ + + 0x16, 0x4a, 0x8c, 0x80, 0x19, 0x02, 0x00, /* logical device RTL8019 */ + 0x1c, 0x41, 0xd0, 0x80, 0xd6, /* compatible device PNP80D6 */ + 0x47, 0x00, 0x20, 0x02, 0x80, 0x03, 0x20, 0x20, /* I/O 0x220-0x380, decodes 10-bit, 32-byte alignment, 32 addresses */ + 0x23, 0x38, 0x9e, 0x01, /* IRQ 3/4/5/9/10/11/12/15, high true edge sensitive */ + + 0x79, 0x00 /* end tag, dummy checksum (filled in by isapnp_add_card) */ +}; + + typedef struct { dp8390_t *dp8390; const char *name; @@ -932,7 +937,6 @@ nic_init(const device_t *info) #ifdef ENABLE_NIC_LOG int i; #endif - char *ansi_id = "REALTEK PLUG & PLAY ETHERNET CARD"; /* Get the desired debug level. */ #ifdef ENABLE_NIC_LOG @@ -1122,65 +1126,15 @@ nic_init(const device_t *info) dev->eeprom[0x7E] = (PCI_DEVID&0xff); dev->eeprom[0x77] = dev->eeprom[0x7B] = - dev->eeprom[0x7F] = (dev->board == NE2K_RTL8019AS) ? (PNP_DEVID>>8) : (PCI_DEVID>>8); + dev->eeprom[0x7F] = (PCI_DEVID>>8); dev->eeprom[0x78] = dev->eeprom[0x7C] = (PCI_VENDID&0xff); dev->eeprom[0x79] = dev->eeprom[0x7D] = (PCI_VENDID>>8); } else { - dev->eeprom[0x12] = PNP_VENDID >> 8; - dev->eeprom[0x13] = PNP_VENDID & 0xff; - dev->eeprom[0x14] = PNP_DEVID >> 8; - dev->eeprom[0x15] = PNP_DEVID & 0xff; + memcpy(&dev->eeprom[0x12], rtl8019as_pnp_rom, sizeof(rtl8019as_pnp_rom)); - /* TAG: Plug and Play Version Number. */ - dev->eeprom[0x1B] = 0x0A; /* Item byte */ - dev->eeprom[0x1C] = 0x10; /* PnP version */ - dev->eeprom[0x1D] = 0x10; /* Vendor version */ - - /* TAG: ANSI Identifier String. */ - dev->eeprom[0x1E] = 0x82; /* Item byte */ - dev->eeprom[0x1F] = 0x22; /* Length bits 7-0 */ - dev->eeprom[0x20] = 0x00; /* Length bits 15-8 */ - memcpy(&dev->eeprom[0x21], ansi_id, 0x22); - - /* TAG: Logical Device ID. */ - dev->eeprom[0x43] = 0x16; /* Item byte */ - dev->eeprom[0x44] = 0x4A; /* Logical device ID0 */ - dev->eeprom[0x45] = 0x8C; /* Logical device ID1 */ - dev->eeprom[0x46] = 0x80; /* Logical device ID2 */ - dev->eeprom[0x47] = 0x19; /* Logical device ID3 */ - dev->eeprom[0x48] = 0x02; /* Flag0 (02=BROM/disabled) */ - dev->eeprom[0x49] = 0x00; /* Flag 1 */ - - /* TAG: Compatible Device ID (NE2000) */ - dev->eeprom[0x4A] = 0x1C; /* Item byte */ - dev->eeprom[0x4B] = 0x41; /* Compatible ID0 */ - dev->eeprom[0x4C] = 0xD0; /* Compatible ID1 */ - dev->eeprom[0x4D] = 0x80; /* Compatible ID2 */ - dev->eeprom[0x4E] = 0xD6; /* Compatible ID3 */ - - /* TAG: I/O Format */ - dev->eeprom[0x4F] = 0x47; /* Item byte */ - dev->eeprom[0x50] = 0x00; /* I/O information */ - dev->eeprom[0x51] = 0x20; /* Min. I/O base bits 7-0 */ - dev->eeprom[0x52] = 0x02; /* Min. I/O base bits 15-8 */ - dev->eeprom[0x53] = 0x80; /* Max. I/O base bits 7-0 */ - dev->eeprom[0x54] = 0x03; /* Max. I/O base bits 15-8 */ - dev->eeprom[0x55] = 0x20; /* Base alignment */ - dev->eeprom[0x56] = 0x20; /* Range length */ - - /* TAG: IRQ Format. */ - dev->eeprom[0x57] = 0x23; /* Item byte */ - dev->eeprom[0x58] = 0x38; /* IRQ mask bits 7-0 */ - dev->eeprom[0x59] = 0x9E; /* IRQ mask bits 15-8 */ - dev->eeprom[0x5A] = 0x01; /* IRQ information */ - - /* TAG: END Tag */ - dev->eeprom[0x5B] = 0x79; /* Item byte */ - /* Checksum is filled in by isapnp_add_card */ - - dev->pnp_card = isapnp_add_card(&dev->eeprom[0x12], 75, nic_pnp_config_changed, nic_pnp_csn_changed, nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, dev); + dev->pnp_card = isapnp_add_card(&dev->eeprom[0x12], sizeof(rtl8019as_pnp_rom), nic_pnp_config_changed, nic_pnp_csn_changed, nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg, dev); } }