Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-6]: src/sys/arch/sparc64/dev Pull up revision 1.33 (requested b...



details:   https://anonhg.NetBSD.org/src/rev/f0c17f0ffa06
branches:  netbsd-1-6
changeset: 529439:f0c17f0ffa06
user:      tron <tron%NetBSD.org@localhost>
date:      Fri Nov 22 17:07:59 2002 +0000

description:
Pull up revision 1.33 (requested by martin in ticket #875):
Set the PCI latency timer for bus master devices.
Slightly different to the patch suggested by Takeshi Nakayama in PR 18451
(idea from FreeBSD).
Additional input from Jason Thorpe: do not hard code the bus frequency,
instead get it from OpenFirmware.

diffstat:

 sys/arch/sparc64/dev/pci_machdep.c |  35 ++++++++++++++++++++++++++++++++++-
 1 files changed, 34 insertions(+), 1 deletions(-)

diffs (60 lines):

diff -r e9f086461cf8 -r f0c17f0ffa06 sys/arch/sparc64/dev/pci_machdep.c
--- a/sys/arch/sparc64/dev/pci_machdep.c        Fri Nov 22 09:38:39 2002 +0000
+++ b/sys/arch/sparc64/dev/pci_machdep.c        Fri Nov 22 17:07:59 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pci_machdep.c,v 1.31 2002/05/16 20:28:33 eeh Exp $     */
+/*     $NetBSD: pci_machdep.c,v 1.31.2.1 2002/11/22 17:07:59 tron Exp $        */
 
 /*
  * Copyright (c) 1999, 2000 Matthew R. Green
@@ -354,10 +354,26 @@
        pci_intr_handle_t *ihp;
 {
        pcitag_t tag = pa->pa_tag;
+       pcireg_t bhlc, ic;
+       int bus_frequency, val, bus_node;
        int interrupts;
        int len, node = PCITAG_NODE(tag);
        char devtype[30];
 
+       bus_node = OF_parent(node);
+       len = OF_getproplen(bus_node, "clock-frequency");
+       if (len < sizeof(bus_frequency)) {
+               DPRINTF(SPDB_INTMAP,
+                       ("pci_intr_map: clock-frequency len %d too small\n", len));
+               return (ENODEV);
+       }
+       if (OF_getprop(bus_node, "clock-frequency", (void *)&bus_frequency, 
+               sizeof(bus_frequency)) != len) {
+               DPRINTF(SPDB_INTMAP,
+                       ("pci_intr_map: could not read bus_frequency\n"));
+               return (ENODEV);
+       }
+
        len = OF_getproplen(node, "interrupts");
        if (len < sizeof(interrupts)) {
                DPRINTF(SPDB_INTMAP,
@@ -384,6 +400,23 @@
                        }
        }
 
+       /*
+        * Initialize the latency timer register for busmaster devices
+        * to work properly.
+        *   latency-timer = min-grant * bus-freq / 4  (from FreeBSD)
+        */
+       ic = pci_conf_read(pa->pa_pc, tag, PCI_INTERRUPT_REG);
+       bus_frequency /= 1000000;
+       val = min(PCI_MIN_GNT(ic) * bus_frequency / 4, 255);
+       if (val > 0) {
+               bhlc = pci_conf_read(pa->pa_pc, tag, PCI_BHLC_REG);
+               if (PCI_LATTIMER(bhlc) < val) {
+                       bhlc &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
+                       bhlc |= (val << PCI_LATTIMER_SHIFT);
+                       pci_conf_write(pa->pa_pc, tag, PCI_BHLC_REG, bhlc);
+               }
+       }
+
        /* XXXX -- we use the ino.  What if there is a valid IGN? */
        *ihp = interrupts;
        return (0);



Home | Main Index | Thread Index | Old Index