xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/agp.c (revision 67bce78b48ed6d01b5a8eef89f5694c372b7e0a1)
1 /*
2 	Copyright (c) 2002, Thomas Kurschel
3 
4 
5 	Part of Radeon kernel driver
6 
7 	AGP fix. Some motherboard BIOSes enable FastWrite even
8 	though the graphics card doesn't support it. Here, we'll
9 	fix that (hopefully it is generic enough).
10 */
11 
12 
13 #include "radeon_driver.h"
14 
15 
16 // missing PCI definitions
17 #define  PCI_status_cap_list	0x10	/* Support Capability List */
18 
19 #define  PCI_header_type_normal		0
20 #define  PCI_header_type_bridge 	1
21 //#define  PCI_header_type_cardbus 	2
22 
23 #define PCI_capability_list		0x34	/* Offset of first capability list entry */
24 #define PCI_cb_capability_list	0x14
25 
26 #define PCI_cap_list_id		0	/* Capability ID */
27 #define PCI_cap_id_pm		0x01	/* Power Management */
28 #define PCI_cap_id_agp		0x02	/* Accelerated Graphics Port */
29 #define PCI_cap_id_vpd		0x03	/* Vital Product Data */
30 #define PCI_cap_id_slotid	0x04	/* Slot Identification */
31 #define PCI_cap_id_msi		0x05	/* Message Signalled Interrupts */
32 #define PCI_cap_id_chswp	0x06	/* CompactPCI HotSwap */
33 #define PCI_cap_list_next	1	/* Next capability in the list */
34 #define PCI_cap_flags		2	/* Capability defined flags (16 bits) */
35 #define PCI_cap_sizeof		4
36 
37 
38 #define PCI_agp_status			4	/* Status register */
39 #define PCI_agp_status_rq_mask	0xff000000	/* Maximum number of requests - 1 */
40 #define PCI_agp_status_sba		0x0200	/* Sideband addressing supported */
41 #define PCI_agp_status_64bit	0x0020	/* 64-bit addressing supported */
42 #define PCI_agp_status_fw		0x0010	/* FW transfers supported */
43 #define PCI_agp_status_rate4	0x0004	/* 4x transfer rate supported */
44 #define PCI_agp_status_rate2	0x0002	/* 2x transfer rate supported */
45 #define PCI_agp_status_rate1	0x0001	/* 1x transfer rate supported */
46 
47 #define PCI_agp_command			8	/* Control register */
48 #define PCI_agp_command_rq_mask 0xff000000  /* Master: Maximum number of requests */
49 #define PCI_agp_command_sba		0x0200	/* Sideband addressing enabled */
50 #define PCI_agp_command_agp		0x0100	/* Allow processing of AGP transactions */
51 #define PCI_agp_command_64bit	0x0020 	/* Allow processing of 64-bit addresses */
52 #define PCI_agp_command_fw		0x0010 	/* Force FW transfers */
53 #define PCI_agp_command_rate4	0x0004	/* Use 4x rate */
54 #define PCI_agp_command_rate2	0x0002	/* Use 2x rate */
55 #define PCI_agp_command_rate1	0x0001	/* Use 1x rate */
56 
57 
58 
59 // helper macros for easier PCI access
60 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
61 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
62 
63 int find_capability( pci_info *pcii, uint8 capability );
64 void Radeon_Fix_AGP( void );
65 
66 
67 // show AGP capabilities
68 static void show_agp_status( uint32 status )
69 {
70 	SHOW_FLOW( 3, "Status (%08lx): %s%s%s%s%s%s", status,
71 		(status & PCI_agp_status_sba) != 0 ? "Sideband addressing " : "",
72 		(status & PCI_agp_status_64bit) != 0 ? "64-bit " : "",
73 		(status & PCI_agp_status_fw) != 0 ? "FastWrite " : "",
74 		(status & PCI_agp_status_rate4) != 0 ? "4x " : "",
75 		(status & PCI_agp_status_rate2) != 0 ? "2x " : "",
76 		(status & PCI_agp_status_rate1) != 0 ? "1x " : "" );
77 }
78 
79 
80 // show AGP settings
81 static void show_agp_command( uint32 command )
82 {
83 	SHOW_FLOW( 3, "Command (%08lx): %s%s%s%s%s%s%s", command,
84 		(command & PCI_agp_command_sba) != 0 ? "Sideband addressing " : "",
85 		(command & PCI_agp_command_agp) != 0 ? "AGP-Enabled " : "AGP-Disabled ",
86 		(command & PCI_agp_command_64bit) != 0 ? "64-bit " : "",
87 		(command & PCI_agp_command_fw) != 0 ? "FastWrite " : "",
88 		(command & PCI_agp_command_rate4) != 0 ? "4x " : "",
89 		(command & PCI_agp_command_rate2) != 0 ? "2x " : "",
90 		(command & PCI_agp_command_rate1) != 0 ? "1x " : "" );
91 }
92 
93 
94 // find PCI capability
95 int find_capability( pci_info *pcii, uint8 capability )
96 {
97 	int try_count;
98 	uint16 status;
99 	uint8 pos;
100 
101 	// check whether PCI capabilities are supported at all
102 	status = get_pci( PCI_status, 2 );
103 
104 	if( (status & PCI_status_cap_list) == 0 )
105 		return B_NAME_NOT_FOUND;
106 
107 	SHOW_FLOW0( 3, "Device supports capabilities" );
108 
109 	// get offset of first capability in list
110 	switch( pcii->header_type & PCI_header_type_mask ) {
111 	case PCI_header_type_normal:
112 	case PCI_header_type_bridge:
113 		pos = get_pci( PCI_capability_list, 1 );
114 		break;
115 	case PCI_header_type_cardbus:
116 		pos = get_pci( PCI_cb_capability_list, 1 );
117 		break;
118 	default:
119 		SHOW_FLOW( 3, "Unknown type (%x)", pcii->header_type & PCI_header_type_mask );
120 		return B_ERROR;
121 	}
122 
123 	// search for whished capability in linked list
124 	for( try_count = 48; try_count > 0 && pos >= 0x40; --try_count ) {
125 		uint8 id;
126 
127 		pos &= ~3;
128 
129 		id = get_pci( pos + PCI_cap_list_id, 1 );
130 		if( id == 0xff )
131 			return B_NAME_NOT_FOUND;
132 
133 		if( id == capability ) {
134 			SHOW_FLOW( 3, "Found capability %d", capability );
135 			return pos;
136 		}
137 
138 		SHOW_FLOW( 3, "Ignored capability %d", id );
139 
140 		pos = get_pci( pos + PCI_cap_list_next, 1 );
141 	}
142 
143 	return B_NAME_NOT_FOUND;
144 }
145 
146 
147 // fix invalid AGP settings
148 void Radeon_Fix_AGP()
149 {
150 	long pci_index;
151 	pci_info pci_data, *pcii;
152 
153 	uint32 common_caps =
154 		PCI_agp_status_sba | PCI_agp_status_64bit | PCI_agp_status_fw |
155 		PCI_agp_status_rate4 | PCI_agp_status_rate2 | PCI_agp_status_rate1;
156 	uint32 read_queue_depth = PCI_agp_status_rq_mask;
157 
158 	SHOW_FLOW0( 4, "Composing common feature list" );
159 
160 	// only required to make get_pci/set_pci working
161 	pcii = &pci_data;
162 
163 	// find common feature set
164 	for( pci_index = 0;
165 		(*pci_bus->get_nth_pci_info)(pci_index, &pci_data) == B_NO_ERROR;
166 		++pci_index )
167 	{
168 		int offset;
169 
170 		SHOW_FLOW( 3, "Checking bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
171 			pcii->bus, pcii->device, pcii->function,
172 			pcii->vendor_id, pcii->device_id );
173 
174 		offset = find_capability( pcii, PCI_cap_id_agp );
175 
176 		if( offset > 0 ) {
177 			uint32 agp_status, agp_command;
178 
179 			agp_status = get_pci( offset + PCI_agp_status, 4 );
180 			agp_command = get_pci( offset + PCI_agp_command, 4 );
181 
182 			SHOW_FLOW( 3, "bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
183 				pcii->bus, pcii->device, pcii->function,
184 				pcii->vendor_id, pcii->device_id );
185 			show_agp_status( agp_status );
186 			show_agp_command( agp_command );
187 
188 			common_caps &= agp_status;
189 			read_queue_depth = min( read_queue_depth, agp_status & PCI_agp_status_rq_mask );
190 		}
191 	}
192 
193 	SHOW_FLOW0( 3, "Combined:" );
194 	show_agp_command( common_caps );
195 
196 	// choose features that all devices support
197 	for( pci_index = 0;
198 		(*pci_bus->get_nth_pci_info)(pci_index, &pci_data) == B_NO_ERROR;
199 		++pci_index )
200 	{
201 		int offset;
202 
203 		offset = find_capability( pcii, PCI_cap_id_agp );
204 
205 		if( offset > 0 ) {
206 			SHOW_FLOW( 3, "Modifying bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
207 				pcii->bus, pcii->device, pcii->function,
208 				pcii->vendor_id, pcii->device_id );
209 
210 			set_pci( offset + PCI_agp_command, 4, common_caps | read_queue_depth );
211 		}
212 	}
213 }
214