USB on ES40

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

USB on ES40

Miod Vallat
Hello,

  there seem to be a few alpha systems where the USB ports do not behave
correctly. One of these is the ES40, where it is often necessary to
disable ohci to be able to use the system.

  I have spent some time pulling hair[0] and trying to figure out why
the USB controller would trigger an interrupt storm, even with no
devices plugged.

  It turns out that, for some better deeply buried reason, the USB
interrupt on all high-end alpha systems (at least Tsunami [1] and Titan
[2] systems, but probably also Marvel [3]) is routed through the ISA
bridge, and is shown to the kernel as an ISA interrupt.

  Some systems (XP1000, DS20) do not lie further and expose a PCI
interrupt (level triggered) with an ISA interrupt vector number, and
everything is fine. But other systems, such as the ES40, work so hard
masquerading the USB interrupt as an ISA interrupt than it seems to
become an edge-triggered interrupt. There lies madness, and this is why
interrupt storms occur on ES40 due to the USB controller, unless it is
disabled in the kernel (boot -fl c to the rescue!)

  The following diff attempts to recognize systems where the USB
interrupt is edge triggered, and prevent the interrupt controller logic
to smartly set it as level triggered. This allows me to use the USB
ports of my ES40 (tested with an USB keyboard and a MAXINT-in-one smart
card reader).

  If your alpha has both an sio0 device and an ohci0 device, please test
this (against HEAD... build GENERIC.MP if you have a multiprocessor
system!), and report whether there is a change in USB behaviour.

Thanks,
Miod

[0] Don't worry, my non-white hair situation has been critical for
    years, with no hope even in the long term undyed future.
[1] CS20, DS10/20, ES40, XP900/1000, DP264, UP* too
[2] DS15/25, ES45
[3] ES47/80, GS160, oh wait we don't run on these yet, but if you have
    one and are willing to test kernels, pleas*e get in touch with me...

Index: pci/sio_pic.c
===================================================================
RCS file: /cvs/src/sys/arch/alpha/pci/sio_pic.c,v
retrieving revision 1.36
diff -u -p -r1.36 sio_pic.c
--- pci/sio_pic.c 18 Feb 2014 19:37:33 -0000 1.36
+++ pci/sio_pic.c 18 Feb 2014 21:12:53 -0000
@@ -116,6 +116,15 @@ u_int8_t initial_ocw1[2];
 u_int8_t initial_elcr[2];
 #endif
 
+/*
+ * Overrides for ELCR settings.
+ * These are used on ES40 and similar systems suffering from a PCI USB HCI
+ * interrupt being routed through the ISA logic with actual logic to
+ * make it behave an edge-triggered interrupt, although PCI interrupts are
+ * supposed to be level-triggered.
+ */
+u_int8_t elcr_override[2] = { 0x00, 0x00 };
+
 void sio_setirqstat(int, int, int);
 int sio_intr_alloc(void *, int, int, int *);
 int sio_intr_check(void *, int, int);
@@ -135,6 +144,9 @@ bus_space_handle_t sio_ioh_elcr;
 int
 i82378_setup_elcr()
 {
+ int device, maxndevs;
+ pcitag_t tag;
+ pcireg_t id;
  int rv;
 
  /*
@@ -145,12 +157,30 @@ i82378_setup_elcr()
 
  rv = bus_space_map(sio_iot, 0x4d0, 2, 0, &sio_ioh_elcr);
 
- if (rv == 0) {
- sio_read_elcr = i82378_read_elcr;
- sio_write_elcr = i82378_write_elcr;
+ if (rv != 0)
+ return 0;
+
+ sio_read_elcr = i82378_read_elcr;
+ sio_write_elcr = i82378_write_elcr;
+
+ /*
+ * Search PCI configuration space for an ALI M5237 USB controller
+ * on the first bus.
+ */
+
+ maxndevs = pci_bus_maxdevs(sio_pc, 0);
+
+ for (device = 0; device < maxndevs; device++) {
+ tag = pci_make_tag(sio_pc, 0, device, 0);
+ id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
+
+ if (id == PCI_ID_CODE(PCI_VENDOR_ALI, PCI_PRODUCT_ALI_M5237)) {
+ elcr_override[10 / 8] |= 1 << (10 % 8);
+ break;
+ }
  }
 
- return (rv);
+ return (0);
 }
 
 u_int8_t
@@ -203,31 +233,13 @@ cy82c693_setup_elcr()
  tag = pci_make_tag(sio_pc, 0, device, 0);
  id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
 
- /* Invalid vendor ID value? */
- if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
- continue;
- /* XXX Not invalid, but we've done this ~forever. */
- if (PCI_VENDOR(id) == 0)
- continue;
-
- if (PCI_VENDOR(id) != PCI_VENDOR_CONTAQ ||
-    PCI_PRODUCT(id) != PCI_PRODUCT_CONTAQ_82C693)
- continue;
-
- /*
- * Found one!
- */
-
-#if 0
- printf("cy82c693_setup_elcr: found 82C693 at device %d\n",
-    device);
-#endif
-
- sio_cy82c693_handle = cy82c693_init(sio_iot);
- sio_read_elcr = cy82c693_read_elcr;
- sio_write_elcr = cy82c693_write_elcr;
-
- return (0);
+ if (id ==
+    PCI_ID_CODE(PCI_VENDOR_CONTAQ, PCI_PRODUCT_CONTAQ_82C693)) {
+ sio_cy82c693_handle = cy82c693_init(sio_iot);
+ sio_read_elcr = cy82c693_read_elcr;
+ sio_write_elcr = cy82c693_write_elcr;
+ return (0);
+ }
  }
 
  /*
@@ -300,13 +312,18 @@ sio_setirqstat(irq, enabled, type)
  ocw1[icu] |= 1 << bit;
 
  /*
- * interrupt type select: set bit to get level-triggered.
+ * interrupt type select: set bit to get level-triggered...
  */
  if (type == IST_LEVEL)
  elcr[icu] |= 1 << bit;
  else
  elcr[icu] &= ~(1 << bit);
 
+ /*
+ * ...unless we pretend to know better.
+ */
+ elcr[icu] &= ~elcr_override[icu];
+
 #ifdef not_here
  /* see the init function... */
  ocw1[0] &= ~0x04; /* always enable IRQ2 on first PIC */
@@ -325,9 +342,6 @@ sio_intr_setup(pc, iot)
  pci_chipset_tag_t pc;
  bus_space_tag_t iot;
 {
-#ifdef notyet
- char *cp;
-#endif
  int i;
 
  sio_iot = iot;

Reply | Threaded
Open this post in threaded view
|

Re: USB on ES40

Maurice Janssen-2
On Tue, Feb 18, 2014 at 09:30:41PM +0000, Miod Vallat wrote:
>  If your alpha has both an sio0 device and an ohci0 device, please test
>this (against HEAD... build GENERIC.MP if you have a multiprocessor
>system!), and report whether there is a change in USB behaviour.

Hi Miod,

I'd like to try your patch on an XP1000, but I'm strugling a bit because
I don't want to touch the hard drive (sd0) that is currently installed in
the machine (with 5.4-stable on it).
I installed the latest snapshot on a USB stick (sd1), but the machine
obviously can't boot direcyly from it.
When I copy the kernel from sd1 to sd0 I can easily boot, but then of course
it thinks sd0a is the root fs (and panics because it can't run init from
5.4 on a 5.5-current kernel due to the time_t changes).

As far as I know there is no easy way to tell the kernel that the root fs
is sd1a, like giving a boot flag from the SRM console.

Without a running current system, I can't compile a kernel with the patch.
So what are my options, besides putting another scsi disk in the machine?

If you can send me a bsd.rd with the patch, I can try to boot it and mount
the USB-stick (or even install the latest snapshot on it, to end up in the
same state as I'm in now, but then at least I can test the working of the
USB system).

--
Maurice