xref: /titanic_41/usr/src/uts/sun4u/io/pci/pcix.c (revision ea8dc4b6d2251b437950c0056bc626b311c73c27)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/kmem.h>
31 #include <sys/async.h>
32 #include <sys/sysmacros.h>
33 #include <sys/sunddi.h>
34 #include <sys/sunndi.h>
35 #include <sys/ddi_impldefs.h>
36 #include <sys/ddi_implfuncs.h>
37 #include <sys/pci/pci_obj.h>
38 #include <sys/pci.h>
39 
40 /*LINTLIBRARY*/
41 
42 static uint16_t
43 pcix_get_pcix_cap(ddi_acc_handle_t handle)
44 {
45 	ushort_t caps_ptr, cap;
46 
47 	/*
48 	 * Walk the Capabilities List and locate
49 	 * the PCI-X Capability.
50 	 */
51 	if (pci_config_get16(handle, PCI_CONF_STAT) & PCI_STAT_CAP)
52 		caps_ptr = pci_config_get8(handle, PCI_CONF_CAP_PTR);
53 	else
54 		caps_ptr = PCI_CAP_NEXT_PTR_NULL;
55 
56 	while (caps_ptr != PCI_CAP_NEXT_PTR_NULL) {
57 		cap = pci_config_get8(handle, caps_ptr);
58 		if (cap == PCI_CAP_ID_PCIX)
59 			return (caps_ptr);
60 
61 		caps_ptr = pci_config_get8(handle, caps_ptr + PCI_CAP_NEXT_PTR);
62 	}
63 
64 	return (0);
65 }
66 
67 void
68 pcix_set_cmd_reg(dev_info_t *child, uint16_t value)
69 {
70 	uint16_t pcix_cap_offset, pcix_cmd;
71 	ddi_acc_handle_t handle;
72 
73 	if (pci_config_setup(child, &handle) != DDI_SUCCESS)
74 		return;
75 
76 	/*
77 	 * Only modify the Command Register of non-bridge functions.
78 	 */
79 	if ((pci_config_get8(handle, PCI_CONF_HEADER) &
80 	    PCI_HEADER_TYPE_M) == PCI_HEADER_PPB) {
81 		pci_config_teardown(&handle);
82 		return;
83 	}
84 
85 	pcix_cap_offset = pcix_get_pcix_cap(handle);
86 
87 	DEBUG1(DBG_INIT_CLD, child,
88 	    "pcix_set_cmd_reg: pcix_cap_offset = %x\n", pcix_cap_offset);
89 
90 	if (pcix_cap_offset) {
91 		/*
92 		 * Read the PCI-X Command Register.
93 		 */
94 		pcix_cmd = pci_config_get16(handle, (pcix_cap_offset + 2));
95 
96 		DEBUG1(DBG_INIT_CLD, child,
97 		    "pcix_set_cmd_reg: PCI-X CMD "
98 		    "Register (Before) %x\n", pcix_cmd);
99 
100 		pcix_cmd &= ~(0x1f << 2); /* clear bits 6-2 */
101 		pcix_cmd |= value;
102 
103 		DEBUG1(DBG_INIT_CLD, child,
104 		    "pcix_set_cmd_reg: PCI-X CMD "
105 		    "Register (After) %x\n", pcix_cmd);
106 
107 		pci_config_put16(handle, (pcix_cap_offset + 2), pcix_cmd);
108 	}
109 
110 	pci_config_teardown(&handle);
111 }
112