1 | /*
|
---|
2 | ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
|
---|
3 | ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
|
---|
4 | ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
|
---|
5 | ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
|
---|
6 | ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
|
---|
7 | ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
---|
8 | ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
|
---|
9 | ** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
|
---|
10 | **
|
---|
11 | ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
|
---|
12 | ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
|
---|
13 | ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
|
---|
14 | ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
|
---|
15 | ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
|
---|
16 | ** THE UNITED STATES.
|
---|
17 | **
|
---|
18 | ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
|
---|
19 | **
|
---|
20 | **
|
---|
21 | ** $Revision: 1.1 $
|
---|
22 | ** $Date: 2000-02-25 00:33:56 $
|
---|
23 | **
|
---|
24 | */
|
---|
25 |
|
---|
26 | #include <stdlib.h>
|
---|
27 | #include <stdio.h>
|
---|
28 | #include <3dfx.h>
|
---|
29 | #define FX_DLL_DEFINITION
|
---|
30 | #include <fxdll.h>
|
---|
31 | #include <fxmemmap.h>
|
---|
32 | #include "fxpci.h"
|
---|
33 | #include "pcilib.h"
|
---|
34 | #ifdef __linux__
|
---|
35 | #include "fxlinux.h"
|
---|
36 | #endif
|
---|
37 | #ifdef __OS2__
|
---|
38 | #include "fxos2.h"
|
---|
39 | #endif
|
---|
40 |
|
---|
41 | /* PRIVATE DATA (within the library) */
|
---|
42 | FxU32 pciVxdVer = 0;
|
---|
43 | FxU32 pciErrorCode = PCI_ERR_NOERR;
|
---|
44 | FxBool pciLibraryInitialized = FXFALSE;
|
---|
45 | PciHwcCallbacks pciHwcCallbacks = { 1 };
|
---|
46 |
|
---|
47 | const FxPlatformIOProcs* gCurPlatformIO = NULL;
|
---|
48 |
|
---|
49 | /*
|
---|
50 | * linear Address Map List
|
---|
51 | *
|
---|
52 | * This is the new way we keep track of boards which are already mapped
|
---|
53 | */
|
---|
54 | static struct {
|
---|
55 | FxU32
|
---|
56 | device_bus_func_number;
|
---|
57 | struct {
|
---|
58 | FxBool
|
---|
59 | mapped;
|
---|
60 | FxU32
|
---|
61 | addr;
|
---|
62 | } addrList[MAX_PCI_BASEADDRESSES];
|
---|
63 | } linearAddressMapList[MAX_PCI_DEVICES];
|
---|
64 |
|
---|
65 | typedef struct _PCIErr {
|
---|
66 | FxU32 code;
|
---|
67 | char *string;
|
---|
68 | } PCIErr, *PCIErrPtr;
|
---|
69 |
|
---|
70 | static PCIErr pciError[] = {
|
---|
71 | {PCI_ERR_NOERR, "No errors.\n"},
|
---|
72 | {PCI_ERR_WINRTINIT, "WinRT initialization failure.\n" },
|
---|
73 | {PCI_ERR_MEMMAPVXD, "Memmap VxD initialization failure.\n" },
|
---|
74 | {PCI_ERR_MAPMEMDRV, "Mapmem driver initialization failure.\n" },
|
---|
75 | {PCI_ERR_GENPORT, "Genport I/O initialization failure.\n" },
|
---|
76 | {PCI_ERR_NO_BUS, "No PCI Bus detected.\n"},
|
---|
77 | {PCI_ERR_NOTOPEN, "PCI library not open.\n" },
|
---|
78 | {PCI_ERR_NOTOPEN2, "Closing unopened PCI library.\n" },
|
---|
79 | {PCI_ERR_NOTOPEN3, "pciGetConfigData() on unopened library.\n" },
|
---|
80 | {PCI_ERR_OUTOFRANGE, "Device_number is out of range.\n" },
|
---|
81 | {PCI_ERR_NODEV, "Cannot read from a non-existant device.\n" },
|
---|
82 | {PCI_ERR_NODEV2, "Cannot update config regs from non-existant device.\n" },
|
---|
83 | {PCI_ERR_WRITEONLY, "Cannot read a WRITE_ONLY register.\n" },
|
---|
84 | {PCI_ERR_READONLY, "Cannot write a READ_ONLY register.\n" },
|
---|
85 | {PCI_ERR_PHARLAP, "Phar Lap returned an error trying to map memory.\n" },
|
---|
86 | {PCI_ERR_WRONGVXD, "Expected VxD version V%d.%d, got V%d.%d\n"},
|
---|
87 | {PCI_ERR_MEMMAP, "Memmap returned an error trying to map memory.\n" },
|
---|
88 | {PCI_ERR_MAPMEM, "Mapmem returned an error trying to map memory.\n" },
|
---|
89 | {PCI_ERR_WINRT, "Winrt returned an error trying to map memory.\n" },
|
---|
90 | {PCI_ERR_VXDINUSE, "Mutual exclusion prohibits this\n" },
|
---|
91 | {PCI_ERR_NO_IO_PERM, "Permission denied.\n"
|
---|
92 | "Couldn't change I/O priveledge level.\n"},
|
---|
93 | {PCI_ERR_NO_MEM_PERM, "Permission denied.\n"
|
---|
94 | "Couldn't access memory mapp.\n"}
|
---|
95 | };
|
---|
96 |
|
---|
97 | /* -------------------------------------------------- */
|
---|
98 | /* Port IO subroutines - each layer has it's own */
|
---|
99 | FX_ENTRY FxU8 FX_CALL
|
---|
100 | pioInByte ( unsigned short port )
|
---|
101 | {
|
---|
102 | FxU8 data;
|
---|
103 |
|
---|
104 | if (pciHwcCallbacks.pioInByte)
|
---|
105 | data = pciHwcCallbacks.pioInByte(port);
|
---|
106 | if (pciHwcCallbacks.doHW)
|
---|
107 | data = _pioInByte( port );
|
---|
108 | return data;
|
---|
109 | }
|
---|
110 |
|
---|
111 | FX_ENTRY FxU16 FX_CALL
|
---|
112 | pioInWord ( unsigned short port )
|
---|
113 | {
|
---|
114 | FxU16 data;
|
---|
115 |
|
---|
116 | if (pciHwcCallbacks.pioInWord)
|
---|
117 | data = pciHwcCallbacks.pioInWord(port);
|
---|
118 | if (pciHwcCallbacks.doHW)
|
---|
119 | data = _pioInWord( port );
|
---|
120 | return data;
|
---|
121 | }
|
---|
122 |
|
---|
123 | FX_ENTRY FxU32 FX_CALL
|
---|
124 | pioInLong ( unsigned short port )
|
---|
125 | {
|
---|
126 | FxU32 data;
|
---|
127 |
|
---|
128 | if (pciHwcCallbacks.pioInLong)
|
---|
129 | data = pciHwcCallbacks.pioInLong(port);
|
---|
130 | if (pciHwcCallbacks.doHW)
|
---|
131 | data = _pioInLong( port );
|
---|
132 | return data;
|
---|
133 | }
|
---|
134 |
|
---|
135 | FX_ENTRY FxBool FX_CALL
|
---|
136 | pioOutByte ( unsigned short port, FxU8 data )
|
---|
137 | {
|
---|
138 | if (pciHwcCallbacks.pioOutByte)
|
---|
139 | pciHwcCallbacks.pioOutByte(port,data);
|
---|
140 | if (pciHwcCallbacks.doHW)
|
---|
141 | _pioOutByte( port, data );
|
---|
142 | return FXTRUE;
|
---|
143 | }
|
---|
144 |
|
---|
145 | FX_ENTRY FxBool FX_CALL
|
---|
146 | pioOutWord ( unsigned short port, FxU16 data )
|
---|
147 | {
|
---|
148 | if (pciHwcCallbacks.pioOutWord)
|
---|
149 | pciHwcCallbacks.pioOutWord(port,data);
|
---|
150 | if (pciHwcCallbacks.doHW)
|
---|
151 | _pioOutWord( port, data );
|
---|
152 | return FXTRUE;
|
---|
153 | }
|
---|
154 |
|
---|
155 | FX_ENTRY FxBool FX_CALL
|
---|
156 | pioOutLong ( unsigned short port, FxU32 data )
|
---|
157 | {
|
---|
158 | if (pciHwcCallbacks.pioOutLong)
|
---|
159 | pciHwcCallbacks.pioOutLong(port,data);
|
---|
160 | if (pciHwcCallbacks.doHW)
|
---|
161 | _pioOutLong( port, data );
|
---|
162 | return FXTRUE;
|
---|
163 | }
|
---|
164 |
|
---|
165 | static PciRegister baseAddresses[MAX_PCI_BASEADDRESSES];
|
---|
166 | static FxU32 vendorIDs[MAX_PCI_DEVICES];
|
---|
167 | static FxU32 configMechanism = 0;
|
---|
168 | static FxBool busDetected = FXFALSE;
|
---|
169 | static FxBool deviceExists[MAX_PCI_DEVICES];
|
---|
170 |
|
---|
171 | /* PRIVATE FUNCTIONS */
|
---|
172 | FxU32
|
---|
173 | _pciCreateConfigAddress( FxU32 bus_number, FxU32 device_number,
|
---|
174 | FxU32 function_number, FxU32 register_offset )
|
---|
175 | {
|
---|
176 | FxU32 retval = CONFIG_ADDRESS_ENABLE_BIT;
|
---|
177 |
|
---|
178 | retval |= ( bus_number & 0xFF ) << 16;
|
---|
179 | retval |= ( device_number & 0x1F ) << 11;
|
---|
180 | retval |= ( function_number & 0x7 ) << 8;
|
---|
181 | retval |= ( register_offset & 0xFC );
|
---|
182 | return retval;
|
---|
183 | } /* _pciCreateConfigAddress */
|
---|
184 |
|
---|
185 |
|
---|
186 |
|
---|
187 | FxU16
|
---|
188 | _pciCreateConfigSpaceMapping( FxU32 device_number, FxU32
|
---|
189 | register_offset )
|
---|
190 | {
|
---|
191 |
|
---|
192 | FxU16 retval = 0;
|
---|
193 | retval |= ( device_number & 0xFF ) << 8;
|
---|
194 | retval |= ( register_offset & 0xFC );
|
---|
195 | retval += CONFIG_MAPPING_OFFSET;
|
---|
196 | return retval;
|
---|
197 | } /* _pciCreateConfigSpaceMapping */
|
---|
198 |
|
---|
199 |
|
---|
200 |
|
---|
201 | FX_ENTRY FxU32 FX_CALL
|
---|
202 | _pciFetchRegister( FxU32 offset, FxU32 size_in_bytes,
|
---|
203 | FxU32 device_number, FxU32 config_mechanism )
|
---|
204 | {
|
---|
205 | FxU32 retval;
|
---|
206 | FxU32 slot, bus;
|
---|
207 |
|
---|
208 | bus = device_number >> 5;
|
---|
209 | slot = device_number & 0x1f;
|
---|
210 |
|
---|
211 | if ( config_mechanism == 1 ) {
|
---|
212 | pioOutLong( CONFIG_ADDRESS_PORT, _pciCreateConfigAddress( bus, slot, 0, offset ) );
|
---|
213 | retval = pioInLong( CONFIG_DATA_PORT );
|
---|
214 | retval >>= 8 * ( offset & 0x3 );
|
---|
215 | } else { /* config mechanism 2 */
|
---|
216 | pioOutByte( CONFIG_ADDRESS_PORT, CONFIG_MAPPING_ENABLE_BYTE );
|
---|
217 | retval = pioInLong( _pciCreateConfigSpaceMapping( device_number, offset ) );
|
---|
218 | retval >>= 8 * ( offset & 0x3 );
|
---|
219 | pioOutByte( CONFIG_ADDRESS_PORT, CONFIG_MAPPING_DISABLE_BYTE );
|
---|
220 | }
|
---|
221 |
|
---|
222 | switch( size_in_bytes ) {
|
---|
223 | case 1:
|
---|
224 | retval &= 0xFF;
|
---|
225 | break;
|
---|
226 | case 2:
|
---|
227 | retval &= 0xFFFF;
|
---|
228 | break;
|
---|
229 | default: /* 4 bytes */
|
---|
230 | break;
|
---|
231 | }
|
---|
232 |
|
---|
233 | return retval;
|
---|
234 | } /* _pciFetchRegister */
|
---|
235 |
|
---|
236 |
|
---|
237 |
|
---|
238 | FX_ENTRY void FX_CALL
|
---|
239 | _pciUpdateRegister( FxU32 offset, FxU32 data, FxU32 size_in_bytes,
|
---|
240 | FxU32 device_number, FxU32 config_mechanism )
|
---|
241 | {
|
---|
242 | FxU32
|
---|
243 | regval = _pciFetchRegister( offset & ( ~0x3 ), 4,
|
---|
244 | device_number, config_mechanism );
|
---|
245 | FxU32 mask = (FxU32) ~0l;
|
---|
246 | FxU32 bus, slot;
|
---|
247 |
|
---|
248 | bus = device_number >> 5;
|
---|
249 | slot = device_number & 0x1f;
|
---|
250 |
|
---|
251 | switch( size_in_bytes ) {
|
---|
252 | case 1:
|
---|
253 | mask &= 0xFF;
|
---|
254 | data &= 0xFF;
|
---|
255 | break;
|
---|
256 | case 2:
|
---|
257 | mask &= 0xFFFF;
|
---|
258 | data &= 0xFFFF;
|
---|
259 | break;
|
---|
260 | case 4:
|
---|
261 | default:
|
---|
262 | break;
|
---|
263 | }
|
---|
264 |
|
---|
265 | data <<= 8 * ( offset & 0x03 );
|
---|
266 | mask <<= 8 * ( offset & 0x03 );
|
---|
267 |
|
---|
268 | regval = ( regval & ~mask ) | data;
|
---|
269 |
|
---|
270 | if ( config_mechanism == 1 ) {
|
---|
271 | pioOutLong( CONFIG_ADDRESS_PORT, _pciCreateConfigAddress( bus, slot, 0, offset ) );
|
---|
272 | pioOutLong( CONFIG_DATA_PORT, regval );
|
---|
273 | } else { /* config mechanism 2 */
|
---|
274 | pioOutByte( CONFIG_ADDRESS_PORT, CONFIG_MAPPING_ENABLE_BYTE );
|
---|
275 | pioOutLong( _pciCreateConfigSpaceMapping( device_number, offset ), regval );
|
---|
276 | pioOutByte( CONFIG_ADDRESS_PORT, CONFIG_MAPPING_DISABLE_BYTE );
|
---|
277 | }
|
---|
278 |
|
---|
279 | return;
|
---|
280 | } /* _pciUpdateRegister */
|
---|
281 |
|
---|
282 | static FxU32
|
---|
283 | find_mapped_address(FxU32 device_bus_func_number, FxU32 addrNum)
|
---|
284 | {
|
---|
285 | FxU32
|
---|
286 | i,
|
---|
287 | retVal = 0x00UL;
|
---|
288 |
|
---|
289 | for(i = 0; i < MAX_PCI_DEVICES; i++) {
|
---|
290 | if (linearAddressMapList[i].device_bus_func_number == device_bus_func_number) {
|
---|
291 | retVal = linearAddressMapList[i].addrList[addrNum].addr;
|
---|
292 |
|
---|
293 | break;
|
---|
294 | }
|
---|
295 | }
|
---|
296 |
|
---|
297 | return retVal;
|
---|
298 | }
|
---|
299 |
|
---|
300 | static void
|
---|
301 | set_mapped_address(FxU32 device_bus_func_number, FxU32 addrNum, FxU32 value)
|
---|
302 | {
|
---|
303 | FxU32 i;
|
---|
304 |
|
---|
305 | for(i = 0; i < MAX_PCI_DEVICES; i++) {
|
---|
306 | if (linearAddressMapList[i].device_bus_func_number == device_bus_func_number) {
|
---|
307 | FxU32 j;
|
---|
308 |
|
---|
309 | linearAddressMapList[i].addrList[addrNum].mapped = (value != 0x00UL);
|
---|
310 | linearAddressMapList[i].addrList[addrNum].addr = value;
|
---|
311 |
|
---|
312 | for(j = 0; j < MAX_PCI_BASEADDRESSES; j++) {
|
---|
313 | if (linearAddressMapList[i].addrList[j].mapped) break;
|
---|
314 | }
|
---|
315 | if (j == MAX_PCI_BASEADDRESSES) linearAddressMapList[i].device_bus_func_number = 0x00UL;
|
---|
316 |
|
---|
317 | break;
|
---|
318 | }
|
---|
319 | }
|
---|
320 | if (i != MAX_PCI_DEVICES) return;
|
---|
321 |
|
---|
322 | for(i = 0; i < MAX_PCI_DEVICES; i++) {
|
---|
323 | if (linearAddressMapList[i].device_bus_func_number == 0) {
|
---|
324 | linearAddressMapList[i].device_bus_func_number = device_bus_func_number;
|
---|
325 |
|
---|
326 | linearAddressMapList[i].addrList[addrNum].mapped = (value != 0x00UL);
|
---|
327 | linearAddressMapList[i].addrList[addrNum].addr = value;
|
---|
328 |
|
---|
329 | break;
|
---|
330 | }
|
---|
331 | }
|
---|
332 | }
|
---|
333 |
|
---|
334 | /* PUBLIC DATA */
|
---|
335 |
|
---|
336 | PciRegister PCI_VENDOR_ID = { 0x0, 2, READ_ONLY };
|
---|
337 | PciRegister PCI_DEVICE_ID = { 0x2, 2, READ_ONLY };
|
---|
338 | PciRegister PCI_COMMAND = { 0x4, 2, READ_WRITE };
|
---|
339 | PciRegister PCI_STATUS = { 0x6, 2, READ_WRITE };
|
---|
340 | PciRegister PCI_REVISION_ID = { 0x8, 1, READ_ONLY };
|
---|
341 | PciRegister PCI_CLASS_CODE = { 0x9, 3, READ_ONLY };
|
---|
342 | PciRegister PCI_CACHE_LINE_SIZE = { 0xC, 1, READ_WRITE };
|
---|
343 | PciRegister PCI_LATENCY_TIMER = { 0xD, 1, READ_WRITE };
|
---|
344 | PciRegister PCI_HEADER_TYPE = { 0xE, 1, READ_ONLY };
|
---|
345 | PciRegister PCI_BIST = { 0xF, 1, READ_WRITE };
|
---|
346 | PciRegister PCI_BASE_ADDRESS_0 = { 0x10, 4, READ_WRITE };
|
---|
347 | PciRegister PCI_BASE_ADDRESS_1 = { 0x14, 4, READ_WRITE };
|
---|
348 | PciRegister PCI_IO_BASE_ADDRESS = { 0x18, 4, READ_WRITE };
|
---|
349 | PciRegister PCI_SUBVENDOR_ID = { 0x2C, 4, READ_ONLY };
|
---|
350 | PciRegister PCI_SUBSYSTEM_ID = { 0x2E, 4, READ_ONLY };
|
---|
351 | PciRegister PCI_ROM_BASE_ADDRESS= { 0x30, 4, READ_WRITE };
|
---|
352 | PciRegister PCI_CAP_PTR = { 0x34, 4, READ_WRITE };
|
---|
353 | PciRegister PCI_INTERRUPT_LINE = { 0x3C, 1, READ_WRITE };
|
---|
354 | PciRegister PCI_INTERRUPT_PIN = { 0x3D, 1, READ_ONLY };
|
---|
355 | PciRegister PCI_MIN_GNT = { 0x3E, 1, READ_ONLY };
|
---|
356 | PciRegister PCI_MAX_LAT = { 0x3F, 1, READ_ONLY };
|
---|
357 | PciRegister PCI_FAB_ID = { 0x40, 1, READ_ONLY };
|
---|
358 | PciRegister PCI_CONFIG_STATUS = { 0x4C, 4, READ_WRITE };
|
---|
359 | PciRegister PCI_CONFIG_SCRATCH = { 0x50, 4, READ_WRITE };
|
---|
360 | PciRegister PCI_AGP_CAP_ID = { 0x54, 4, READ_ONLY };
|
---|
361 | PciRegister PCI_AGP_STATUS = { 0x58, 4, READ_ONLY };
|
---|
362 | PciRegister PCI_AGP_CMD = { 0x5C, 4, READ_WRITE };
|
---|
363 | PciRegister PCI_ACPI_CAP_ID = { 0x60, 4, READ_ONLY };
|
---|
364 | PciRegister PCI_CNTRL_STATUS = { 0x64, 4, READ_WRITE };
|
---|
365 |
|
---|
366 | /* sst1 definitions left in for compatability */
|
---|
367 | PciRegister PCI_SST1_INIT_ENABLE = { 0x40, 4, READ_WRITE };
|
---|
368 | PciRegister PCI_SST1_BUS_SNOOP_0 = { 0x44, 4, READ_WRITE };
|
---|
369 | PciRegister PCI_SST1_BUS_SNOOP_1 = { 0x48, 4, READ_WRITE };
|
---|
370 | PciRegister PCI_SST1_CFG_STATUS = { 0x4C, 4, READ_WRITE };
|
---|
371 |
|
---|
372 | /* PUBLIC FUNCTIONS */
|
---|
373 |
|
---|
374 | FX_ENTRY const char * FX_CALL
|
---|
375 | pciGetErrorString( void )
|
---|
376 | {
|
---|
377 | static char vxdErrString[120];
|
---|
378 | if (pciErrorCode == PCI_ERR_WRONGVXD) {
|
---|
379 | sprintf(vxdErrString, "Expected VXD version V%d.%d, got V%d.%d\n",
|
---|
380 | FX_MAJOR_VER, FX_MINOR_VER,
|
---|
381 | BYTE1(pciVxdVer), BYTE0(pciVxdVer));
|
---|
382 | return vxdErrString;
|
---|
383 | }
|
---|
384 | return pciError[pciErrorCode].string;
|
---|
385 | } /* pciGetErrorString */
|
---|
386 |
|
---|
387 |
|
---|
388 |
|
---|
389 | FX_ENTRY FxU32 FX_CALL
|
---|
390 | pciGetErrorCode( void )
|
---|
391 | {
|
---|
392 | return pciError[pciErrorCode].code;
|
---|
393 | } /* pciGetErrorCode */
|
---|
394 |
|
---|
395 |
|
---|
396 | FX_EXPORT FxBool FX_CSTYLE
|
---|
397 | pciOpenEx( PciHwcCallbacks *cb )
|
---|
398 | {
|
---|
399 | pciHwcCallbacks = *cb;
|
---|
400 | return pciOpen();
|
---|
401 | }
|
---|
402 |
|
---|
403 | // internal routine for scanning the PCI bus the first time during a pciOpen
|
---|
404 | static void
|
---|
405 | sampleVendorID(int deviceNumber, int configMode)
|
---|
406 | {
|
---|
407 | FxU32 regVal;
|
---|
408 |
|
---|
409 | // set the global mode: this routine is used to determine which mode works
|
---|
410 | configMechanism = configMode;
|
---|
411 | regVal = _pciFetchRegister( PCI_VENDOR_ID.regAddress,
|
---|
412 | PCI_VENDOR_ID.sizeInBytes,
|
---|
413 | deviceNumber, configMode );
|
---|
414 | regVal &= 0xFFFF;
|
---|
415 |
|
---|
416 | if ( regVal != 0xFFFF ) {
|
---|
417 | busDetected = FXTRUE;
|
---|
418 | vendorIDs[deviceNumber] = regVal;
|
---|
419 | } else {
|
---|
420 | vendorIDs[deviceNumber] = 0;
|
---|
421 | }
|
---|
422 | }
|
---|
423 |
|
---|
424 | FxBool
|
---|
425 | pciOpenMyOS(void)
|
---|
426 | {
|
---|
427 | int numDevices, deviceNumber;
|
---|
428 |
|
---|
429 | #ifdef __linux__
|
---|
430 | numDevices=getNumDevicesLinux();
|
---|
431 | #endif
|
---|
432 | #ifdef __OS2__
|
---|
433 | numDevices=getNumDevicesOS2();
|
---|
434 | #endif
|
---|
435 | for (deviceNumber=0; deviceNumber < MAX_PCI_DEVICES; deviceNumber++) {
|
---|
436 | if (deviceNumber<numDevices) {
|
---|
437 | busDetected=FXTRUE;
|
---|
438 | configMechanism=1;
|
---|
439 | deviceExists[deviceNumber] = FXTRUE;
|
---|
440 | vendorIDs[deviceNumber] = 0x121a;
|
---|
441 | }
|
---|
442 | else deviceExists[deviceNumber] = FXFALSE;
|
---|
443 | }
|
---|
444 | if (numDevices) {
|
---|
445 | pciLibraryInitialized=FXTRUE;
|
---|
446 | } else {
|
---|
447 | pciLibraryInitialized=FXFALSE;
|
---|
448 | }
|
---|
449 | return pciLibraryInitialized;
|
---|
450 | }
|
---|
451 |
|
---|
452 | FX_EXPORT FxBool FX_CSTYLE
|
---|
453 | pciOpen( void )
|
---|
454 | {
|
---|
455 | int deviceNumber;
|
---|
456 |
|
---|
457 | if ( pciLibraryInitialized ) return FXTRUE;
|
---|
458 |
|
---|
459 | baseAddresses[0] = PCI_BASE_ADDRESS_0;
|
---|
460 | baseAddresses[1] = PCI_BASE_ADDRESS_1;
|
---|
461 | baseAddresses[2] = PCI_IO_BASE_ADDRESS;
|
---|
462 | baseAddresses[3] = PCI_ROM_BASE_ADDRESS;
|
---|
463 |
|
---|
464 | busDetected = FXFALSE;
|
---|
465 | if (pciHwcCallbacks.doHW) {
|
---|
466 | if (!pciPlatformInit() ||
|
---|
467 | (gCurPlatformIO == NULL) ||
|
---|
468 | !pciInitializeDDio()) return FXFALSE;
|
---|
469 | }
|
---|
470 | /*
|
---|
471 | ** Scan All PCI device numbers
|
---|
472 | */
|
---|
473 |
|
---|
474 | #ifdef __linux__
|
---|
475 | if (hasDev3DfxLinux()) return pciOpenMyOS();
|
---|
476 | #endif
|
---|
477 | #ifdef __OS2__
|
---|
478 | if (hasDev3DfxOS2()) return pciOpenMyOS();
|
---|
479 | #endif
|
---|
480 |
|
---|
481 | for ( deviceNumber = 0; deviceNumber < MAX_PCI_DEVICES; deviceNumber++ ) {
|
---|
482 | FxU32 regVal;
|
---|
483 | FxU32 slot;
|
---|
484 | FxU32 bus;
|
---|
485 |
|
---|
486 | sampleVendorID(deviceNumber,1);
|
---|
487 |
|
---|
488 | bus = deviceNumber >> 5;
|
---|
489 | slot = (deviceNumber & 0x1f);
|
---|
490 |
|
---|
491 | pioOutLong( CONFIG_ADDRESS_PORT,
|
---|
492 | _pciCreateConfigAddress( bus, slot, 0, 0x0 ) );
|
---|
493 | regVal = pioInLong( CONFIG_DATA_PORT );
|
---|
494 |
|
---|
495 | if ( ( regVal & 0xFFFF ) != 0xFFFF ) {
|
---|
496 | busDetected = FXTRUE;
|
---|
497 | configMechanism = 1;
|
---|
498 | deviceExists[deviceNumber] = FXTRUE;
|
---|
499 | vendorIDs[deviceNumber] = regVal & 0xffff;
|
---|
500 | } else {
|
---|
501 | deviceExists[deviceNumber] = FXFALSE;
|
---|
502 | }
|
---|
503 |
|
---|
504 | }
|
---|
505 |
|
---|
506 | if ( !busDetected ) {
|
---|
507 | /* Try Configuration Mechanism 2 (only 16 devices) */
|
---|
508 | /* Since Configuration Mech#2 is obsolete this does not
|
---|
509 | support multiple busses */
|
---|
510 |
|
---|
511 | for ( deviceNumber = 0; deviceNumber < 16; deviceNumber++ ) {
|
---|
512 | sampleVendorID(deviceNumber,2);
|
---|
513 | }
|
---|
514 | }
|
---|
515 |
|
---|
516 | if ( busDetected ) {
|
---|
517 | pciLibraryInitialized = FXTRUE;
|
---|
518 | } else {
|
---|
519 | pciErrorCode = PCI_ERR_NO_BUS;
|
---|
520 | return FXFALSE;
|
---|
521 | }
|
---|
522 |
|
---|
523 | return FXTRUE;
|
---|
524 | } /* pciOpen */
|
---|
525 |
|
---|
526 | FX_EXPORT FxBool FX_CSTYLE
|
---|
527 | pciClose( void )
|
---|
528 | {
|
---|
529 | if ( !pciLibraryInitialized ) {
|
---|
530 | pciErrorCode = PCI_ERR_NOTOPEN2;
|
---|
531 | return FXFALSE;
|
---|
532 | }
|
---|
533 | pciLibraryInitialized = FXFALSE;
|
---|
534 |
|
---|
535 | return pciCloseDDio();
|
---|
536 | }
|
---|
537 |
|
---|
538 |
|
---|
539 | FX_EXPORT FxBool FX_CSTYLE
|
---|
540 | pciDeviceExists( FxU32 device_number ) {
|
---|
541 | if ( !pciLibraryInitialized ) {
|
---|
542 | pciErrorCode = PCI_ERR_NOTOPEN;
|
---|
543 | return FXFALSE;
|
---|
544 | }
|
---|
545 | if ( device_number >= MAX_PCI_DEVICES ) return FXFALSE;
|
---|
546 | return vendorIDs[device_number];
|
---|
547 | } /* pciDeviceExists */
|
---|
548 |
|
---|
549 |
|
---|
550 |
|
---|
551 | FX_EXPORT FxBool FX_CSTYLE
|
---|
552 | pciGetConfigData( PciRegister reg, FxU32 device_bus_func_number, FxU32 *data )
|
---|
553 | {
|
---|
554 | int device_number = (device_bus_func_number) & 0xFFF;
|
---|
555 |
|
---|
556 | if ( !pciLibraryInitialized ) {
|
---|
557 | pciErrorCode = PCI_ERR_NOTOPEN3;
|
---|
558 | return FXFALSE;
|
---|
559 | }
|
---|
560 | if ( device_number >= MAX_PCI_DEVICES ) {
|
---|
561 | pciErrorCode = PCI_ERR_OUTOFRANGE;
|
---|
562 | return FXFALSE;
|
---|
563 | }
|
---|
564 |
|
---|
565 | if ( !vendorIDs[device_number] ) {
|
---|
566 | pciErrorCode = PCI_ERR_NODEV;
|
---|
567 | return FXFALSE;
|
---|
568 | }
|
---|
569 |
|
---|
570 | if ( reg.rwFlag == WRITE_ONLY ) {
|
---|
571 | pciErrorCode = PCI_ERR_WRITEONLY;
|
---|
572 | return FXFALSE;
|
---|
573 | }
|
---|
574 |
|
---|
575 | #ifdef __linux__
|
---|
576 | if (hasDev3DfxLinux()) {
|
---|
577 | *data = pciFetchRegisterLinux(reg.regAddress, reg.sizeInBytes,
|
---|
578 | device_bus_func_number);
|
---|
579 | return FXTRUE;
|
---|
580 | }
|
---|
581 | #endif
|
---|
582 | #ifdef __OS2__
|
---|
583 | if (hasDev3DfxOS2()) {
|
---|
584 | *data = pciFetchRegisterOS2(reg.regAddress, reg.sizeInBytes,
|
---|
585 | device_bus_func_number);
|
---|
586 | return FXTRUE;
|
---|
587 | }
|
---|
588 | #endif
|
---|
589 | *data = _pciFetchRegister( reg.regAddress, reg.sizeInBytes,
|
---|
590 | device_bus_func_number, configMechanism );
|
---|
591 |
|
---|
592 | return FXTRUE;
|
---|
593 | } /* pciGetConfigData */
|
---|
594 |
|
---|
595 |
|
---|
596 |
|
---|
597 | FX_EXPORT FxBool FX_CSTYLE
|
---|
598 | pciSetConfigData( PciRegister reg, FxU32 device_bus_func_number, FxU32 *data )
|
---|
599 | {
|
---|
600 | int device_number = (device_bus_func_number) & 0xFFF;
|
---|
601 |
|
---|
602 | if ( !pciLibraryInitialized ) {
|
---|
603 | pciErrorCode = PCI_ERR_NOTOPEN3;
|
---|
604 | return FXFALSE;
|
---|
605 | }
|
---|
606 | if ( device_number >= MAX_PCI_DEVICES ) {
|
---|
607 | pciErrorCode = PCI_ERR_OUTOFRANGE;
|
---|
608 | return FXFALSE;
|
---|
609 | }
|
---|
610 |
|
---|
611 | if ( !vendorIDs[device_number] ) {
|
---|
612 | pciErrorCode = PCI_ERR_NODEV2;
|
---|
613 | return FXFALSE;
|
---|
614 | }
|
---|
615 |
|
---|
616 | if ( reg.rwFlag == READ_ONLY ) {
|
---|
617 | pciErrorCode = PCI_ERR_READONLY;
|
---|
618 | return FXFALSE;
|
---|
619 | }
|
---|
620 |
|
---|
621 | #ifdef __linux__
|
---|
622 | if (hasDev3DfxLinux()) {
|
---|
623 | return pciUpdateRegisterLinux(reg.regAddress, *data, reg.sizeInBytes,
|
---|
624 | device_bus_func_number);
|
---|
625 | }
|
---|
626 | #endif
|
---|
627 | #ifdef __OS2__
|
---|
628 | if (hasDev3DfxOS2()) {
|
---|
629 | return pciUpdateRegisterOS2(reg.regAddress, *data, reg.sizeInBytes,
|
---|
630 | device_bus_func_number);
|
---|
631 | }
|
---|
632 | #endif
|
---|
633 | _pciUpdateRegister( reg.regAddress, *data, reg.sizeInBytes,
|
---|
634 | device_bus_func_number, configMechanism );
|
---|
635 |
|
---|
636 | return FXTRUE;
|
---|
637 | } /* pciSetConfigData */
|
---|
638 |
|
---|
639 |
|
---|
640 | FX_EXPORT FxBool FX_CSTYLE
|
---|
641 | pciFindCardMulti(FxU32 vendorID, FxU32 deviceID,
|
---|
642 | FxU32 *devNum, FxU32 cardNum)
|
---|
643 | {
|
---|
644 | FxU32 deviceNumber;
|
---|
645 |
|
---|
646 | /* 1) open the PCI device and scan it for devices */
|
---|
647 | if (!pciOpen()) return FXFALSE;
|
---|
648 |
|
---|
649 | /* 2) scan the existing devices for a match */
|
---|
650 | for ( deviceNumber = 0; deviceNumber < MAX_PCI_DEVICES; deviceNumber++ ) {
|
---|
651 | if (pciDeviceExists(deviceNumber)) {
|
---|
652 | FxU32
|
---|
653 | vID, dID;
|
---|
654 | FxBool
|
---|
655 | matchP = FXFALSE;
|
---|
656 |
|
---|
657 | pciGetConfigData( PCI_VENDOR_ID, deviceNumber, &vID );
|
---|
658 | pciGetConfigData( PCI_DEVICE_ID, deviceNumber, &dID );
|
---|
659 |
|
---|
660 | if (deviceID == 0xFFFF) /* if special value */
|
---|
661 | dID = deviceID; /* then force a match */
|
---|
662 |
|
---|
663 | matchP = ((vID == vendorID) && (dID == deviceID));
|
---|
664 | if (matchP) {
|
---|
665 | if (cardNum == 0) {
|
---|
666 | *devNum = deviceNumber;
|
---|
667 | return FXTRUE;
|
---|
668 | }
|
---|
669 | }
|
---|
670 |
|
---|
671 | /* single board SLI hack! - jeske */
|
---|
672 | if ((vID == _3DFX_PCI_ID) && (dID == 0x0002)) {
|
---|
673 | pciGetConfigData( PCI_VENDOR_ID, deviceNumber | (1 << 13), &vID);
|
---|
674 | pciGetConfigData( PCI_DEVICE_ID, deviceNumber | (1 << 13), &dID);
|
---|
675 |
|
---|
676 | if ((vID == vendorID) && (dID == deviceID)) {
|
---|
677 | matchP = FXTRUE;
|
---|
678 | if (cardNum == 0) {
|
---|
679 | *devNum = deviceNumber | (1 << 13); /* stuff in function 1 */
|
---|
680 | return FXTRUE;
|
---|
681 | }
|
---|
682 | }
|
---|
683 | }
|
---|
684 | /* end of single board SLI hack! - jeske */
|
---|
685 |
|
---|
686 | if (matchP) cardNum--;
|
---|
687 | }
|
---|
688 | }
|
---|
689 | return FXFALSE; /* didn't find the card, return false */
|
---|
690 | } /* pciFindCardMulti */
|
---|
691 |
|
---|
692 |
|
---|
693 |
|
---|
694 | FX_EXPORT FxBool FX_CSTYLE
|
---|
695 | pciFindCard(FxU32 vendorID, FxU32 deviceID, FxU32 *devNum) {
|
---|
696 | return pciFindCardMulti(vendorID, deviceID, devNum, 0);
|
---|
697 | } /* pciFindCard */
|
---|
698 |
|
---|
699 |
|
---|
700 |
|
---|
701 | /*----------------------------------------------------------------------
|
---|
702 | find and map a PCI card into virtual memory using the following 4
|
---|
703 | steps:
|
---|
704 | 1) open the PCI device and scan it for devices
|
---|
705 | 2) scan the existing devices for a vendorId, deviceId, cardNum match
|
---|
706 | 3) find the current physcial address of the card
|
---|
707 | 4) map the physical memory to virtual memory
|
---|
708 | ----------------------------------------------------------------------*/
|
---|
709 | FX_EXPORT FxU32 * FX_CSTYLE
|
---|
710 | pciMapCardMulti(FxU32 vendorID, FxU32 deviceID,
|
---|
711 | FxI32 length,
|
---|
712 | FxU32 *devNum,
|
---|
713 | FxU32 cardNum, FxU32 addressNum)
|
---|
714 | {
|
---|
715 | FxU32
|
---|
716 | physAddress,
|
---|
717 | virtAddress;
|
---|
718 |
|
---|
719 | /* 1) open the PCI device and scan it for devices
|
---|
720 | * 2) scan the existing devices for a match
|
---|
721 | */
|
---|
722 | if (!pciFindCardMulti(vendorID, deviceID, devNum, cardNum)) return NULL;
|
---|
723 | if (addressNum > MAX_PCI_BASEADDRESSES) return NULL;
|
---|
724 |
|
---|
725 | /* 3) find the current physcial address of the card */
|
---|
726 | pciGetConfigData( baseAddresses[addressNum], *devNum, &physAddress );
|
---|
727 | if (length <= 0) return (FxU32*)length;
|
---|
728 |
|
---|
729 | /* Mask the memory type information bits off.
|
---|
730 | * [0]: Memory type indicator (0 memory/1 i/o)
|
---|
731 | * [12]: Type
|
---|
732 | * 00: 32 bits wide and mapable anywhere
|
---|
733 | * 01: 32 bits wide, mapped < 1meg
|
---|
734 | * 10: 64 bits wide and mappable anywhere
|
---|
735 | * 11: reserved
|
---|
736 | * [3]: Prefetcable
|
---|
737 | */
|
---|
738 | physAddress &= ~0xF;
|
---|
739 |
|
---|
740 | /* 4) have we mapped this device before? */
|
---|
741 | virtAddress = find_mapped_address(*devNum, addressNum);
|
---|
742 | if (virtAddress == 0x00UL) {
|
---|
743 | /* 5) map the physical memory to virtual memory
|
---|
744 | *
|
---|
745 | * NB: Some systems (notably nt) require a bus # in addition to the
|
---|
746 | * physical address in order to map a device. pciMapPhysicalToLinear
|
---|
747 | * has an implicit bus0 which works most of the time, but fails
|
---|
748 | * across pci bridges and to agp devices. Anyway, recall that the
|
---|
749 | * deviceNumber is a tuple w/ the following internal structure:
|
---|
750 | *
|
---|
751 | * device_number[0:4] = slot
|
---|
752 | * device_number[5:12] = bus
|
---|
753 | * device_number[13:15] = function
|
---|
754 | */
|
---|
755 | if (!pciMapPhysicalDeviceToLinear(&virtAddress,
|
---|
756 | ((*devNum >> 5UL) & 0xFFUL), physAddress,
|
---|
757 | (FxU32*) &length)) {
|
---|
758 |
|
---|
759 | virtAddress = 0x00UL;
|
---|
760 | }
|
---|
761 | set_mapped_address(*devNum, addressNum, virtAddress);
|
---|
762 | }
|
---|
763 |
|
---|
764 | return (FxU32*)virtAddress;
|
---|
765 | } /* pciMapCardMulti */
|
---|
766 |
|
---|
767 |
|
---|
768 | FX_EXPORT FxU32 * FX_CSTYLE
|
---|
769 | pciMapCard(FxU32 vendorID, FxU32 deviceID,
|
---|
770 | FxI32 length, FxU32 *devNum, FxU32 addressNum)
|
---|
771 | {
|
---|
772 | return pciMapCardMulti(vendorID, deviceID, length, devNum, 0, addressNum);
|
---|
773 | } /* pciMapCard */
|
---|
774 |
|
---|
775 | FX_EXPORT FxBool FX_CSTYLE
|
---|
776 | pciMapPhysicalToLinear( FxU32 *linear_addr, FxU32 physical_addr,
|
---|
777 | FxU32 *length )
|
---|
778 | {
|
---|
779 | return pciMapPhysicalDeviceToLinear(linear_addr,
|
---|
780 | 0x00UL, physical_addr,
|
---|
781 | length);
|
---|
782 | } /* pciMapPhysicalToLinear */
|
---|
783 |
|
---|
784 | FX_ENTRY FxBool FX_CALL
|
---|
785 | pciMapPhysicalDeviceToLinear(FxU32 *linear_addr,
|
---|
786 | FxU32 busNumber, FxU32 physical_addr,
|
---|
787 | FxU32 *length)
|
---|
788 | {
|
---|
789 | return pciMapLinearDD(busNumber, physical_addr,
|
---|
790 | linear_addr, length);
|
---|
791 | }
|
---|
792 |
|
---|
793 |
|
---|
794 | FX_EXPORT void FX_CSTYLE
|
---|
795 | pciUnmapPhysical( FxU32 linear_addr, FxU32 length )
|
---|
796 | {
|
---|
797 | int i,j;
|
---|
798 |
|
---|
799 | for (i = 0; i < MAX_PCI_DEVICES; i++) {
|
---|
800 | for (j = 0; j < MAX_PCI_BASEADDRESSES; j++) {
|
---|
801 | if(linearAddressMapList[i].addrList[j].addr == linear_addr) {
|
---|
802 | linearAddressMapList[i].addrList[j].addr = 0x00UL;
|
---|
803 | linearAddressMapList[i].addrList[j].mapped = FXFALSE;
|
---|
804 |
|
---|
805 | break;
|
---|
806 | }
|
---|
807 | }
|
---|
808 | }
|
---|
809 |
|
---|
810 | if (i != MAX_PCI_DEVICES) pciUnmapLinearDD(linear_addr, length);
|
---|
811 | }
|
---|
812 |
|
---|
813 | FX_EXPORT FxBool FX_CSTYLE
|
---|
814 | pciSetPassThroughBase(FxU32* baseAddr, FxU32 baseAddrLen)
|
---|
815 | {
|
---|
816 | FxBool retVal;
|
---|
817 |
|
---|
818 | if (pciLibraryInitialized) {
|
---|
819 | retVal = pciSetPassThroughBaseDD(baseAddr, baseAddrLen);
|
---|
820 | } else {
|
---|
821 | pciErrorCode = PCI_ERR_NOTOPEN;
|
---|
822 | retVal = FXFALSE;
|
---|
823 | }
|
---|
824 |
|
---|
825 | return retVal;
|
---|
826 | }
|
---|
827 |
|
---|
828 | FX_EXPORT FxBool FX_CSTYLE
|
---|
829 | pciOutputDebugString(const char* msg)
|
---|
830 | {
|
---|
831 | return pciOutputDebugStringDD(msg);
|
---|
832 | }
|
---|
833 |
|
---|
834 | FX_EXPORT FxBool FX_CSTYLE
|
---|
835 | pciLinearRangeSetPermission(const FxU32 addrBase, const FxU32 addrLen, const FxBool writeableP)
|
---|
836 | {
|
---|
837 | return pciLinearRangeSetPermissionDD(addrBase, addrLen, writeableP);
|
---|
838 | }
|
---|
839 |
|
---|