1346 lines
46 KiB
Plaintext
1346 lines
46 KiB
Plaintext
----------------------------------------------------------------------
|
|
Patch name: patch.usb-fys
|
|
Author: Ben Lunt, updated by cbothamy and vruppert
|
|
Date: Wed Jan 22 19:26:40 CET 2003
|
|
Status: applied to main code
|
|
|
|
Detailed description:
|
|
|
|
Comment from the author:
|
|
|
|
Attached is a "patch" file detailing what you need to do
|
|
to add USB support (UHCI only for now) to your existing
|
|
Bochs (2.0.xx) source code.
|
|
|
|
I use Win32 and VC++ but the source and modifications
|
|
should be platform and compiler independant.
|
|
|
|
Please let me know if this patch some how breaks the
|
|
build process of your compilation (Bochs 2.0.0 or above
|
|
only).
|
|
|
|
I would also like any feedback on how this code works
|
|
(or doesn't work) on your platform and within your
|
|
images. If you explain in as much detail as you can on
|
|
how it did or did not work, I will try to add to the source
|
|
to help it work on all platforms and images.
|
|
|
|
Patch was created with:
|
|
diff -u
|
|
Apply patch to what version:
|
|
cvs checked out on Thu Jan 23 21:00:00 CET 2003
|
|
Instructions:
|
|
To patch, go to main bochs directory.
|
|
Type "patch -p0 < THIS_PATCH_FILE".
|
|
----------------------------------------------------------------------
|
|
diff -urN ../bochs/bochs.h ./bochs.h
|
|
--- ../bochs/bochs.h 2003-01-11 09:28:36.000000000 +0100
|
|
+++ ./bochs.h 2003-01-22 23:38:03.000000000 +0100
|
|
@@ -298,7 +298,7 @@
|
|
CPU2LOG, CPU3LOG, CPU4LOG, CPU5LOG, CPU6LOG, CPU7LOG, CPU8LOG, CPU9LOG,
|
|
CPU10LOG, CPU11LOG, CPU12LOG, CPU13LOG, CPU14LOG, CPU15LOG, CTRLLOG,
|
|
UNMAPLOG, SERRLOG, BIOSLOG, PIT81LOG, PIT82LOG, IODEBUGLOG, PCI2ISALOG,
|
|
- PLUGINLOG, EXTFPUIRQLOG , PCIVGALOG
|
|
+ PLUGINLOG, EXTFPUIRQLOG , PCIVGALOG, PCIUSBLOG
|
|
};
|
|
|
|
class BOCHSAPI iofunctions {
|
|
@@ -628,6 +628,7 @@
|
|
#define BX_N_OPTROM_IMAGES 4
|
|
#define BX_N_SERIAL_PORTS 1
|
|
#define BX_N_PARALLEL_PORTS 1
|
|
+#define BX_N_USB_HUBS 1
|
|
|
|
typedef struct BOCHSAPI {
|
|
bx_floppy_options floppya;
|
|
@@ -638,6 +639,7 @@
|
|
// bx_disk_options diskd;
|
|
// bx_cdrom_options cdromd;
|
|
bx_serial_options com[BX_N_SERIAL_PORTS];
|
|
+ bx_usb_options usb[BX_N_USB_HUBS];
|
|
bx_rom_options rom;
|
|
bx_vgarom_options vgarom;
|
|
bx_rom_options optrom[BX_N_OPTROM_IMAGES]; // Optional rom images
|
|
diff -urN ../bochs/config.h.in ./config.h.in
|
|
--- ../bochs/config.h.in 2003-01-23 20:31:57.000000000 +0100
|
|
+++ ./config.h.in 2003-01-22 23:49:54.000000000 +0100
|
|
@@ -242,6 +242,7 @@
|
|
#define BX_USE_PCI_SMF 1 // PCI
|
|
#define BX_USE_P2I_SMF 1 // PCI-to-ISA bridge
|
|
#define BX_USE_PCIVGA_SMF 1 // PCI-VGA
|
|
+#define BX_USE_PCIUSB_SMF 1 // USB hub
|
|
#define BX_USE_NE2K_SMF 1 // NE2K
|
|
#define BX_USE_EFI_SMF 1 // External FPU IRQ
|
|
|
|
@@ -254,7 +255,7 @@
|
|
|| !BX_USE_PAR_SMF || !BX_USE_PIC_SMF || !BX_USE_PIT_SMF \
|
|
|| !BX_USE_SER_SMF || !BX_USE_UM_SMF || !BX_USE_VGA_SMF \
|
|
|| !BX_USE_SB16_SMF || !BX_USE_DEV_SMF || !BX_USE_PCI_SMF \
|
|
- || !BX_USE_P2I_SMF || !BX_USE_PCIVGA_SMF \
|
|
+ || !BX_USE_P2I_SMF || !BX_USE_PCIVGA_SMF || !BX_USE_PCIUSB_SMF \
|
|
|| !BX_USE_NE2K_SMF || !BX_USE_EFI_SMF)
|
|
#error You must use SMF to have plugins
|
|
#endif
|
|
@@ -674,6 +675,13 @@
|
|
// Experimental VGA on PCI
|
|
#define BX_PCI_VGA_SUPPORT 1
|
|
|
|
+// limited USB on PCI
|
|
+#define BX_PCI_USB_SUPPORT 0
|
|
+
|
|
+#if (BX_PCI_USB_SUPPORT && !BX_PCI_SUPPORT)
|
|
+#error To enable USB, you must also enable PCI
|
|
+#endif
|
|
+
|
|
// Promise VLBIDE DC2300 Support
|
|
#define BX_PDC20230C_VLBIDE_SUPPORT 0
|
|
|
|
diff -urN ../bochs/configure ./configure
|
|
--- ../bochs/configure 2003-01-20 21:32:42.000000000 +0100
|
|
+++ ./configure 2003-01-23 00:10:46.000000000 +0100
|
|
@@ -1017,6 +1017,7 @@
|
|
--enable-split-hd allows split hard disk image
|
|
--enable-ne2000 enable limited ne2000 support
|
|
--enable-pci enable limited i440FX PCI support
|
|
+ --enable-usb enable limited USB support
|
|
--enable-dc2300-vlb-ide enable Promise DC2300 VLB-IDE support
|
|
--enable-4meg-pages support 4Megabyte pages extensions
|
|
--enable-pae support Physical Address Extensions
|
|
@@ -4208,7 +4209,7 @@
|
|
case $host in
|
|
*-*-irix6*)
|
|
# Find out which ABI we are using.
|
|
- echo '#line 4211 "configure"' > conftest.$ac_ext
|
|
+ echo '#line 4212 "configure"' > conftest.$ac_ext
|
|
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
|
(eval $ac_compile) 2>&5
|
|
ac_status=$?
|
|
@@ -4758,7 +4759,7 @@
|
|
save_CFLAGS="$CFLAGS"
|
|
CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
|
|
compiler_c_o=no
|
|
-if { (eval echo configure:4761: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
|
|
+if { (eval echo configure:4762: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
|
|
# The compiler can only warn and ignore the option if not recognized
|
|
# So say no if there are warnings
|
|
if test -s out/conftest.err; then
|
|
@@ -6589,7 +6590,7 @@
|
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
|
lt_status=$lt_dlunknown
|
|
cat > conftest.$ac_ext <<EOF
|
|
-#line 6592 "configure"
|
|
+#line 6593 "configure"
|
|
#include "confdefs.h"
|
|
|
|
#if HAVE_DLFCN_H
|
|
@@ -6687,7 +6688,7 @@
|
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
|
lt_status=$lt_dlunknown
|
|
cat > conftest.$ac_ext <<EOF
|
|
-#line 6690 "configure"
|
|
+#line 6691 "configure"
|
|
#include "confdefs.h"
|
|
|
|
#if HAVE_DLFCN_H
|
|
@@ -8729,7 +8730,7 @@
|
|
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
|
lt_status=$lt_dlunknown
|
|
cat > conftest.$ac_ext <<EOF
|
|
-#line 8732 "configure"
|
|
+#line 8733 "configure"
|
|
#include "confdefs.h"
|
|
|
|
#if HAVE_DLFCN_H
|
|
@@ -19467,6 +19468,39 @@
|
|
fi;
|
|
|
|
|
|
+echo "$as_me:$LINENO: checking for limited USB support" >&5
|
|
+echo $ECHO_N "checking for limited USB support... $ECHO_C" >&6
|
|
+# Check whether --enable-usb or --disable-usb was given.
|
|
+if test "${enable_usb+set}" = set; then
|
|
+ enableval="$enable_usb"
|
|
+ if test "$enableval" = yes; then
|
|
+ echo "$as_me:$LINENO: result: yes" >&5
|
|
+echo "${ECHO_T}yes" >&6
|
|
+ cat >>confdefs.h <<\_ACEOF
|
|
+#define BX_PCI_USB_SUPPORT 1
|
|
+_ACEOF
|
|
+
|
|
+ PCI_OBJ="$PCI_OBJ pciusb.o"
|
|
+ else
|
|
+ echo "$as_me:$LINENO: result: no" >&5
|
|
+echo "${ECHO_T}no" >&6
|
|
+ cat >>confdefs.h <<\_ACEOF
|
|
+#define BX_PCI_USB_SUPPORT 0
|
|
+_ACEOF
|
|
+
|
|
+ fi
|
|
+else
|
|
+
|
|
+ echo "$as_me:$LINENO: result: no" >&5
|
|
+echo "${ECHO_T}no" >&6
|
|
+ cat >>confdefs.h <<\_ACEOF
|
|
+#define BX_PCI_USB_SUPPORT 0
|
|
+_ACEOF
|
|
+
|
|
+
|
|
+
|
|
+fi;
|
|
+
|
|
echo "$as_me:$LINENO: checking for Promise DC2300 VLB-IDE support" >&5
|
|
echo $ECHO_N "checking for Promise DC2300 VLB-IDE support... $ECHO_C" >&6
|
|
# Check whether --enable-dc2300-vlb-ide or --disable-dc2300-vlb-ide was given.
|
|
diff -urN ../bochs/configure.in ./configure.in
|
|
--- ../bochs/configure.in 2003-01-20 21:32:42.000000000 +0100
|
|
+++ ./configure.in 2003-01-23 00:11:00.000000000 +0100
|
|
@@ -772,6 +772,23 @@
|
|
)
|
|
AC_SUBST(PCI_OBJ)
|
|
|
|
+AC_MSG_CHECKING(for limited USB support)
|
|
+AC_ARG_ENABLE(usb,
|
|
+ [ --enable-usb enable limited USB support],
|
|
+ [if test "$enableval" = yes; then
|
|
+ AC_MSG_RESULT(yes)
|
|
+ AC_DEFINE(BX_PCI_USB_SUPPORT, 1)
|
|
+ PCI_OBJ="$PCI_OBJ pciusb.o"
|
|
+ else
|
|
+ AC_MSG_RESULT(no)
|
|
+ AC_DEFINE(BX_PCI_USB_SUPPORT, 0)
|
|
+ fi],
|
|
+ [
|
|
+ AC_MSG_RESULT(no)
|
|
+ AC_DEFINE(BX_PCI_USB_SUPPORT, 0)
|
|
+ ]
|
|
+ )
|
|
+
|
|
AC_MSG_CHECKING(for Promise DC2300 VLB-IDE support)
|
|
AC_ARG_ENABLE(dc2300-vlb-ide,
|
|
[ --enable-dc2300-vlb-ide enable Promise DC2300 VLB-IDE support],
|
|
diff -urN ../bochs/gui/siminterface.h ./gui/siminterface.h
|
|
--- ../bochs/gui/siminterface.h 2002-12-17 16:53:29.000000000 +0100
|
|
+++ ./gui/siminterface.h 2003-01-25 13:27:18.000000000 +0100
|
|
@@ -272,6 +272,10 @@
|
|
BXP_COM3_PATH,
|
|
BXP_COM4_ENABLED,
|
|
BXP_COM4_PATH,
|
|
+#define BXP_PARAMS_PER_USB_HUB 3
|
|
+ BXP_USB1_ENABLED,
|
|
+ BXP_USB1_IOADDR,
|
|
+ BXP_USB1_IRQ,
|
|
BXP_PRIVATE_COLORMAP,
|
|
BXP_FULLSCREEN,
|
|
BXP_SCREENMODE,
|
|
@@ -413,6 +417,15 @@
|
|
(bx_id)(BXP_COM1_ENABLED + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))
|
|
#define BXP_COMx_PATH(x) \
|
|
(bx_id)(BXP_COM1_PATH + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))
|
|
+
|
|
+// use x=1
|
|
+#define BXP_USBx_ENABLED(x) \
|
|
+ (bx_id)(BXP_USB1_ENABLED + (((x)-1)*BXP_PARAMS_PER_USB_HUB))
|
|
+#define BXP_USBx_IOADDR(x) \
|
|
+ (bx_id)(BXP_USB1_IOADDR + (((x)-1)*BXP_PARAMS_PER_USB_HUB))
|
|
+#define BXP_USBx_IRQ(x) \
|
|
+ (bx_id)(BXP_USB1_IRQ + (((x)-1)*BXP_PARAMS_PER_USB_HUB))
|
|
+
|
|
// use x=1,2
|
|
#define BXP_PARPORTx_ENABLED(x) \
|
|
(bx_id)(BXP_PARPORT1_ENABLED + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT))
|
|
@@ -1148,6 +1161,12 @@
|
|
bx_param_string_c *Odev;
|
|
} bx_serial_options;
|
|
|
|
+typedef struct {
|
|
+ bx_param_bool_c *Oenabled;
|
|
+ bx_param_num_c *Oioaddr;
|
|
+ bx_param_num_c *Oirq;
|
|
+ } bx_usb_options;
|
|
+
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// base class simulator interface, contains just virtual functions.
|
|
diff -urN ../bochs/iodev/devices.cc ./iodev/devices.cc
|
|
--- ../bochs/iodev/devices.cc 2003-01-11 09:28:52.000000000 +0100
|
|
+++ ./iodev/devices.cc 2003-01-23 00:00:09.000000000 +0100
|
|
@@ -54,6 +54,9 @@
|
|
#if BX_PCI_VGA_SUPPORT
|
|
pluginPciVgaAdapter = NULL;
|
|
#endif
|
|
+#if BX_PCI_USB_SUPPORT
|
|
+ pluginPciUSBAdapter = NULL;
|
|
+#endif
|
|
#endif
|
|
pit = NULL;
|
|
pluginKeyboard = &stubKeyboard;
|
|
@@ -154,6 +157,9 @@
|
|
#if BX_PCI_VGA_SUPPORT
|
|
PLUG_load_plugin(pcivga, PLUGTYPE_OPTIONAL);
|
|
#endif
|
|
+#if BX_PCI_USB_SUPPORT
|
|
+ PLUG_load_plugin(pciusb, PLUGTYPE_OPTIONAL);
|
|
+#endif
|
|
#else
|
|
BX_ERROR(("Bochs is not compiled with PCI support"));
|
|
#endif
|
|
@@ -272,6 +278,9 @@
|
|
#if BX_PCI_VGA_SUPPORT
|
|
pluginPciVgaAdapter->reset(type);
|
|
#endif
|
|
+#if BX_PCI_USB_SUPPORT
|
|
+ pluginPciUSBAdapter->reset(type);
|
|
+#endif
|
|
}
|
|
#endif
|
|
#if BX_SUPPORT_IOAPIC
|
|
@@ -636,6 +645,15 @@
|
|
return false;
|
|
}
|
|
|
|
+bx_bool bx_devices_c::is_usb_enabled ()
|
|
+{
|
|
+ for (int i=0; i<BX_N_USB_HUBS; i++) {
|
|
+ if (SIM->get_param_bool (BXP_USBx_ENABLED(i+1))->get())
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+}
|
|
+
|
|
bx_bool bx_devices_c::is_parallel_enabled ()
|
|
{
|
|
for (int i=0; i<BX_N_PARALLEL_PORTS; i++) {
|
|
diff -urN ../bochs/iodev/iodev.h ./iodev/iodev.h
|
|
--- ../bochs/iodev/iodev.h 2003-01-11 09:28:52.000000000 +0100
|
|
+++ ./iodev/iodev.h 2003-01-23 00:00:46.000000000 +0100
|
|
@@ -298,6 +298,7 @@
|
|
bx_pci_stub_c *pluginPciBridge;
|
|
bx_devmodel_c *pluginPci2IsaBridge;
|
|
bx_devmodel_c *pluginPciVgaAdapter;
|
|
+ bx_devmodel_c *pluginPciUSBAdapter;
|
|
bx_pit_c *pit;
|
|
bx_keyb_stub_c *pluginKeyboard;
|
|
bx_dma_stub_c *pluginDmaDevice;
|
|
@@ -371,6 +372,7 @@
|
|
|
|
int timer_handle;
|
|
bx_bool is_serial_enabled ();
|
|
+ bx_bool is_usb_enabled ();
|
|
bx_bool is_parallel_enabled ();
|
|
};
|
|
|
|
@@ -382,6 +384,9 @@
|
|
#if BX_PCI_VGA_SUPPORT
|
|
#include "iodev/pcivga.h"
|
|
#endif
|
|
+#if BX_PCI_USB_SUPPORT
|
|
+#include "iodev/pciusb.h"
|
|
+#endif
|
|
#endif
|
|
#include "iodev/vga.h"
|
|
#if BX_SUPPORT_APIC
|
|
diff -urN ../bochs/iodev/pciusb.cc ./iodev/pciusb.cc
|
|
--- ../bochs/iodev/pciusb.cc 1970-01-01 01:00:00.000000000 +0100
|
|
+++ ./iodev/pciusb.cc 2003-02-06 20:09:24.000000000 +0100
|
|
@@ -0,0 +1,668 @@
|
|
+/////////////////////////////////////////////////////////////////////////
|
|
+// $Id: patch.usb-fys,v 1.5 2003-02-16 18:08:27 vruppert Exp $
|
|
+/////////////////////////////////////////////////////////////////////////
|
|
+//
|
|
+// Copyright (C) 2003 MandrakeSoft S.A.
|
|
+//
|
|
+// MandrakeSoft S.A.
|
|
+// 43, rue d'Aboukir
|
|
+// 75002 Paris - France
|
|
+// http://www.linux-mandrake.com/
|
|
+// http://www.mandrakesoft.com/
|
|
+//
|
|
+// This library is free software; you can redistribute it and/or
|
|
+// modify it under the terms of the GNU Lesser General Public
|
|
+// License as published by the Free Software Foundation; either
|
|
+// version 2 of the License, or (at your option) any later version.
|
|
+//
|
|
+// This library is distributed in the hope that it will be useful,
|
|
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+// Lesser General Public License for more details.
|
|
+//
|
|
+// You should have received a copy of the GNU Lesser General Public
|
|
+// License along with this library; if not, write to the Free Software
|
|
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+
|
|
+//
|
|
+// Experimental PCI USB adapter
|
|
+// Benjamin D Lunt (fys@cybertrails.com) coded most of this usb emulation.
|
|
+// I hope to add to this code to make it more functionable.
|
|
+//
|
|
+
|
|
+// Define BX_PLUGGABLE in files that can be compiled into plugins. For
|
|
+// platforms that require a special tag on exported symbols, BX_PLUGGABLE
|
|
+// is used to know when we are exporting symbols and when we are importing.
|
|
+#define BX_PLUGGABLE
|
|
+
|
|
+#include "bochs.h"
|
|
+#if BX_PCI_SUPPORT && BX_PCI_USB_SUPPORT
|
|
+
|
|
+#define LOG_THIS theUSBDevice->
|
|
+
|
|
+bx_pciusb_c* theUSBDevice = NULL;
|
|
+
|
|
+ int
|
|
+libpciusb_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
|
|
+{
|
|
+ theUSBDevice = new bx_pciusb_c ();
|
|
+ bx_devices.pluginPciUSBAdapter = theUSBDevice;
|
|
+ BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUSBDevice, BX_PLUGIN_PCIUSB);
|
|
+ return 0; // Success
|
|
+}
|
|
+
|
|
+ void
|
|
+libpciusb_LTX_plugin_fini(void)
|
|
+{
|
|
+}
|
|
+
|
|
+
|
|
+bx_pciusb_c::bx_pciusb_c(void)
|
|
+{
|
|
+ put("USB");
|
|
+ settype(PCIUSBLOG);
|
|
+}
|
|
+
|
|
+bx_pciusb_c::~bx_pciusb_c(void)
|
|
+{
|
|
+ // nothing for now
|
|
+ BX_DEBUG(("Exit."));
|
|
+}
|
|
+
|
|
+
|
|
+ void
|
|
+bx_pciusb_c::init(void)
|
|
+{
|
|
+ // called once when bochs initializes
|
|
+
|
|
+ if (!bx_options.usb[0].Oenabled->get()) return;
|
|
+
|
|
+ Bit16u base_ioaddr = bx_options.usb[0].Oioaddr->get();
|
|
+ Bit8u irq = bx_options.usb[0].Oirq->get();
|
|
+
|
|
+ DEV_register_irq(irq, "USB Hub #1");
|
|
+ BX_USB_THIS hub[0].irq = irq;
|
|
+
|
|
+ // Call our timer routine every 1mS (1,000uS)
|
|
+ // Continuous and active
|
|
+ BX_USB_THIS hub[0].timer_index =
|
|
+ bx_pc_system.register_timer(this, usb_timer_handler, 1000, 1,1, "usb.timer");
|
|
+
|
|
+ for (unsigned addr=base_ioaddr; addr<(unsigned)(base_ioaddr+0x14); addr++) {
|
|
+ BX_DEBUG(("register read/write: 0x%04x", addr));
|
|
+ DEV_register_ioread_handler(this, read_handler, addr, "USB Hub #1", 7);
|
|
+ DEV_register_iowrite_handler(this, write_handler, addr, "USB Hub #1", 7);
|
|
+ }
|
|
+ BX_USB_THIS hub[0].base_ioaddr = base_ioaddr;
|
|
+
|
|
+ DEV_register_pci_handlers(this,
|
|
+ pci_read_handler,
|
|
+ pci_write_handler,
|
|
+ BX_PCI_DEVICE(1,2),
|
|
+ "Experimental PCI USB");
|
|
+
|
|
+ for (unsigned i=0; i<256; i++) {
|
|
+ BX_USB_THIS hub[0].pci_conf[i] = 0x0;
|
|
+ }
|
|
+
|
|
+ BX_INFO(("usb1 at 0x%04x-0x%04x irq %d", base_ioaddr, base_ioaddr+0x13, irq));
|
|
+}
|
|
+
|
|
+ void
|
|
+bx_pciusb_c::reset(unsigned type)
|
|
+{
|
|
+ unsigned i;
|
|
+
|
|
+ static const struct reset_vals_t {
|
|
+ unsigned addr;
|
|
+ unsigned char val;
|
|
+ } reset_vals[] = {
|
|
+ { 0x00, 0x86 }, { 0x01, 0x80 }, // 0x8086 = vendor
|
|
+ { 0x02, 0x20 }, { 0x03, 0x70 }, // 0x7020 = device
|
|
+ { 0x04, 0x05 }, { 0x05, 0x00 }, // command_io
|
|
+ { 0x06, 0x80 }, { 0x07, 0x02 }, // status
|
|
+ { 0x08, 0x01 }, // revision number
|
|
+ { 0x09, 0x00 }, // interface
|
|
+ { 0x0a, 0x03 }, // class_sub USB Host Controller
|
|
+ { 0x0b, 0x0c }, // class_base Serial Bus Controller
|
|
+ { 0x0D, 0x20 }, // bus latency
|
|
+ { 0x0e, 0x00 }, // header_type_generic
|
|
+ // address space 0x20 - 0x23
|
|
+ { 0x20, ((bx_options.usb[0].Oioaddr->get() & 0xE0) | 0x01) },
|
|
+ { 0x21, (bx_options.usb[0].Oioaddr->get() >> 8) },
|
|
+ { 0x22, 0x00 }, { 0x23, 0x00 },
|
|
+ { 0x3c, bx_options.usb[0].Oirq->get() }, // IRQ
|
|
+ { 0x3d, 0x04 }, // INT
|
|
+ { 0x6a, 0x01 }, // USB clock
|
|
+ { 0xc1, 0x20 } // PIRQ enable
|
|
+
|
|
+ };
|
|
+ for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) {
|
|
+ BX_USB_THIS hub[0].pci_conf[reset_vals[i].addr] = reset_vals[i].val;
|
|
+ }
|
|
+
|
|
+ // reset locals
|
|
+ BX_USB_THIS global_reset = 0;
|
|
+
|
|
+ // Put the USB registers into their RESET state
|
|
+ for (i=0; i<BX_USB_CONFDEV; i++) {
|
|
+ BX_USB_THIS hub[i].usb_command.max_packet_size = 0;
|
|
+ BX_USB_THIS hub[i].usb_command.configured = 0;
|
|
+ BX_USB_THIS hub[i].usb_command.debug = 0;
|
|
+ BX_USB_THIS hub[i].usb_command.resume = 0;
|
|
+ BX_USB_THIS hub[i].usb_command.suspend = 1;
|
|
+ BX_USB_THIS hub[i].usb_command.host_reset = 0;
|
|
+ BX_USB_THIS hub[i].usb_command.reset = 0;
|
|
+ BX_USB_THIS hub[i].usb_command.schedule = 0;
|
|
+ BX_USB_THIS hub[i].usb_status.error_interrupt = 0;
|
|
+ BX_USB_THIS hub[i].usb_status.host_error = 0;
|
|
+ BX_USB_THIS hub[i].usb_status.host_halted = 0;
|
|
+ BX_USB_THIS hub[i].usb_status.interrupt = 0;
|
|
+ BX_USB_THIS hub[i].usb_status.pci_error = 0;
|
|
+ BX_USB_THIS hub[i].usb_status.resume = 0;
|
|
+ BX_USB_THIS hub[i].usb_enable.short_packet = 0;
|
|
+ BX_USB_THIS hub[i].usb_enable.on_complete = 0;
|
|
+ BX_USB_THIS hub[i].usb_enable.resume = 0;
|
|
+ BX_USB_THIS hub[i].usb_enable.timeout_crc = 0;
|
|
+ BX_USB_THIS hub[i].usb_frame_num.frame_num = 0x0000;
|
|
+ BX_USB_THIS hub[i].usb_frame_base.frame_base = 0x00000000;
|
|
+ BX_USB_THIS hub[i].usb_sof.sof_timing = 0x40;
|
|
+ for (unsigned j=0; j<USB_NUM_PORTS; j++) {
|
|
+ BX_USB_THIS hub[i].usb_port[j].connect_changed = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].line_dminus = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].line_dplus = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].low_speed = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].reset = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].resume = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].suspend = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].enabled = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].able_changed = 0;
|
|
+ BX_USB_THIS hub[i].usb_port[j].status = 0;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+ // static IO port read callback handler
|
|
+ // redirects to non-static class handler to avoid virtual functions
|
|
+
|
|
+ Bit32u
|
|
+bx_pciusb_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
|
|
+{
|
|
+#if !BX_USE_PCIUSB_SMF
|
|
+ bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
|
|
+
|
|
+ return( class_ptr->read(address, io_len) );
|
|
+}
|
|
+
|
|
+
|
|
+ Bit32u
|
|
+bx_pciusb_c::read(Bit32u address, unsigned io_len)
|
|
+{
|
|
+#else
|
|
+ UNUSED(this_ptr);
|
|
+#endif // !BX_USE_PCIUSB_SMF
|
|
+ Bit32u val = 0x0;
|
|
+ Bit8u offset,port;
|
|
+
|
|
+ BX_DEBUG(("register read from address 0x%04x - ", (unsigned) address));
|
|
+
|
|
+ offset = address - BX_USB_THIS hub[0].base_ioaddr;
|
|
+
|
|
+ switch (offset) {
|
|
+ case 0x0C: // Start of Frame Modify
|
|
+ case 0x11: // port0 (high byte read)
|
|
+ case 0x13: // port1 (high byte read)
|
|
+ if (io_len != 1)
|
|
+ BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
|
|
+ break;
|
|
+ case 0x10: // port0
|
|
+ case 0x12: // port1
|
|
+ if ((io_len < 1) || (io_len > 2))
|
|
+ BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
|
|
+ break;
|
|
+ case 0x00: // command register (16-bit)
|
|
+ case 0x02: // status register (16-bit)
|
|
+ case 0x04: // interrupt enable register (1-bit)
|
|
+ case 0x06: // frame number register (16-bit)
|
|
+ if (io_len != 2)
|
|
+ BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
|
|
+ break;
|
|
+ case 0x08: // frame base register (32-bit)
|
|
+ if (io_len != 4)
|
|
+ BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (offset) {
|
|
+ case 0x00: // command register (16-bit)
|
|
+ val = BX_USB_THIS hub[0].usb_command.max_packet_size << 7
|
|
+ | BX_USB_THIS hub[0].usb_command.configured << 6
|
|
+ | BX_USB_THIS hub[0].usb_command.debug << 5
|
|
+ | BX_USB_THIS hub[0].usb_command.resume << 4
|
|
+ | BX_USB_THIS hub[0].usb_command.suspend << 3
|
|
+ | BX_USB_THIS hub[0].usb_command.reset << 2
|
|
+ | BX_USB_THIS hub[0].usb_command.host_reset << 1
|
|
+ | BX_USB_THIS hub[0].usb_command.schedule;
|
|
+ break;
|
|
+
|
|
+ case 0x02: // status register (16-bit)
|
|
+ val = BX_USB_THIS hub[0].usb_status.host_halted << 5
|
|
+ | BX_USB_THIS hub[0].usb_status.host_error << 4
|
|
+ | BX_USB_THIS hub[0].usb_status.pci_error << 3
|
|
+ | BX_USB_THIS hub[0].usb_status.resume << 2
|
|
+ | BX_USB_THIS hub[0].usb_status.error_interrupt << 1
|
|
+ | BX_USB_THIS hub[0].usb_status.interrupt;
|
|
+ break;
|
|
+
|
|
+ case 0x04: // interrupt enable register (16-bit)
|
|
+ val = BX_USB_THIS hub[0].usb_enable.short_packet << 3
|
|
+ | BX_USB_THIS hub[0].usb_enable.on_complete << 2
|
|
+ | BX_USB_THIS hub[0].usb_enable.resume << 1
|
|
+ | BX_USB_THIS hub[0].usb_enable.timeout_crc;
|
|
+ break;
|
|
+
|
|
+ case 0x06: // frame number register (16-bit)
|
|
+ val = BX_USB_THIS hub[0].usb_frame_num.frame_num;
|
|
+ break;
|
|
+
|
|
+ case 0x08: // frame base register (32-bit)
|
|
+ val = BX_USB_THIS hub[0].usb_frame_base.frame_base;
|
|
+ break;
|
|
+
|
|
+ case 0x0C: // start of Frame Modify register (8-bit)
|
|
+ val = BX_USB_THIS hub[0].usb_sof.sof_timing;
|
|
+ break;
|
|
+
|
|
+ case 0x10: // port0
|
|
+ case 0x12: // port1
|
|
+ port = (offset & 0x0F) >> 1;
|
|
+ if (port < USB_NUM_PORTS) {
|
|
+ val = BX_USB_THIS hub[0].usb_port[port].suspend << 12
|
|
+ | BX_USB_THIS hub[0].usb_port[port].reset << 9
|
|
+ | BX_USB_THIS hub[0].usb_port[port].low_speed << 8
|
|
+ | 1 << 7
|
|
+ | BX_USB_THIS hub[0].usb_port[port].resume << 6
|
|
+ | BX_USB_THIS hub[0].usb_port[port].line_dplus << 5
|
|
+ | BX_USB_THIS hub[0].usb_port[port].line_dminus << 4
|
|
+ | BX_USB_THIS hub[0].usb_port[port].able_changed << 3
|
|
+ | BX_USB_THIS hub[0].usb_port[port].enabled << 2
|
|
+ | BX_USB_THIS hub[0].usb_port[port].connect_changed << 1
|
|
+ | BX_USB_THIS hub[0].usb_port[port].status;
|
|
+ break;
|
|
+ } // else fall through to default
|
|
+
|
|
+ default:
|
|
+ val = 0; // keep compiler happy
|
|
+ BX_PANIC(("unsupported io read from address=0x%04x!", (unsigned) address));
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ BX_DEBUG(("val = 0x%08x", (Bit32u) val));
|
|
+
|
|
+ return(val);
|
|
+}
|
|
+
|
|
+
|
|
+ // static IO port write callback handler
|
|
+ // redirects to non-static class handler to avoid virtual functions
|
|
+
|
|
+ void
|
|
+bx_pciusb_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
|
|
+{
|
|
+#if !BX_USE_PCIUSB_SMF
|
|
+ bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
|
|
+
|
|
+ class_ptr->write(address, value, io_len);
|
|
+}
|
|
+
|
|
+ void
|
|
+bx_pciusb_c::write(Bit32u address, Bit32u value, unsigned io_len)
|
|
+{
|
|
+#else
|
|
+ UNUSED(this_ptr);
|
|
+#endif // !BX_USE_PCIUSB_SMF
|
|
+ Bit8u offset,port;
|
|
+
|
|
+ BX_DEBUG(("register write to address 0x%04x - ", (unsigned) address));
|
|
+
|
|
+ offset = address - BX_USB_THIS hub[0].base_ioaddr;
|
|
+
|
|
+ switch (offset) {
|
|
+ case 0x0C: // Start of Frame Modify
|
|
+ if (io_len != 1)
|
|
+ BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
|
|
+ break;
|
|
+ case 0x00: // command register (16-bit)
|
|
+ case 0x02: // status register (16-bit)
|
|
+ case 0x04: // interrupt enable register (1-bit)
|
|
+ case 0x06: // frame number register (16-bit)
|
|
+ case 0x10: // port0
|
|
+ case 0x12: // port1
|
|
+ if (io_len != 2)
|
|
+ BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
|
|
+ break;
|
|
+ case 0x08: // frame base register (32-bit)
|
|
+ if (io_len != 4)
|
|
+ BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ switch (offset) {
|
|
+ case 0x00: // command register (16-bit) (R/W)
|
|
+ if (value & 0xFF00)
|
|
+ BX_ERROR(("write to command register with bits 15:8 not zero: 0x%04x", value));
|
|
+
|
|
+ BX_USB_THIS hub[0].usb_command.max_packet_size = (value & 0x80) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_command.configured = (value & 0x40) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_command.debug = (value & 0x20) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_command.resume = (value & 0x10) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_command.suspend = (value & 0x08) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_command.reset = (value & 0x04) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_command.host_reset = (value & 0x02) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_command.schedule = (value & 0x01) ? 1: 0;
|
|
+
|
|
+ // If software set the reset bit, we need to set reset bit of each port for 10ms.
|
|
+ if (BX_USB_THIS hub[0].usb_command.reset)
|
|
+ BX_USB_THIS global_reset = 10;
|
|
+
|
|
+ // If host_reset then reset all registers, etc.
|
|
+ if (BX_USB_THIS hub[0].usb_command.host_reset)
|
|
+ BX_USB_THIS reset(0);
|
|
+
|
|
+ // If Run/Stop, identify in log and ignore
|
|
+ if (BX_USB_THIS hub[0].usb_command.schedule)
|
|
+ BX_INFO(("Software set Schedule bit in Command register"));
|
|
+
|
|
+ // If Debug mode set, panic. Not implemented
|
|
+ if (BX_USB_THIS hub[0].usb_command.debug)
|
|
+ BX_PANIC(("Software set DEBUG bit in Command register. Not implemented"));
|
|
+
|
|
+ break;
|
|
+
|
|
+ case 0x02: // status register (16-bit) (R/WC)
|
|
+ if (value & 0xFFC0)
|
|
+ BX_ERROR(("write to status register with bits 15:6 not zero: 0x%04x", value));
|
|
+
|
|
+ BX_USB_THIS hub[0].usb_status.host_halted = (value & 0x20) ? 0: BX_USB_THIS hub[0].usb_status.host_halted;
|
|
+ BX_USB_THIS hub[0].usb_status.host_error = (value & 0x10) ? 0: BX_USB_THIS hub[0].usb_status.host_error;
|
|
+ BX_USB_THIS hub[0].usb_status.pci_error = (value & 0x08) ? 0: BX_USB_THIS hub[0].usb_status.pci_error;
|
|
+ BX_USB_THIS hub[0].usb_status.resume = (value & 0x04) ? 0: BX_USB_THIS hub[0].usb_status.resume;
|
|
+ BX_USB_THIS hub[0].usb_status.error_interrupt = (value & 0x02) ? 0: BX_USB_THIS hub[0].usb_status.error_interrupt;
|
|
+ BX_USB_THIS hub[0].usb_status.interrupt = (value & 0x01) ? 0: BX_USB_THIS hub[0].usb_status.interrupt;
|
|
+ break;
|
|
+
|
|
+ case 0x04: // interrupt enable register (16-bit)
|
|
+ if (value & 0xFFF0)
|
|
+ BX_ERROR(("write to interrupt enable register with bits 15:4 not zero: 0x%04x", value));
|
|
+
|
|
+ BX_USB_THIS hub[0].usb_enable.short_packet = (value & 0x08) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_enable.on_complete = (value & 0x04) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_enable.resume = (value & 0x02) ? 1: 0;
|
|
+ BX_USB_THIS hub[0].usb_enable.timeout_crc = (value & 0x01) ? 1: 0;
|
|
+
|
|
+ // For now, we will just ignore these being set since we never raise the IRQ
|
|
+
|
|
+ break;
|
|
+
|
|
+ case 0x06: // frame number register (16-bit)
|
|
+ if (value & 0xF800)
|
|
+ BX_ERROR(("write to frame number register with bits 15:11 not zero: 0x%04x", value));
|
|
+
|
|
+ if (BX_USB_THIS hub[0].usb_status.host_halted)
|
|
+ BX_USB_THIS hub[0].usb_frame_num.frame_num = value;
|
|
+ else
|
|
+ // ignored by the hardward, but lets report it anyway
|
|
+ BX_ERROR(("write to frame number register with STATUS.HALTED == 0"));
|
|
+
|
|
+ break;
|
|
+
|
|
+ case 0x08: // frame base register (32-bit)
|
|
+ if (value & 0xFFF)
|
|
+ BX_PANIC(("write to frame base register with bits 11:0 not zero: 0x%08x", value));
|
|
+
|
|
+ BX_USB_THIS hub[0].usb_frame_base.frame_base = value;
|
|
+ break;
|
|
+
|
|
+ case 0x0C: // start of Frame Modify register (8-bit)
|
|
+ if (value & 0x80)
|
|
+ BX_ERROR(("write to SOF Modify register with bit 7 not zero: 0x%04x", value));
|
|
+
|
|
+ BX_USB_THIS hub[0].usb_sof.sof_timing = value;
|
|
+ break;
|
|
+
|
|
+ case 0x10: // port0
|
|
+ case 0x12: // port1
|
|
+ port = (offset & 0x0F) >> 1;
|
|
+ if (port < USB_NUM_PORTS) {
|
|
+ if (value & ((1<<5) | (1<<4) | (1<<0)))
|
|
+ BX_PANIC(("write to one or more read-only bits in port%d register: 0x%04x", port, value));
|
|
+ if (!(value & (1<<7)))
|
|
+ BX_ERROR(("write to port%d register bit 7 = 0", port));
|
|
+ if (value & (1<<8))
|
|
+ BX_INFO(("write to bit 8 in port%d register ignored", port));
|
|
+ if (value & (1<<2))
|
|
+ BX_INFO(("port%d enabled ignored. Not implemented", port));
|
|
+ if ((value & (1<<12)) && BX_USB_THIS hub[0].usb_command.suspend)
|
|
+ BX_ERROR(("write to port%d register bit 12 when in Global-Suspend", port));
|
|
+
|
|
+ BX_USB_THIS hub[0].usb_port[port].suspend = (value & (1<<12)) ? 1 : 0;
|
|
+ BX_USB_THIS hub[0].usb_port[port].reset = (value & (1<<9)) ? 1 : 0;
|
|
+ BX_USB_THIS hub[0].usb_port[port].resume = (value & (1<<6)) ? 1 : 0;
|
|
+ BX_USB_THIS hub[0].usb_port[port].able_changed = (value & (1<<3)) ? 0 : BX_USB_THIS hub[0].usb_port[0].able_changed;
|
|
+ BX_USB_THIS hub[0].usb_port[port].enabled = (value & (1<<2)) ? 1 : 0;
|
|
+ BX_USB_THIS hub[0].usb_port[port].connect_changed = (value & (1<<1)) ? 0 : BX_USB_THIS hub[0].usb_port[0].connect_changed;
|
|
+ break;
|
|
+ }
|
|
+ // else fall through to default
|
|
+
|
|
+ default:
|
|
+ BX_PANIC(("unsupported io write to address=0x%04x!", (unsigned) address));
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+void bx_pciusb_c::usb_timer_handler(void *this_ptr)
|
|
+{
|
|
+ bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
|
|
+ class_ptr->usb_timer();
|
|
+}
|
|
+
|
|
+// Called once every 1ms
|
|
+void bx_pciusb_c::usb_timer(void)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ // The Frame Number Register is incremented every 1ms ?????????
|
|
+ // Needs more work and investigation on this.
|
|
+ BX_USB_THIS hub[0].usb_frame_num.frame_num++;
|
|
+ BX_USB_THIS hub[0].usb_frame_num.frame_num &= (1024-1);
|
|
+
|
|
+ // If the "global reset" bit was set by software, we need
|
|
+ // to set the reset bit in each "active" port for 10ms
|
|
+ if (BX_USB_THIS global_reset) {
|
|
+ for (i=0; i<USB_NUM_PORTS; i++) {
|
|
+ BX_USB_THIS hub[0].usb_port[i].able_changed = 0;
|
|
+ BX_USB_THIS hub[0].usb_port[i].connect_changed = 0;
|
|
+ BX_USB_THIS hub[0].usb_port[i].enabled = 0;
|
|
+ BX_USB_THIS hub[0].usb_port[i].line_dminus = 0;
|
|
+ BX_USB_THIS hub[0].usb_port[i].line_dplus = 0;
|
|
+ BX_USB_THIS hub[0].usb_port[i].low_speed = 0;
|
|
+ BX_USB_THIS hub[0].usb_port[i].reset = 1;
|
|
+ BX_USB_THIS hub[0].usb_port[i].resume = 0;
|
|
+ BX_USB_THIS hub[0].usb_port[i].status = 0;
|
|
+ BX_USB_THIS hub[0].usb_port[i].suspend = 0;
|
|
+ }
|
|
+ BX_USB_THIS global_reset--;
|
|
+ } else {
|
|
+ for (i=0; i<USB_NUM_PORTS; i++)
|
|
+ BX_USB_THIS hub[0].usb_port[i].reset = 0;
|
|
+ }
|
|
+
|
|
+ // If command.schedule = 0, then we need to set Status.Halted
|
|
+ if (!BX_USB_THIS hub[0].usb_command.schedule)
|
|
+ BX_USB_THIS hub[0].usb_status.host_halted = 1;
|
|
+
|
|
+
|
|
+ // TODO:
|
|
+ // If ins Global_Suspend mode and any of usb_port[i] bits 6,3, or 1 are set,
|
|
+ // we need to issue a Global_Resume (set the global resume bit).
|
|
+ // However, since we don't do anything, let's not.
|
|
+
|
|
+}
|
|
+
|
|
+ // static pci configuration space read callback handler
|
|
+ // redirects to non-static class handler to avoid virtual functions
|
|
+
|
|
+ Bit32u
|
|
+bx_pciusb_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len)
|
|
+{
|
|
+#if !BX_USE_PCIUSB_SMF
|
|
+ bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
|
|
+
|
|
+ return class_ptr->pci_read(address, io_len);
|
|
+}
|
|
+
|
|
+
|
|
+ Bit32u
|
|
+bx_pciusb_c::pci_read(Bit8u address, unsigned io_len)
|
|
+{
|
|
+#else
|
|
+ UNUSED(this_ptr);
|
|
+#endif // !BX_USE_PCIUSB_SMF
|
|
+
|
|
+ Bit32u value = 0;
|
|
+
|
|
+ if (io_len > 4 || io_len == 0) {
|
|
+ BX_ERROR(("Experimental USB PCI read register 0x%02x, len=%u !",
|
|
+ (unsigned) address, (unsigned) io_len));
|
|
+ return 0xffffffff;
|
|
+ }
|
|
+
|
|
+ const char* pszName = " ";
|
|
+ switch (address) {
|
|
+ case 0x00: if (io_len == 2) {
|
|
+ pszName = "(vendor id) ";
|
|
+ } else if (io_len == 4) {
|
|
+ pszName = "(vendor + device) ";
|
|
+ }
|
|
+ break;
|
|
+ case 0x04: if (io_len == 2) {
|
|
+ pszName = "(command) ";
|
|
+ } else if (io_len == 4) {
|
|
+ pszName = "(command+status) ";
|
|
+ }
|
|
+ break;
|
|
+ case 0x08: if (io_len == 1) {
|
|
+ pszName = "(revision id) ";
|
|
+ } else if (io_len == 4) {
|
|
+ pszName = "(rev.+class code) ";
|
|
+ }
|
|
+ break;
|
|
+ case 0x0c: pszName = "(cache line size) "; break;
|
|
+ case 0x20: pszName = "(base address) "; break;
|
|
+ case 0x28: pszName = "(cardbus cis) "; break;
|
|
+ case 0x2c: pszName = "(subsys. vendor+) "; break;
|
|
+ case 0x30: pszName = "(rom base) "; break;
|
|
+ case 0x3c: pszName = "(interrupt line+) "; break;
|
|
+ case 0x3d: pszName = "(interrupt pin) "; break;
|
|
+ }
|
|
+
|
|
+ // This odd code is to display only what bytes actually were read.
|
|
+ char szTmp[9];
|
|
+ char szTmp2[3];
|
|
+ szTmp[0] = '\0';
|
|
+ szTmp2[0] = '\0';
|
|
+ for (unsigned i=0; i<io_len; i++) {
|
|
+ value |= (BX_USB_THIS hub[0].pci_conf[address+i] << (i*8));
|
|
+ sprintf(szTmp2, "%02x", (BX_USB_THIS hub[0].pci_conf[address+i]));
|
|
+ strrev(szTmp2);
|
|
+ strcat(szTmp, szTmp2);
|
|
+ }
|
|
+ strrev(szTmp);
|
|
+ BX_DEBUG(("Experimental USB PCI read register 0x%02x %svalue 0x%s",
|
|
+ address, pszName, szTmp));
|
|
+ return value;
|
|
+}
|
|
+
|
|
+
|
|
+ // static pci configuration space write callback handler
|
|
+ // redirects to non-static class handler to avoid virtual functions
|
|
+
|
|
+ void
|
|
+bx_pciusb_c::pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len)
|
|
+{
|
|
+#if !BX_USE_PCIUSB_SMF
|
|
+ bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
|
|
+
|
|
+ class_ptr->pci_write(address, value, io_len);
|
|
+}
|
|
+
|
|
+ void
|
|
+bx_pciusb_c::pci_write(Bit8u address, Bit32u value, unsigned io_len)
|
|
+{
|
|
+#else
|
|
+ UNUSED(this_ptr);
|
|
+#endif // !BX_USE_PCIUSB_SMF
|
|
+
|
|
+ if (io_len > 4 || io_len == 0) {
|
|
+ BX_ERROR(("Experimental USB PCI write register 0x%02x, len=%u !",
|
|
+ (unsigned) address, (unsigned) io_len));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // This odd code is to display only what bytes actually were written.
|
|
+ char szTmp[9];
|
|
+ char szTmp2[3];
|
|
+ szTmp[0] = '\0';
|
|
+ szTmp2[0] = '\0';
|
|
+ for (unsigned i=0; i<io_len; i++) {
|
|
+ const Bit8u value8 = (value >> (i*8)) & 0xFF;
|
|
+ switch (address+i) {
|
|
+ case 0x20: // Base address
|
|
+ BX_USB_THIS hub[0].pci_conf[address+i] = (value8 & 0xe0) | 0x01;
|
|
+ sprintf(szTmp2, "%02x", (value8 & 0xe0) | 0x01);
|
|
+ break;
|
|
+ case 0x10: // Reserved
|
|
+ case 0x11: //
|
|
+ case 0x12: //
|
|
+ case 0x13: //
|
|
+ case 0x14: //
|
|
+ case 0x15: //
|
|
+ case 0x16: //
|
|
+ case 0x17: //
|
|
+ case 0x18: //
|
|
+ case 0x19: //
|
|
+ case 0x1a: //
|
|
+ case 0x1b: //
|
|
+ case 0x1c: //
|
|
+ case 0x1d: //
|
|
+ case 0x1e: //
|
|
+ case 0x1f: //
|
|
+ case 0x22: // Always 0
|
|
+ case 0x23: //
|
|
+ case 0x24: // Reserved
|
|
+ case 0x25: //
|
|
+ case 0x26: //
|
|
+ case 0x27: //
|
|
+ case 0x30: // Oh, no, you're not writing to rom_base!
|
|
+ case 0x31: //
|
|
+ case 0x32: //
|
|
+ case 0x33: //
|
|
+ case 0x3d: //
|
|
+ case 0x05: // disallowing write to command hi-byte
|
|
+ case 0x06: // disallowing write to status lo-byte (is that expected?)
|
|
+ strcpy(szTmp2, "..");
|
|
+ break;
|
|
+ default:
|
|
+ BX_USB_THIS hub[0].pci_conf[address+i] = value8;
|
|
+ sprintf(szTmp2, "%02x", value8);
|
|
+ }
|
|
+ strrev(szTmp2);
|
|
+ strcat(szTmp, szTmp2);
|
|
+ }
|
|
+ strrev(szTmp);
|
|
+ BX_DEBUG(("Experimental USB PCI write register 0x%02x value 0x%s", address, szTmp));
|
|
+}
|
|
+
|
|
+#endif // BX_PCI_SUPPORT && BX_PCI_USB_SUPPORT
|
|
diff -urN ../bochs/iodev/pciusb.h ./iodev/pciusb.h
|
|
--- ../bochs/iodev/pciusb.h 1970-01-01 01:00:00.000000000 +0100
|
|
+++ ./iodev/pciusb.h 2003-01-25 14:12:43.000000000 +0100
|
|
@@ -0,0 +1,195 @@
|
|
+/////////////////////////////////////////////////////////////////////////
|
|
+// $Id: patch.usb-fys,v 1.5 2003-02-16 18:08:27 vruppert Exp $
|
|
+/////////////////////////////////////////////////////////////////////////
|
|
+//
|
|
+// Copyright (C) 2003 MandrakeSoft S.A.
|
|
+//
|
|
+// MandrakeSoft S.A.
|
|
+// 43, rue d'Aboukir
|
|
+// 75002 Paris - France
|
|
+// http://www.linux-mandrake.com/
|
|
+// http://www.mandrakesoft.com/
|
|
+//
|
|
+// This library is free software; you can redistribute it and/or
|
|
+// modify it under the terms of the GNU Lesser General Public
|
|
+// License as published by the Free Software Foundation; either
|
|
+// version 2 of the License, or (at your option) any later version.
|
|
+//
|
|
+// This library is distributed in the hope that it will be useful,
|
|
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+// Lesser General Public License for more details.
|
|
+//
|
|
+// You should have received a copy of the GNU Lesser General Public
|
|
+// License along with this library; if not, write to the Free Software
|
|
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
+
|
|
+// Benjamin D Lunt (fys@cybertrails.com) coded most of this usb emulation.
|
|
+// I hope to add to this code to make it more functionable.
|
|
+//
|
|
+
|
|
+#if BX_USE_PCIUSB_SMF
|
|
+# define BX_USB_THIS theUSBDevice->
|
|
+#else
|
|
+# define BX_USB_THIS this->
|
|
+#endif
|
|
+
|
|
+#define BX_USB_MAXDEV 1
|
|
+#define BX_USB_CONFDEV 1 /* only 1 USB hub currently */
|
|
+
|
|
+#define USB_NUM_PORTS 2 /* UHCI supports 2 ports per root hub */
|
|
+
|
|
+typedef struct {
|
|
+
|
|
+ Bit16u base_ioaddr;
|
|
+ Bit8u irq;
|
|
+ int timer_index;
|
|
+
|
|
+ // Registers
|
|
+ // Base + 0x00 Command register
|
|
+ // Base + 0x02 Status register
|
|
+ // Base + 0x04 Interrupt Enable register
|
|
+ // Base + 0x06 Frame Number register
|
|
+ // Base + 0x08 Frame Base Register (32-bit)
|
|
+ // Base + 0x0C Start of Frame Modify register
|
|
+ // Base + 0x0D
|
|
+ // Base + 0x0E
|
|
+ // Base + 0x0F
|
|
+ // Base + 0x10 Eight(?) 16-bit ports (one for each port on hub)
|
|
+
|
|
+ // Bit reps of registers above
|
|
+ // Command Register
|
|
+ // Bits 15-8 are reserved
|
|
+ // Bit 7 = Maximum packet size
|
|
+ // Bit 6 = Host Controller has been configured (set by software)
|
|
+ // Bit 5 = software debug mode
|
|
+ // Bit 4 = force global resume
|
|
+ // Bit 3 = enter global suspend mode
|
|
+ // Bit 2 = global reset
|
|
+ // Bit 1 = host controller reset
|
|
+ // Bit 0 = run/stop schedule
|
|
+ struct {
|
|
+ bx_bool max_packet_size; //(bit 7) 0 = 32 bytes, 1 = 64 bytes
|
|
+ bx_bool configured; //(bit 6)
|
|
+ bx_bool debug; //(bit 5)
|
|
+ bx_bool resume; //(bit 4)
|
|
+ bx_bool suspend; //(bit 3)
|
|
+ bx_bool reset; //(bit 2)
|
|
+ bx_bool host_reset; //(bit 1)
|
|
+ bx_bool schedule; //(bit 0) 0 = Stop, 1 = Run
|
|
+ } usb_command;
|
|
+
|
|
+ // Status Register
|
|
+ // Bits 15-6 are reserved
|
|
+ // Bit 5 = Host controller halted
|
|
+ // Bit 4 = Host controller process error
|
|
+ // Bit 3 = PCI Bus error
|
|
+ // Bit 2 = resume received
|
|
+ // Bit 1 = USB error interrupt
|
|
+ // Bit 0 = USB interrupt
|
|
+ struct {
|
|
+ bx_bool host_halted; //(bit 5)
|
|
+ bx_bool host_error; //(bit 4)
|
|
+ bx_bool pci_error; //(bit 3)
|
|
+ bx_bool resume; //(bit 2)
|
|
+ bx_bool error_interrupt; //(bit 1)
|
|
+ bx_bool interrupt; //(bit 0)
|
|
+ } usb_status;
|
|
+
|
|
+ // Interrupt Enable Register
|
|
+ // Bits 15-4 are reserved
|
|
+ // Bit 3 = enable short packet interrupts
|
|
+ // Bit 2 = enable interrupt On Complete
|
|
+ // Bit 1 = enable resume
|
|
+ // Bit 0 = enable timeout/crc
|
|
+ struct {
|
|
+ bx_bool short_packet; //(bit 3)
|
|
+ bx_bool on_complete; //(bit 2)
|
|
+ bx_bool resume; //(bit 1)
|
|
+ bx_bool timeout_crc; //(bit 0)
|
|
+ } usb_enable;
|
|
+
|
|
+ // Frame Number Register
|
|
+ // Bits 15-11 are reserved
|
|
+ // Bits 10-0 Frame List Current Index/Frame Number
|
|
+ struct {
|
|
+ Bit16u frame_num;
|
|
+ } usb_frame_num;
|
|
+
|
|
+ // Frame List Base Address Register
|
|
+ // Bits 31-12 Base
|
|
+ // Bits 11-0 *must* be zeros when written to
|
|
+ struct {
|
|
+ Bit32u frame_base;
|
|
+ } usb_frame_base;
|
|
+
|
|
+ // Start of Frame Modify Register
|
|
+ // Bit 7 reserved
|
|
+ // Bits 6-0 SOF timing value (default 64)
|
|
+ // SOF cycle time equals 11936+timing value
|
|
+ struct {
|
|
+ Bit8u sof_timing;
|
|
+ } usb_sof;
|
|
+
|
|
+ // Port Register (0-1)
|
|
+ // Bits 15-13 are reserved
|
|
+ // Bit 12 suspend port
|
|
+ // Bit 11-10 are reserved
|
|
+ // Bit 9 port in reset state
|
|
+ // Bit 8 low-speed device is attached (read-only)
|
|
+ // Bit 7 reserved
|
|
+ // Bit 6 resume detected (read-only)
|
|
+ // Bit 5 line-status D+ (read-only)
|
|
+ // Bit 4 line-status D- (read-only)
|
|
+ // Bit 3 port enabled/disable status has changed
|
|
+ // (write 1 to this bit to clear it)
|
|
+ // Bit 2 port is enabled
|
|
+ // Bit 1 connect status has changed
|
|
+ // (write 1 to this bit to clear it)
|
|
+ // Bit 0 current connect status (read-only)
|
|
+ // Can only write in WORD sizes (Read in byte sizes???)
|
|
+ struct {
|
|
+ bx_bool suspend;
|
|
+ bx_bool reset;
|
|
+ bx_bool low_speed;
|
|
+ bx_bool resume;
|
|
+ bx_bool line_dplus;
|
|
+ bx_bool line_dminus;
|
|
+ bx_bool able_changed;
|
|
+ bx_bool enabled;
|
|
+ bx_bool connect_changed;
|
|
+ bx_bool status;
|
|
+ } usb_port[USB_NUM_PORTS];
|
|
+
|
|
+ Bit8u pci_conf[256];
|
|
+
|
|
+} bx_usb_t;
|
|
+
|
|
+
|
|
+class bx_pciusb_c : public bx_devmodel_c
|
|
+{
|
|
+public:
|
|
+ bx_pciusb_c(void);
|
|
+ ~bx_pciusb_c(void);
|
|
+ virtual void init(void);
|
|
+ virtual void reset(unsigned type);
|
|
+
|
|
+private:
|
|
+
|
|
+ bx_usb_t hub[BX_USB_MAXDEV];
|
|
+ Bit8u global_reset;
|
|
+
|
|
+ static void usb_timer_handler(void *);
|
|
+ void usb_timer(void);
|
|
+
|
|
+ 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);
|
|
+ static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len);
|
|
+ static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len);
|
|
+#if !BX_USE_PCIUSB_SMF
|
|
+ Bit32u read(Bit32u address, unsigned io_len);
|
|
+ void write(Bit32u address, Bit32u value, unsigned io_len);
|
|
+ Bit32u pci_read(Bit8u address, unsigned io_len);
|
|
+ void pci_write(Bit8u address, Bit32u value, unsigned io_len);
|
|
+#endif
|
|
+};
|
|
diff -urN ../bochs/main.cc ./main.cc
|
|
--- ../bochs/main.cc 2003-01-13 21:50:12.000000000 +0100
|
|
+++ ./main.cc 2003-01-25 13:29:22.000000000 +0100
|
|
@@ -747,7 +747,8 @@
|
|
// initialize serial and parallel port options
|
|
#define PAR_SER_INIT_LIST_MAX \
|
|
((BXP_PARAMS_PER_PARALLEL_PORT * BX_N_PARALLEL_PORTS) \
|
|
- + (BXP_PARAMS_PER_SERIAL_PORT * BX_N_SERIAL_PORTS))
|
|
+ + (BXP_PARAMS_PER_SERIAL_PORT * BX_N_SERIAL_PORTS) \
|
|
+ + (BXP_PARAMS_PER_USB_HUB * BX_N_USB_HUBS))
|
|
bx_param_c *par_ser_init_list[1+PAR_SER_INIT_LIST_MAX];
|
|
bx_param_c **par_ser_ptr = &par_ser_init_list[0];
|
|
|
|
@@ -797,6 +798,43 @@
|
|
*par_ser_ptr++ = bx_options.com[i].Oenabled;
|
|
*par_ser_ptr++ = bx_options.com[i].Odev;
|
|
}
|
|
+
|
|
+ // usb hubs
|
|
+ for (i=0; i<BX_N_USB_HUBS; i++) {
|
|
+ // options for USB hub
|
|
+ sprintf (name, "Enable usb hub #%d (USB%d)", i+1, i+1);
|
|
+ sprintf (descr, "Controls whether USB%d is installed or not", i+1);
|
|
+ bx_options.usb[i].Oenabled = new bx_param_bool_c (
|
|
+ BXP_USBx_ENABLED(i+1),
|
|
+ strdup(name),
|
|
+ strdup(descr),
|
|
+ (i==0)?1 : 0); // only enable the first by default
|
|
+ bx_options.usb[i].Oioaddr = new bx_param_num_c (
|
|
+ BXP_USBx_IOADDR(i+1),
|
|
+ "USB ioaddr",
|
|
+ "IO base adress of USB hub",
|
|
+ 0, 0xffe0,
|
|
+ (i==0)?0xff40 : 0);
|
|
+ bx_options.usb[i].Oirq = new bx_param_num_c (
|
|
+ BXP_USBx_IRQ(i+1),
|
|
+ "USB irq",
|
|
+ "IRQ of USB hub",
|
|
+ 0, 15,
|
|
+ (i==0)?9 : 0);
|
|
+ deplist = new bx_list_c (BXP_NULL, 2);
|
|
+ deplist->add (bx_options.usb[i].Oioaddr);
|
|
+ deplist->add (bx_options.usb[i].Oirq);
|
|
+ bx_options.usb[i].Oenabled->set_dependent_list (deplist);
|
|
+ // add to menu
|
|
+ *par_ser_ptr++ = bx_options.usb[i].Oenabled;
|
|
+ *par_ser_ptr++ = bx_options.usb[i].Oioaddr;
|
|
+ *par_ser_ptr++ = bx_options.usb[i].Oirq;
|
|
+
|
|
+ bx_options.usb[i].Oioaddr->set_ask_format (
|
|
+ BX_WITH_WX? "I/O Address :"
|
|
+ : "Enter new ioaddr: [0x%x] ");
|
|
+ bx_options.usb[i].Oioaddr->set_base (16);
|
|
+ }
|
|
// add final NULL at the end, and build the menu
|
|
*par_ser_ptr = NULL;
|
|
menu = new bx_list_c (BXP_MENU_SERIAL_PARALLEL,
|
|
@@ -2924,7 +2962,26 @@
|
|
}
|
|
}
|
|
#endif
|
|
-
|
|
+ else if (!strcmp(params[0], "usb1")) {
|
|
+ for (i=1; i<num_params; i++) {
|
|
+ if (!strncmp(params[i], "enabled=", 8)) {
|
|
+ bx_options.usb[0].Oenabled->set (atol(¶ms[i][8]));
|
|
+ }
|
|
+ else if (!strncmp(params[i], "ioaddr=", 7)) {
|
|
+ if ( (params[i][7] == '0') && (params[i][8] == 'x') )
|
|
+ bx_options.usb[0].Oioaddr->set (strtoul (¶ms[i][7], NULL, 16));
|
|
+ else
|
|
+ bx_options.usb[0].Oioaddr->set (strtoul (¶ms[i][7], NULL, 10));
|
|
+ bx_options.usb[0].Oenabled->set (1);
|
|
+ }
|
|
+ else if (!strncmp(params[i], "irq=", 4)) {
|
|
+ bx_options.usb[0].Oirq->set (atol(¶ms[i][4]));
|
|
+ }
|
|
+ else {
|
|
+ PARSE_ERR(("%s: unknown parameter for usb1 ignored.", context));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
else if (!strcmp(params[0], "floppy_bootsig_check")) {
|
|
if (num_params != 2) {
|
|
PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
|
|
@@ -3661,6 +3718,18 @@
|
|
}
|
|
|
|
int
|
|
+bx_write_usb_options (FILE *fp, bx_usb_options *opt, int n)
|
|
+{
|
|
+ fprintf (fp, "usb%d: enabled=%d", n, opt->Oenabled->get ());
|
|
+ if (opt->Oenabled->get ()) {
|
|
+ fprintf (fp, ", ioaddr=0x%04x, irq=%d", opt->Oioaddr->get (),
|
|
+ opt->Oirq->get ());
|
|
+ }
|
|
+ fprintf (fp, "\n");
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int
|
|
bx_write_sb16_options (FILE *fp, bx_sb16_options *opt)
|
|
{
|
|
if (!opt->Opresent->get ()) {
|
|
@@ -3786,6 +3855,7 @@
|
|
//bx_write_serial_options (fp, &bx_options.com[1], 2);
|
|
//bx_write_serial_options (fp, &bx_options.com[2], 3);
|
|
//bx_write_serial_options (fp, &bx_options.com[3], 4);
|
|
+ bx_write_usb_options (fp, &bx_options.usb[0], 1);
|
|
bx_write_sb16_options (fp, &bx_options.sb16);
|
|
int bootdrive = bx_options.Obootdrive->get ();
|
|
fprintf (fp, "boot: %s\n", (bootdrive==BX_BOOT_FLOPPYA) ? "floppy" : (bootdrive==BX_BOOT_DISKC) ? "disk" : "cdrom");
|
|
diff -urN ../bochs/plugin.h ./plugin.h
|
|
--- ../bochs/plugin.h 2003-01-11 09:28:51.000000000 +0100
|
|
+++ ./plugin.h 2003-01-22 23:53:14.000000000 +0100
|
|
@@ -37,7 +37,8 @@
|
|
#define BX_PLUGIN_SB16 "sb16"
|
|
#define BX_PLUGIN_NE2K "ne2k"
|
|
#define BX_PLUGIN_EXTFPUIRQ "extfpuirq"
|
|
-#define BX_PLUGIN_PCIVGA "pcivga"
|
|
+#define BX_PLUGIN_PCIVGA "pcivga"
|
|
+#define BX_PLUGIN_PCIUSB "pciusb"
|
|
|
|
|
|
#define BX_REGISTER_DEVICE pluginRegisterDevice
|
|
@@ -302,6 +303,7 @@
|
|
DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci)
|
|
DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci2isa)
|
|
DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pcivga)
|
|
+DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pciusb)
|
|
DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(sb16)
|
|
DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(ne2k)
|
|
DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(extfpuirq)
|