Module Name:    src
Committed By:   msaitoh
Date:           Tue Jan 29 09:25:52 UTC 2019

Modified Files:
        src/sys/dev/pci: ppb.c

Log Message:
 If the secondary bus is configured and the bus mastering is not enabled,
enable it. Suggested by thorpej@.


To generate a diff of this commit:
cvs rdiff -u -r1.66 -r1.67 src/sys/dev/pci/ppb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/ppb.c
diff -u src/sys/dev/pci/ppb.c:1.66 src/sys/dev/pci/ppb.c:1.67
--- src/sys/dev/pci/ppb.c:1.66	Mon Jan 28 04:09:51 2019
+++ src/sys/dev/pci/ppb.c	Tue Jan 29 09:25:52 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: ppb.c,v 1.66 2019/01/28 04:09:51 msaitoh Exp $	*/
+/*	$NetBSD: ppb.c,v 1.67 2019/01/29 09:25:52 msaitoh Exp $	*/
 
 /*
  * Copyright (c) 1996, 1998 Christopher G. Demetriou.  All rights reserved.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.66 2019/01/28 04:09:51 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ppb.c,v 1.67 2019/01/29 09:25:52 msaitoh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ppb.h"
@@ -222,6 +222,7 @@ ppbattach(device_t parent, device_t self
 	char intrbuf[PCI_INTRSTR_LEN];
 #endif
 	pcireg_t busdata, reg;
+	bool second_configured = false;
 
 	pci_aprint_devinfo(pa, NULL);
 
@@ -358,10 +359,72 @@ ppbattach(device_t parent, device_t self
 	}
 #endif /* PPB_USEINTR */
 
-	/* Enable bus master. */
-	reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
-	pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
-	    reg | PCI_COMMAND_MASTER_ENABLE);
+	/* Configuration test */
+	if (PPB_BUSINFO_SECONDARY(busdata) != 0) {
+		uint32_t base, limit;
+
+		/* I/O region test */
+		reg = pci_conf_read(pc, pa->pa_tag, PCI_BRIDGE_STATIO_REG);
+		base = (reg & PCI_BRIDGE_STATIO_IOBASE_MASK) << 8;
+		limit = ((reg >> PCI_BRIDGE_STATIO_IOLIMIT_SHIFT)
+		    & PCI_BRIDGE_STATIO_IOLIMIT_MASK) << 8;
+		limit |= 0x00000fff;
+		if (PCI_BRIDGE_IO_32BITS(reg)) {
+			reg = pci_conf_read(pc, pa->pa_tag,
+			    PCI_BRIDGE_IOHIGH_REG);
+			base |= ((reg >> PCI_BRIDGE_IOHIGH_BASE_SHIFT)
+			    & 0xffff) << 16;
+			limit |= ((reg >> PCI_BRIDGE_IOHIGH_LIMIT_SHIFT)
+			    & 0xffff) << 16;
+		}
+		if (base < limit) {
+			second_configured = true;
+			goto configure;
+		}
+
+		/* Non-prefetchable memory region test */
+		reg = pci_conf_read(pc, pa->pa_tag, PCI_BRIDGE_MEMORY_REG);
+		base = ((reg >> PCI_BRIDGE_MEMORY_BASE_SHIFT)
+		    & PCI_BRIDGE_MEMORY_BASE_MASK) << 20;
+		limit = (((reg >> PCI_BRIDGE_MEMORY_LIMIT_SHIFT)
+		    & PCI_BRIDGE_MEMORY_LIMIT_MASK) << 20) | 0x000fffff;
+		if (base < limit) {
+			second_configured = true;
+			goto configure;
+		}
+
+		/* Prefetchable memory region test */
+		reg = pci_conf_read(pc, pa->pa_tag,
+		    PCI_BRIDGE_PREFETCHMEM_REG);
+		base = ((reg >> PCI_BRIDGE_PREFETCHMEM_BASE_SHIFT)
+		    & PCI_BRIDGE_PREFETCHMEM_BASE_MASK) << 20;
+		limit = (((reg >> PCI_BRIDGE_PREFETCHMEM_LIMIT_SHIFT)
+			& PCI_BRIDGE_PREFETCHMEM_LIMIT_MASK) << 20) | 0x000fffff;
+		if (PCI_BRIDGE_PREFETCHMEM_64BITS(reg)) {
+			reg = pci_conf_read(pc, pa->pa_tag,
+			    PCI_BRIDGE_IOHIGH_REG);
+			base |= (uint64_t)pci_conf_read(pc, pa->pa_tag,
+			    PCI_BRIDGE_PREFETCHBASE32_REG) << 32;
+			limit |= (uint64_t)pci_conf_read(pc, pa->pa_tag,
+			    PCI_BRIDGE_PREFETCHLIMIT32_REG) << 32;
+		}
+		if (base < limit) {
+			second_configured = true;
+			goto configure;
+		}
+	}
+
+configure:
+	/*
+	 * If the secondary bus is configured and the bus mastering is not
+	 * enabled, enable it.
+	 */
+	if (second_configured) {
+		reg = pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+		if ((reg & PCI_COMMAND_MASTER_ENABLE) == 0)
+			pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
+			    reg | PCI_COMMAND_MASTER_ENABLE);
+	}
 
 	if (!pmf_device_register(self, ppb_suspend, ppb_resume))
 		aprint_error_dev(self, "couldn't establish power handler\n");

Reply via email to