---------------------------------------------------------------------- Patch name: patch.tekram-dc280e-vlb-ide Author: Christophe Bothamy Date: October, 8st 2002 Detailed description: This patch adds Tekram DC280E VLB-IDE support to Bochs. This card has 2 ata channels, so this would be better than the promise DC2300. Driver name is DC280EU.ZIP. It should find it somewhere on the net. Look on tekram site at: http://www.tekram.com.tw/Storageftp/IDE/DC-2X0/DC-280X/DC-280E/Driver%26AP/ Datasheet can be found at : http://www.ryston.cz/petr/vlb/vlbidechips.html With this patch win95 uses native acesses on the first four ATA/ATAPI devices. Quite a few "IO read(1f0h) with drq == 0" errors appears in the log, and seem to be related with the timing of the ATA devices. Many thanks to Volker for fixing the interrupt bug! It was not working before. Patch was created with: cvs diff -u Apply patch to what version: cvs checked out on October, 8st 2002 Instructions: To patch, go to main bochs directory. Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- =================================================================== RCS file: /cvsroot/bochs/bochs/config.h.in,v retrieving revision 1.85 diff -u -r1.85 config.h.in --- config.h.in 6 Oct 2002 14:16:13 -0000 1.85 +++ config.h.in 8 Oct 2002 14:53:44 -0000 @@ -611,6 +611,13 @@ // Promise VLBIDE DC2300 Support #define BX_PDC20230C_VLBIDE_SUPPORT 0 +// Tekram VLBIDE DC280E Support +#define BX_W83759A_VLBIDE_SUPPORT 0 + +#if (BX_PDC20230C_VLBIDE_SUPPORT == 1 && BX_W83759A_VLBIDE_SUPPORT == 1) +#error Promise DC2300 can not be used with Tekram DC280E +#endif + // dynamic translation (future: not supported yet) #define BX_DYNAMIC_TRANSLATION 0 #define BX_DYNAMIC_CPU_I386 0 Index: configure =================================================================== RCS file: /cvsroot/bochs/bochs/configure,v retrieving revision 1.148 diff -u -r1.148 configure --- configure 6 Oct 2002 14:16:13 -0000 1.148 +++ configure 8 Oct 2002 14:53:46 -0000 @@ -855,6 +855,7 @@ --enable-ne2000 enable limited ne2000 support --enable-pci enable limited i440FX PCI support --enable-dc2300-vlb-ide enable Promise DC2300 VLB-IDE support + --enable-dc280e-vlb-ide enable Tekram DC280E VLB-IDE support --enable-4meg-pages support 4Megabyte pages extensions --enable-pae support Physical Address Extensions --enable-guest2host-tlb support guest to host addr TLB for speed @@ -9267,6 +9268,38 @@ echo "${ECHO_T}no" >&6 cat >>confdefs.h <<\_ACEOF #define BX_PDC20230C_VLBIDE_SUPPORT 0 +_ACEOF + + + +fi; + +echo "$as_me:$LINENO: checking for Tekram DC280E VLB-IDE support" >&5 +echo $ECHO_N "checking for Tekram DC280E VLB-IDE support... $ECHO_C" >&6 +# Check whether --enable-dc280e-vlb-ide or --disable-dc280e-vlb-ide was given. +if test "${enable_dc280e_vlb_ide+set}" = set; then + enableval="$enable_dc280e_vlb_ide" + if test "$enableval" = yes; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + cat >>confdefs.h <<\_ACEOF +#define BX_W83759A_VLBIDE_SUPPORT 1 +_ACEOF + + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + cat >>confdefs.h <<\_ACEOF +#define BX_W83759A_VLBIDE_SUPPORT 0 +_ACEOF + + fi +else + + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + cat >>confdefs.h <<\_ACEOF +#define BX_W83759A_VLBIDE_SUPPORT 0 _ACEOF Index: configure.in =================================================================== RCS file: /cvsroot/bochs/bochs/configure.in,v retrieving revision 1.148 diff -u -r1.148 configure.in --- configure.in 5 Oct 2002 12:07:51 -0000 1.148 +++ configure.in 8 Oct 2002 14:53:47 -0000 @@ -563,6 +563,22 @@ ] ) +AC_MSG_CHECKING(for Tekram DC280E VLB-IDE support) +AC_ARG_ENABLE(dc280e-vlb-ide, + [ --enable-dc280e-vlb-ide enable Tekram DC280E VLB-IDE support], + [if test "$enableval" = yes; then + AC_MSG_RESULT(yes) + AC_DEFINE(BX_W83759A_VLBIDE_SUPPORT, 1) + else + AC_MSG_RESULT(no) + AC_DEFINE(BX_W83759A_VLBIDE_SUPPORT, 0) + fi], + [ + AC_MSG_RESULT(no) + AC_DEFINE(BX_W83759A_VLBIDE_SUPPORT, 0) + ] + ) + AC_MSG_CHECKING(for 4Meg pages support) AC_ARG_ENABLE(4meg-pages, Index: iodev/harddrv.cc =================================================================== RCS file: /cvsroot/bochs/bochs/iodev/harddrv.cc,v retrieving revision 1.80 diff -u -r1.80 harddrv.cc --- iodev/harddrv.cc 6 Oct 2002 20:19:03 -0000 1.80 +++ iodev/harddrv.cc 8 Oct 2002 14:53:48 -0000 @@ -337,6 +337,38 @@ BX_HD_THIS pdc20230c.p1f4_value = 0; #endif +#if BX_W83759A_VLBIDE_SUPPORT + + BX_HD_THIS devices->register_io_read_handler(this, w83759a_read_handler, BX_W83759A_IDIN, "W83759A"); + BX_HD_THIS devices->register_io_write_handler(this, w83759a_write_handler, BX_W83759A_IDIN, "W83759A"); + BX_HD_THIS devices->register_io_read_handler(this, w83759a_read_handler, BX_W83759A_INDEX, "W83759A"); + BX_HD_THIS devices->register_io_write_handler(this, w83759a_write_handler, BX_W83759A_INDEX, "W83759A"); + BX_HD_THIS devices->register_io_read_handler(this, w83759a_read_handler, BX_W83759A_DATA, "W83759A"); + BX_HD_THIS devices->register_io_write_handler(this, w83759a_write_handler, BX_W83759A_DATA, "W83759A"); + BX_HD_THIS devices->register_io_read_handler(this, w83759a_read_handler, BX_W83759A_IDOUT, "W83759A"); + BX_HD_THIS devices->register_io_write_handler(this, w83759a_write_handler, BX_W83759A_IDOUT, "W83759A"); + + BX_HD_THIS w83759a.detected = false; + BX_HD_THIS w83759a.prog_mode = 0; + BX_HD_THIS w83759a.index = 0x80; + BX_HD_THIS w83759a.registers[0x0] = 0x8f; + BX_HD_THIS w83759a.registers[0x1] = 0x8f; + BX_HD_THIS w83759a.registers[0x2] = 0xff; + BX_HD_THIS w83759a.registers[0x3] = 0xff; + BX_HD_THIS w83759a.registers[0x4] = 0xff; + BX_HD_THIS w83759a.registers[0x5] = 0xff; + BX_HD_THIS w83759a.registers[0x6] = 0x80; + BX_HD_THIS w83759a.registers[0x7] = 0x8a; + BX_HD_THIS w83759a.registers[0x8] = 0x00; + BX_HD_THIS w83759a.registers[0x9] = 0x00; + BX_HD_THIS w83759a.registers[0xa] = 0x00; + BX_HD_THIS w83759a.registers[0xb] = 0x00; + BX_HD_THIS w83759a.registers[0xc] = 0x00; + BX_HD_THIS w83759a.registers[0xd] = 0x00; + BX_HD_THIS w83759a.registers[0xe] = 0x00; + BX_HD_THIS w83759a.registers[0xf] = 0x00; + +#endif // generate CMOS values for hard drive if not using a CMOS image if (!bx_options.cmos.OcmosImage->get ()) { @@ -434,6 +466,31 @@ if (BX_HD_THIS channels[channel].irq) BX_HD_THIS devices->pic->lower_irq(BX_HD_THIS channels[channel].irq); } + +#if BX_W83759A_VLBIDE_SUPPORT + + BX_HD_THIS w83759a.detected = false; + BX_HD_THIS w83759a.prog_mode = 0; + BX_HD_THIS w83759a.index = 0x80; + BX_HD_THIS w83759a.registers[0x0] = 0x8f; + BX_HD_THIS w83759a.registers[0x1] = 0x8f; + BX_HD_THIS w83759a.registers[0x2] = 0xff; + BX_HD_THIS w83759a.registers[0x3] = 0xff; + BX_HD_THIS w83759a.registers[0x4] = 0xff; + BX_HD_THIS w83759a.registers[0x5] = 0xff; + BX_HD_THIS w83759a.registers[0x6] = 0x80; + BX_HD_THIS w83759a.registers[0x7] = 0x8a; + BX_HD_THIS w83759a.registers[0x8] = 0x00; + BX_HD_THIS w83759a.registers[0x9] = 0x00; + BX_HD_THIS w83759a.registers[0xa] = 0x00; + BX_HD_THIS w83759a.registers[0xb] = 0x00; + BX_HD_THIS w83759a.registers[0xc] = 0x00; + BX_HD_THIS w83759a.registers[0xd] = 0x00; + BX_HD_THIS w83759a.registers[0xe] = 0x00; + BX_HD_THIS w83759a.registers[0xf] = 0x00; + +#endif + } @@ -1956,6 +2013,7 @@ case 0xef: // SET FEATURES switch(BX_SELECTED_CONTROLLER(channel).features) { + case 0x03: // Set transfer mode based on SC register. FIXME we should handle this case 0x02: // Enable and case 0x82: // Disable write cache. case 0xAA: // Enable and @@ -2282,6 +2340,118 @@ (unsigned) address, (unsigned) value)); } } + +#if BX_W83759A_VLBIDE_SUPPORT + + // static IO port read callback handler + // redirects to non-static class handler to avoid virtual functions + + Bit32u +bx_hard_drive_c::w83759a_read_handler(void *this_ptr, Bit32u address, unsigned io_len) +{ +#if !BX_USE_HD_SMF + bx_hard_drive_c *class_ptr = (bx_hard_drive_c *) this_ptr; + + return( class_ptr->w83759a_read(address, io_len) ); +} + + + Bit32u +bx_hard_drive_c::w83759a_read(Bit32u address, unsigned io_len) +{ +#else + UNUSED(this_ptr); +#endif // !BX_USE_HD_SMF + + Bit8u value8 = 0xff; + + if (!BX_HD_THIS w83759a.detected) { + BX_HD_THIS w83759a.detected = true; + BX_INFO(("Tekram VLB-IDE DC280E accessed")); + } + + BX_DEBUG(("W83759A VLBIDE: read access port %04x, iolen=%x", address, io_len)); + + switch(address) { + case BX_W83759A_IDIN: + BX_INFO(("W83759A VLBIDE: read from IDIN !")); + break; + case BX_W83759A_INDEX: + value8 = BX_HD_THIS w83759a.index; + BX_DEBUG(("W83759A VLBIDE: read from INDEX returning %02x",value8)); + break; + case BX_W83759A_DATA: + if ((BX_HD_THIS w83759a.index < 0x80) || (BX_HD_THIS w83759a.index > 0x8f)) value8 = 0xff; + else value8 = BX_HD_THIS w83759a.registers[BX_HD_THIS w83759a.index&0xf]; + BX_DEBUG(("W83759A VLBIDE: read from DATA returning reg %02x %02x",BX_HD_THIS w83759a.index,value8)); + break; + case BX_W83759A_IDOUT: + value8 = BX_W83759A_ID; + BX_DEBUG(("W83759A VLBIDE: read from IDOUT returning %02x",value8)); + break; + } + + return value8; +} + + // static IO port write callback handler + // redirects to non-static class handler to avoid virtual functions + + void +bx_hard_drive_c::w83759a_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) +{ +#if !BX_USE_HD_SMF + bx_hard_drive_c *class_ptr = (bx_hard_drive_c *) this_ptr; + + class_ptr->w83759a_write(address, value, io_len); +} + + void +bx_hard_drive_c::w83759a_write(Bit32u address, Bit32u value, unsigned io_len) +{ +#else + UNUSED(this_ptr); +#endif // !BX_USE_HD_SMF + + BX_DEBUG(("W83759A VLBIDE: write access port %04x, iolen=%x", address, io_len)); + + switch(address) { + case BX_W83759A_IDIN: + BX_DEBUG(("W83759A VLBIDE: write to IDIN value %x",value)); + if (value == BX_W83759A_ID) { + BX_DEBUG(("W83759A VLBIDE: Entering programming sequence")); + BX_HD_THIS w83759a.prog_mode = 1; + } + else { + BX_DEBUG(("W83759A VLBIDE: Leaving programming sequence")); + BX_HD_THIS w83759a.prog_mode = 0; + } + break; + case BX_W83759A_INDEX: + BX_DEBUG(("W83759A VLBIDE: write to INDEX value %x",value)); + BX_HD_THIS w83759a.index = value; + break; + case BX_W83759A_DATA: + BX_DEBUG(("W83759A VLBIDE: write to DATA reg %02x value %x",BX_HD_THIS w83759a.index,value)); + switch (BX_HD_THIS w83759a.index&0x0f) { + case 0: + case 2: + case 4: + case 7: + BX_DEBUG(("W83759A VLBIDE: reg %02x is read only",BX_HD_THIS w83759a.index)); + break; + default: + BX_HD_THIS w83759a.registers[BX_HD_THIS w83759a.index&0x0f] = value; + BX_DEBUG(("W83759A VLBIDE: reg %02x written",BX_HD_THIS w83759a.index)); + } + break; + case BX_W83759A_IDOUT: + BX_DEBUG(("W83759A VLBIDE: write to IDOUT discarded")); + break; + } + +} +#endif void bx_hard_drive_c::close_harddrive(void) Index: iodev/harddrv.h =================================================================== RCS file: /cvsroot/bochs/bochs/iodev/harddrv.h,v retrieving revision 1.16 diff -u -r1.16 harddrv.h --- iodev/harddrv.h 30 Sep 2002 14:19:46 -0000 1.16 +++ iodev/harddrv.h 8 Oct 2002 14:53:48 -0000 @@ -305,6 +305,19 @@ static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); + +#if BX_W83759A_VLBIDE_SUPPORT + +#if !BX_USE_HD_SMF + Bit32u w83759a_read(Bit32u address, unsigned io_len); + void w83759a_write(Bit32u address, Bit32u value, unsigned io_len); +#endif + + static Bit32u w83759a_read_handler(void *this_ptr, Bit32u address, unsigned io_len); + static void w83759a_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); + +#endif + private: BX_HD_SMF Boolean calculate_logical_address(Bit8u channel, off_t *sector); @@ -356,6 +369,36 @@ Bit32u p1f3_value; Bit32u p1f4_value; } pdc20230c; +#endif + +#if BX_W83759A_VLBIDE_SUPPORT + +// From specs, configuration registers can be at 0x1bX or 0x13X +// Specs p11 are totally wrong. I guess registers can be : +// Y0BX with Y in 1 5 9 D and X in 0 4 8 C +// or Y03X with Y in 1 5 9 D and X in 0 4 8 C +#define BX_W83759A_IDIN 0x10b0 +#define BX_W83759A_INDEX 0x10b4 +#define BX_W83759A_DATA 0x10b8 +#define BX_W83759A_IDOUT 0x10bc + +#if 0 +#define BX_W83759A_IDIN 0x1030 +#define BX_W83759A_INDEX 0x1034 +#define BX_W83759A_DATA 0x1038 +#define BX_W83759A_IDOUT 0x103c +#endif + +#define BX_W83759A_ID 0x00 + +// Only one w83759A chip can be present. +// Well there is a multichip mode, but all on same io port + struct w83759a_t { + Boolean prog_mode; + Bit8u index; + Bit8u registers[0x10]; + Boolean detected; + } w83759a; #endif bx_devices_c *devices;