source: trunk/src/opengl/glide/swlibs/pcilib/fxpci.c

Last change on this file was 2887, checked in by sandervl, 26 years ago

Created swlibs dir

File size: 23.3 KB
Line 
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) */
42FxU32 pciVxdVer = 0;
43FxU32 pciErrorCode = PCI_ERR_NOERR;
44FxBool pciLibraryInitialized = FXFALSE;
45PciHwcCallbacks pciHwcCallbacks = { 1 };
46
47const 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 */
54static 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
65typedef struct _PCIErr {
66 FxU32 code;
67 char *string;
68} PCIErr, *PCIErrPtr;
69
70static 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 */
99FX_ENTRY FxU8 FX_CALL
100pioInByte ( 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
111FX_ENTRY FxU16 FX_CALL
112pioInWord ( 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
123FX_ENTRY FxU32 FX_CALL
124pioInLong ( 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
135FX_ENTRY FxBool FX_CALL
136pioOutByte ( 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
145FX_ENTRY FxBool FX_CALL
146pioOutWord ( 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
155FX_ENTRY FxBool FX_CALL
156pioOutLong ( 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
165static PciRegister baseAddresses[MAX_PCI_BASEADDRESSES];
166static FxU32 vendorIDs[MAX_PCI_DEVICES];
167static FxU32 configMechanism = 0;
168static FxBool busDetected = FXFALSE;
169static FxBool deviceExists[MAX_PCI_DEVICES];
170
171/* PRIVATE FUNCTIONS */
172FxU32
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
187FxU16
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
201FX_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
238FX_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
282static FxU32
283find_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
300static void
301set_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
336PciRegister PCI_VENDOR_ID = { 0x0, 2, READ_ONLY };
337PciRegister PCI_DEVICE_ID = { 0x2, 2, READ_ONLY };
338PciRegister PCI_COMMAND = { 0x4, 2, READ_WRITE };
339PciRegister PCI_STATUS = { 0x6, 2, READ_WRITE };
340PciRegister PCI_REVISION_ID = { 0x8, 1, READ_ONLY };
341PciRegister PCI_CLASS_CODE = { 0x9, 3, READ_ONLY };
342PciRegister PCI_CACHE_LINE_SIZE = { 0xC, 1, READ_WRITE };
343PciRegister PCI_LATENCY_TIMER = { 0xD, 1, READ_WRITE };
344PciRegister PCI_HEADER_TYPE = { 0xE, 1, READ_ONLY };
345PciRegister PCI_BIST = { 0xF, 1, READ_WRITE };
346PciRegister PCI_BASE_ADDRESS_0 = { 0x10, 4, READ_WRITE };
347PciRegister PCI_BASE_ADDRESS_1 = { 0x14, 4, READ_WRITE };
348PciRegister PCI_IO_BASE_ADDRESS = { 0x18, 4, READ_WRITE };
349PciRegister PCI_SUBVENDOR_ID = { 0x2C, 4, READ_ONLY };
350PciRegister PCI_SUBSYSTEM_ID = { 0x2E, 4, READ_ONLY };
351PciRegister PCI_ROM_BASE_ADDRESS= { 0x30, 4, READ_WRITE };
352PciRegister PCI_CAP_PTR = { 0x34, 4, READ_WRITE };
353PciRegister PCI_INTERRUPT_LINE = { 0x3C, 1, READ_WRITE };
354PciRegister PCI_INTERRUPT_PIN = { 0x3D, 1, READ_ONLY };
355PciRegister PCI_MIN_GNT = { 0x3E, 1, READ_ONLY };
356PciRegister PCI_MAX_LAT = { 0x3F, 1, READ_ONLY };
357PciRegister PCI_FAB_ID = { 0x40, 1, READ_ONLY };
358PciRegister PCI_CONFIG_STATUS = { 0x4C, 4, READ_WRITE };
359PciRegister PCI_CONFIG_SCRATCH = { 0x50, 4, READ_WRITE };
360PciRegister PCI_AGP_CAP_ID = { 0x54, 4, READ_ONLY };
361PciRegister PCI_AGP_STATUS = { 0x58, 4, READ_ONLY };
362PciRegister PCI_AGP_CMD = { 0x5C, 4, READ_WRITE };
363PciRegister PCI_ACPI_CAP_ID = { 0x60, 4, READ_ONLY };
364PciRegister PCI_CNTRL_STATUS = { 0x64, 4, READ_WRITE };
365
366/* sst1 definitions left in for compatability */
367PciRegister PCI_SST1_INIT_ENABLE = { 0x40, 4, READ_WRITE };
368PciRegister PCI_SST1_BUS_SNOOP_0 = { 0x44, 4, READ_WRITE };
369PciRegister PCI_SST1_BUS_SNOOP_1 = { 0x48, 4, READ_WRITE };
370PciRegister PCI_SST1_CFG_STATUS = { 0x4C, 4, READ_WRITE };
371
372/* PUBLIC FUNCTIONS */
373
374FX_ENTRY const char * FX_CALL
375pciGetErrorString( 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
389FX_ENTRY FxU32 FX_CALL
390pciGetErrorCode( void )
391{
392 return pciError[pciErrorCode].code;
393} /* pciGetErrorCode */
394
395
396FX_EXPORT FxBool FX_CSTYLE
397pciOpenEx( 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
404static void
405sampleVendorID(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
424FxBool
425pciOpenMyOS(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
452FX_EXPORT FxBool FX_CSTYLE
453pciOpen( 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
526FX_EXPORT FxBool FX_CSTYLE
527pciClose( void )
528{
529 if ( !pciLibraryInitialized ) {
530 pciErrorCode = PCI_ERR_NOTOPEN2;
531 return FXFALSE;
532 }
533 pciLibraryInitialized = FXFALSE;
534
535 return pciCloseDDio();
536}
537
538
539FX_EXPORT FxBool FX_CSTYLE
540pciDeviceExists( 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
551FX_EXPORT FxBool FX_CSTYLE
552pciGetConfigData( 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
597FX_EXPORT FxBool FX_CSTYLE
598pciSetConfigData( 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
640FX_EXPORT FxBool FX_CSTYLE
641pciFindCardMulti(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
694FX_EXPORT FxBool FX_CSTYLE
695pciFindCard(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 ----------------------------------------------------------------------*/
709FX_EXPORT FxU32 * FX_CSTYLE
710pciMapCardMulti(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
768FX_EXPORT FxU32 * FX_CSTYLE
769pciMapCard(FxU32 vendorID, FxU32 deviceID,
770 FxI32 length, FxU32 *devNum, FxU32 addressNum)
771{
772 return pciMapCardMulti(vendorID, deviceID, length, devNum, 0, addressNum);
773} /* pciMapCard */
774
775FX_EXPORT FxBool FX_CSTYLE
776pciMapPhysicalToLinear( FxU32 *linear_addr, FxU32 physical_addr,
777 FxU32 *length )
778{
779 return pciMapPhysicalDeviceToLinear(linear_addr,
780 0x00UL, physical_addr,
781 length);
782} /* pciMapPhysicalToLinear */
783
784FX_ENTRY FxBool FX_CALL
785pciMapPhysicalDeviceToLinear(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
794FX_EXPORT void FX_CSTYLE
795pciUnmapPhysical( 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
813FX_EXPORT FxBool FX_CSTYLE
814pciSetPassThroughBase(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
828FX_EXPORT FxBool FX_CSTYLE
829pciOutputDebugString(const char* msg)
830{
831 return pciOutputDebugStringDD(msg);
832}
833
834FX_EXPORT FxBool FX_CSTYLE
835pciLinearRangeSetPermission(const FxU32 addrBase, const FxU32 addrLen, const FxBool writeableP)
836{
837 return pciLinearRangeSetPermissionDD(addrBase, addrLen, writeableP);
838}
839
Note: See TracBrowser for help on using the repository browser.