xref: /haiku/src/add-ons/kernel/drivers/graphics/radeon/agp.c (revision aff60bb217827097c13d643275fdf1f1c66e7f17)
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_rq_shift	24
41 #define PCI_agp_status_sba		0x0200	/* Sideband addressing supported */
42 #define PCI_agp_status_64bit	0x0020	/* 64-bit addressing supported */
43 #define PCI_agp_status_fw		0x0010	/* FW transfers supported */
44 #define PCI_agp_status_rate4	0x0004	/* 4x transfer rate supported */
45 #define PCI_agp_status_rate2	0x0002	/* 2x transfer rate supported */
46 #define PCI_agp_status_rate1	0x0001	/* 1x transfer rate supported */
47 
48 #define PCI_agp_command			8	/* Control register */
49 #define PCI_agp_command_rq_mask 0xff000000  /* Master: Maximum number of requests */
50 #define PCI_agp_command_rq_shift 24
51 #define PCI_agp_command_sba		0x0200	/* Sideband addressing enabled */
52 #define PCI_agp_command_agp		0x0100	/* Allow processing of AGP transactions */
53 #define PCI_agp_command_64bit	0x0020 	/* Allow processing of 64-bit addresses */
54 #define PCI_agp_command_fw		0x0010 	/* Force FW transfers */
55 #define PCI_agp_command_rate4	0x0004	/* Use 4x rate */
56 #define PCI_agp_command_rate2	0x0002	/* Use 2x rate */
57 #define PCI_agp_command_rate1	0x0001	/* Use 1x rate */
58 
59 
60 
61 // helper macros for easier PCI access
62 #define get_pci(o, s) (*pci_bus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
63 #define set_pci(o, s, v) (*pci_bus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
64 
65 
66 // show AGP capabilities
67 static void show_agp_status( uint32 status )
68 {
69 	SHOW_FLOW( 3, "Status (%08lx): Max Queue Depth=%ld %s%s%s%s%s%s", status,
70 		(status & PCI_agp_status_rq_mask) >> PCI_agp_status_rq_shift,
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): Queue Depth=%ld %s%s%s%s%s%s%s", command,
84 		(command & PCI_agp_command_rq_mask) >> PCI_agp_command_rq_shift,
85 		(command & PCI_agp_command_sba) != 0 ? "Sideband addressing " : "",
86 		(command & PCI_agp_command_agp) != 0 ? "AGP-Enabled " : "AGP-Disabled ",
87 		(command & PCI_agp_command_64bit) != 0 ? "64-bit " : "",
88 		(command & PCI_agp_command_fw) != 0 ? "FastWrite " : "",
89 		(command & PCI_agp_command_rate4) != 0 ? "4x " : "",
90 		(command & PCI_agp_command_rate2) != 0 ? "2x " : "",
91 		(command & PCI_agp_command_rate1) != 0 ? "1x " : "" );
92 }
93 
94 
95 // find PCI capability
96 int find_capability( pci_info *pcii, uint8 capability )
97 {
98 	int try_count;
99 	uint16 status;
100 	uint8 pos;
101 
102 	// check whether PCI capabilities are supported at all
103 	status = get_pci( PCI_status, 2 );
104 
105 	if( (status & PCI_status_cap_list) == 0 )
106 		return B_NAME_NOT_FOUND;
107 
108 	SHOW_FLOW0( 3, "Device supports capabilities" );
109 
110 	// get offset of first capability in list
111 	switch( pcii->header_type & PCI_header_type_mask ) {
112 	case PCI_header_type_normal:
113 	case PCI_header_type_bridge:
114 		pos = get_pci( PCI_capability_list, 1 );
115 		break;
116 	case PCI_header_type_cardbus:
117 		pos = get_pci( PCI_cb_capability_list, 1 );
118 		break;
119 	default:
120 		SHOW_FLOW( 3, "Unknown type (%x)", pcii->header_type & PCI_header_type_mask );
121 		return B_ERROR;
122 	}
123 
124 	// search for whished capability in linked list
125 	for( try_count = 48; try_count > 0 && pos >= 0x40; --try_count ) {
126 		uint8 id;
127 
128 		pos &= ~3;
129 
130 		id = get_pci( pos + PCI_cap_list_id, 1 );
131 		if( id == 0xff )
132 			return B_NAME_NOT_FOUND;
133 
134 		if( id == capability ) {
135 			SHOW_FLOW( 3, "Found capability %d", capability );
136 			return pos;
137 		}
138 
139 		SHOW_FLOW( 3, "Ignored capability %d", id );
140 
141 		pos = get_pci( pos + PCI_cap_list_next, 1 );
142 	}
143 
144 	return B_NAME_NOT_FOUND;
145 }
146 
147 
148 // fix invalid AGP settings
149 void Radeon_Fix_AGP(void)
150 {
151 	long pci_index;
152 	pci_info pci_data, *pcii;
153 
154 	// start with all features enabled, queue depth bits must be 0
155 	uint32 common_caps =
156 		PCI_agp_status_sba | PCI_agp_status_64bit | PCI_agp_status_fw |
157 		PCI_agp_status_rate4 | PCI_agp_status_rate2 | PCI_agp_status_rate1;
158 	uint32 read_queue_depth = PCI_agp_status_rq_mask;
159 
160 	SHOW_FLOW0( 4, "Composing common feature list" );
161 
162 	// only required to make get_pci/set_pci working
163 	pcii = &pci_data;
164 
165 	// find common feature set
166 	for( pci_index = 0;
167 		(*pci_bus->get_nth_pci_info)(pci_index, &pci_data) == B_NO_ERROR;
168 		++pci_index )
169 	{
170 		int offset;
171 
172 		/*SHOW_FLOW( 3, "Checking bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
173 			pcii->bus, pcii->device, pcii->function,
174 			pcii->vendor_id, pcii->device_id );*/
175 
176 		offset = find_capability( pcii, PCI_cap_id_agp );
177 
178 		if( offset > 0 ) {
179 			uint32 agp_status, agp_command;
180 
181 			agp_status = get_pci( offset + PCI_agp_status, 4 );
182 			agp_command = get_pci( offset + PCI_agp_command, 4 );
183 
184 			SHOW_FLOW( 3, "bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
185 				pcii->bus, pcii->device, pcii->function,
186 				pcii->vendor_id, pcii->device_id );
187 			show_agp_status( agp_status );
188 			show_agp_command( agp_command );
189 
190 			common_caps &= agp_status;
191 			read_queue_depth = min( read_queue_depth, agp_status & PCI_agp_status_rq_mask );
192 		}
193 	}
194 
195 	// explicitely enable AGP - it's not part of status register
196 	common_caps |= PCI_agp_command_agp;
197 
198 	// choose fastest transmission speed and disable lower ones
199 	if( (common_caps & PCI_agp_status_rate4) != 0 )
200 		common_caps &= ~(PCI_agp_status_rate2 | PCI_agp_status_rate1);
201 	else if( (common_caps & PCI_agp_status_rate2) != 0 )
202 		common_caps &= ~PCI_agp_status_rate1;
203 	else if( (common_caps & PCI_agp_status_rate1) == 0 )
204 		// no speed found - disable AGP
205 		common_caps &= ~PCI_agp_command_agp;
206 
207 	common_caps |= read_queue_depth;
208 
209 	SHOW_FLOW0( 3, "Combined:" );
210 	show_agp_command( common_caps );
211 
212 	// choose features that all devices support
213 	for( pci_index = 0;
214 		(*pci_bus->get_nth_pci_info)(pci_index, &pci_data) == B_NO_ERROR;
215 		++pci_index )
216 	{
217 		int offset;
218 
219 		offset = find_capability( pcii, PCI_cap_id_agp );
220 
221 		if( offset > 0 ) {
222 			SHOW_FLOW( 3, "Modifying bus %d, device %d, function %d (vendor_id=%04x, device_id=%04x):",
223 				pcii->bus, pcii->device, pcii->function,
224 				pcii->vendor_id, pcii->device_id );
225 
226 			set_pci( offset + PCI_agp_command, 4, common_caps );
227 		}
228 	}
229 }
230