]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/hwinfo/src/int10/i10_pci.c
Signierten GPG-Schluessel importiert.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / int10 / i10_pci.c
1 /*
2 * Copyright 1999 Egbert Eich
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the authors not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. The authors makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
13 *
14 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <malloc.h>
25 #include <stdio.h>
26 #include <sys/mman.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <string.h>
30 #if defined (__alpha__) || defined (__ia64__)
31 #include <sys/io.h>
32 #endif
33 #include "AsmMacros.h"
34
35 #include "pci.h"
36
37 #define RESORT 1
38 #define FIX_ROM 0
39
40 /*
41 * I'm rather simple mindend - therefore I do a poor man's
42 * pci scan without all the fancy stuff that is done in
43 * scanpci. However that's all we need.
44 */
45
46 PciStructPtr PciStruct = NULL;
47 PciBusPtr PciBuses = NULL;
48 PciStructPtr CurrentPci = NULL;
49 PciStructPtr PciList = NULL;
50 int pciMaxBus = 0;
51
52 static CARD32 PciCfg1Addr;
53
54 static void readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func,
55 CARD32 *reg);
56 static int checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func);
57 static int checkSlotCfg2(CARD32 bus, int dev);
58 static void readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg);
59 static CARD8 interpretConfigSpace(CARD32 *reg, int busidx,
60 CARD8 dev, CARD8 func);
61 static CARD32 findBIOSMap(PciStructPtr pciP, CARD32 *biosSize);
62 static void restoreMem(PciStructPtr pciP);
63
64
65 #ifdef __alpha__
66 #define PCI_BUS_FROM_TAG(tag) (((tag) & 0x00ff0000) >> 16)
67 #define PCI_DFN_FROM_TAG(tag) (((tag) & 0x0000ff00) >> 8)
68
69 #include <asm/unistd.h>
70
71 CARD32
72 axpPciCfgRead(CARD32 tag)
73 {
74 int bus, dfn;
75 CARD32 val = 0xffffffff;
76
77 bus = PCI_BUS_FROM_TAG(tag);
78 dfn = PCI_DFN_FROM_TAG(tag);
79
80 syscall(__NR_pciconfig_read, bus, dfn, tag & 0xff, 4, &val);
81 return(val);
82 }
83
84 void
85 axpPciCfgWrite(CARD32 tag, CARD32 val)
86 {
87 int bus, dfn;
88
89 bus = PCI_BUS_FROM_TAG(tag);
90 dfn = PCI_DFN_FROM_TAG(tag);
91
92 syscall(__NR_pciconfig_write, bus, dfn, tag & 0xff, 4, &val);
93 }
94
95 static CARD32 (*readPci)(CARD32 reg) = axpPciCfgRead;
96 static void (*writePci)(CARD32 reg, CARD32 val) = axpPciCfgWrite;
97 #else
98 static CARD32 readPciCfg1(CARD32 reg);
99 static void writePciCfg1(CARD32 reg, CARD32 val);
100 #ifndef __ia64__
101 static CARD32 readPciCfg2(CARD32 reg);
102 static void writePciCfg2(CARD32 reg, CARD32 val);
103 #endif
104
105 static CARD32 (*readPci)(CARD32 reg) = readPciCfg1;
106 static void (*writePci)(CARD32 reg, CARD32 val) = writePciCfg1;
107 #endif
108
109 #if defined(__alpha__) || defined(__sparc__)
110 #define PCI_EN 0x00000000
111 #else
112 #define PCI_EN 0x80000000
113 #endif
114
115
116 static int numbus;
117 static int hostbridges = 1;
118 static unsigned long pciMinMemReg = ~0;
119
120
121
122 void
123 scan_pci(int pci_cfg_method)
124 {
125 unsigned short configtype;
126
127 CARD32 reg[64];
128 int busidx;
129 CARD8 cardnum;
130 CARD8 func;
131 int idx;
132
133 PciStructPtr pci1;
134 PciBusPtr pci_b1,pci_b2;
135
136 if(pci_cfg_method) {
137 configtype = pci_cfg_method;
138 }
139 else {
140 #if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__)
141 configtype = 1;
142 #else
143 CARD8 tmp1, tmp2;
144 CARD32 tmp32_1, tmp32_2;
145 outb(PCI_MODE2_ENABLE_REG, 0x00);
146 outb(PCI_MODE2_FORWARD_REG, 0x00);
147 tmp1 = inb(PCI_MODE2_ENABLE_REG);
148 tmp2 = inb(PCI_MODE2_FORWARD_REG);
149 if ((tmp1 == 0x00) && (tmp2 == 0x00)) {
150 configtype = 2;
151 readPci = readPciCfg2;
152 writePci = writePciCfg2;
153 } else {
154 tmp32_1 = inl(PCI_MODE1_ADDRESS_REG);
155 outl(PCI_MODE1_ADDRESS_REG, PCI_EN);
156 tmp32_2 = inl(PCI_MODE1_ADDRESS_REG);
157 outl(PCI_MODE1_ADDRESS_REG, tmp32_1);
158 if (tmp32_2 == PCI_EN) {
159 configtype = 1;
160 } else {
161 return;
162 }
163 }
164 #endif
165 }
166
167 if (configtype == 1) {
168 busidx = 0;
169 numbus = 1;
170 idx = 0;
171 do {
172 for (cardnum = 0; cardnum < MAX_DEV_PER_VENDOR_CFG1; cardnum++) {
173 func = 0;
174 do {
175 /* loop over the different functions, if present */
176 if (!checkSlotCfg1(busidx,cardnum,func)) {
177 if (!func)
178 break;
179 else {
180 func++;
181 continue;
182 }
183 }
184 readConfigSpaceCfg1(busidx,cardnum,func,reg);
185
186 func = interpretConfigSpace(reg,busidx,
187 cardnum,func);
188
189 if (++idx >= MAX_PCI_DEVICES)
190 break;
191 } while (func < 8);
192 if (idx >= MAX_PCI_DEVICES)
193 break;
194 }
195 if (idx >= MAX_PCI_DEVICES)
196 break;
197 } while (++busidx < PCI_MAXBUS);
198 #if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__)
199 /* don't use outl() ;-) */
200 #else
201 outl(PCI_MODE1_ADDRESS_REG, 0);
202 #endif
203 } else {
204 int slot;
205
206 busidx = 0;
207 numbus = 1;
208 idx = 0;
209 do {
210 for (slot=0xc0; slot<0xd0; slot++) {
211 if (!checkSlotCfg2(busidx,slot))
212 break;
213 readConfigSpaceCfg2(busidx,slot,reg);
214
215 interpretConfigSpace(reg,busidx,
216 slot,0);
217 if (++idx >= MAX_PCI_DEVICES)
218 break;
219 }
220 if (idx >= MAX_PCI_DEVICES)
221 break;
222 } while (++busidx < PCI_MAXBUS);
223 }
224
225
226 pciMaxBus = numbus - 1;
227
228 /* link buses */
229 pci_b1 = PciBuses;
230 while (pci_b1) {
231 pci_b2 = PciBuses;
232 pci_b1->pBus = NULL;
233 while (pci_b2) {
234 if (pci_b1->primary == pci_b2->secondary)
235 pci_b1->pBus = pci_b2;
236 pci_b2 = pci_b2->next;
237 }
238 pci_b1 = pci_b1->next;
239 }
240 pci1 = PciStruct;
241 while (pci1) {
242 pci_b2 = PciBuses;
243 pci1->pBus = NULL;
244 while (pci_b2) {
245 if (pci1->bus == pci_b2->secondary)
246 pci1->pBus = pci_b2;
247 pci_b2 = pci_b2->next;
248 }
249 pci1 = pci1->next;
250 }
251 if (RESORT) {
252 PciStructPtr tmp = PciStruct, tmp1;
253 PciStruct = NULL;
254 while (tmp) {
255 tmp1 = tmp->next;
256 tmp->next = PciStruct;
257 PciStruct = tmp;
258 tmp = tmp1;
259 }
260 }
261 PciList = CurrentPci = PciStruct;
262 }
263
264 #ifndef __alpha__
265 static CARD32
266 readPciCfg1(CARD32 reg)
267 {
268 CARD32 val;
269
270 outl(PCI_MODE1_ADDRESS_REG, reg);
271 val = inl(PCI_MODE1_DATA_REG);
272 outl(PCI_MODE1_ADDRESS_REG, 0);
273 return val;
274 }
275
276 static void
277 writePciCfg1(CARD32 reg, CARD32 val)
278 {
279 outl(PCI_MODE1_ADDRESS_REG, reg);
280 outl(PCI_MODE1_DATA_REG,val);
281 outl(PCI_MODE1_ADDRESS_REG, 0);
282 }
283
284 #ifndef __ia64__
285 static CARD32
286 readPciCfg2(CARD32 reg)
287 {
288 CARD32 val;
289 CARD8 bus = (reg >> 16) & 0xff;
290 CARD8 dev = (reg >> 11) & 0x1f;
291 CARD8 num = reg & 0xff;
292
293 outb(PCI_MODE2_ENABLE_REG, 0xF1);
294 outb(PCI_MODE2_FORWARD_REG, bus);
295 val = inl((dev << 8) + num);
296 outb(PCI_MODE2_ENABLE_REG, 0x00);
297 return val;
298 }
299
300 static void
301 writePciCfg2(CARD32 reg, CARD32 val)
302 {
303 CARD8 bus = (reg >> 16) & 0xff;
304 CARD8 dev = (reg >> 11) & 0x1f;
305 CARD8 num = reg & 0xff;
306
307 outb(PCI_MODE2_ENABLE_REG, 0xF1);
308 outb(PCI_MODE2_FORWARD_REG, bus);
309 outl((dev << 8) + num,val);
310 outb(PCI_MODE2_ENABLE_REG, 0x00);
311 }
312 #endif
313 #endif
314
315 void
316 pciVideoDisable(void)
317 {
318 /* disable VGA routing on bridges */
319 PciBusPtr pbp = PciBuses;
320 PciStructPtr pcp = PciStruct;
321
322 while (pbp) {
323 writePci(pbp->Slot.l | 0x3c, pbp->bctl & ~(CARD32)(8<<16));
324 pbp = pbp->next;
325 }
326 /* disable display devices */
327 while (pcp) {
328 writePci(pcp->Slot.l | 0x04, pcp->cmd_st & ~(CARD32)3);
329 writePci(pcp->Slot.l | 0x30, pcp->RomBase & ~(CARD32)1);
330 pcp = pcp->next;
331 }
332 }
333
334 void
335 pciVideoRestore(void)
336 {
337 /* disable VGA routing on bridges */
338 PciBusPtr pbp = PciBuses;
339 PciStructPtr pcp = PciStruct;
340
341 while (pbp) {
342 writePci(pbp->Slot.l | 0x3c, pbp->bctl);
343 pbp = pbp->next;
344 }
345 /* disable display devices */
346 while (pcp) {
347 writePci(pcp->Slot.l | 0x04, pcp->cmd_st);
348 writePci(pcp->Slot.l | 0x30, pcp->RomBase);
349 pcp = pcp->next;
350 }
351 }
352
353 void
354 EnableCurrent()
355 {
356 PciBusPtr pbp;
357 PciStructPtr pcp = CurrentPci;
358
359 pciVideoDisable();
360
361 pbp = pcp->pBus;
362 while (pbp) { /* enable bridges */
363 writePci(pbp->Slot.l | 0x3c, pbp->bctl | (CARD32)(8<<16));
364 pbp = pbp->pBus;
365 }
366 writePci(pcp->Slot.l | 0x04, pcp->cmd_st | (CARD32)3);
367 writePci(pcp->Slot.l | 0x30, pcp->RomBase | (CARD32)1);
368 }
369
370 CARD8
371 PciRead8(int offset, CARD32 Slot)
372 {
373 int shift = offset & 0x3;
374 offset = offset & 0xFC;
375 return ((readPci(Slot | offset) >> (shift << 3)) & 0xff);
376 }
377
378 CARD16
379 PciRead16(int offset, CARD32 Slot)
380 {
381 int shift = offset & 0x2;
382 offset = offset & 0xFC;
383 return ((readPci(Slot | offset) >> (shift << 3)) & 0xffff);
384 }
385
386 CARD32
387 PciRead32(int offset, CARD32 Slot)
388 {
389 offset = offset & 0xFC;
390 return (readPci(Slot | offset));
391 }
392
393 void
394 PciWrite8(int offset, CARD8 byte, CARD32 Slot)
395 {
396 CARD32 val;
397 int shift = offset & 0x3;
398 offset = offset & 0xFC;
399 val = readPci(Slot | offset);
400 val &= ~(CARD32)(0xff << (shift << 3));
401 val |= byte << (shift << 3);
402 writePci(Slot | offset, val);
403 }
404
405 void
406 PciWrite16(int offset, CARD16 word, CARD32 Slot)
407 {
408 CARD32 val;
409 int shift = offset & 0x2;
410 offset = offset & 0xFC;
411 val = readPci(Slot | offset);
412 val &= ~(CARD32)(0xffff << (shift << 3));
413 val |= word << (shift << 3);
414 writePci(Slot | offset, val);
415 }
416
417 void
418 PciWrite32(int offset, CARD32 lg, CARD32 Slot)
419 {
420 offset = offset & 0xFC;
421 writePci(Slot | offset, lg);
422 }
423
424 int
425 mapPciRom(PciStructPtr pciP)
426 {
427 unsigned long RomBase = 0;
428 int mem_fd;
429 unsigned char *mem, *ptr;
430 unsigned char *scratch = NULL;
431 int length = 0;
432 CARD32 biosSize = 0x1000000;
433 CARD32 enablePci = 0; /* to keep gcc happy */
434
435 if (!pciP)
436 pciP = CurrentPci;
437
438 if (FIX_ROM) {
439 RomBase = findBIOSMap(pciP, &biosSize);
440 if (!RomBase) {
441 RomBase = pciP->RomBase & ~(CARD32)0xFF;
442 }
443 } else {
444 RomBase = pciP->RomBase & ~(CARD32)0xFF;
445 if (~RomBase + 1 < biosSize || !RomBase)
446 RomBase = findBIOSMap(pciP, &biosSize);
447 }
448
449 if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
450 perror("opening memory");
451 restoreMem(pciP);
452 return (0);
453 }
454
455 PciWrite32(0x30,RomBase | 1,pciP->Slot.l);
456
457 #ifdef __alpha__
458 mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
459 MAP_SHARED, mem_fd, RomBase | _bus_base());
460 #else
461 mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
462 MAP_SHARED, mem_fd, RomBase);
463 #endif
464 if (pciP != CurrentPci) {
465 enablePci = PciRead32(0x4,pciP->Slot.l);
466 PciWrite32(0x4,enablePci | 0x2,pciP->Slot.l);
467 }
468
469 while ( *ptr == 0x55 && *(ptr+1) == 0xAA) {
470 unsigned short data_off = *(ptr+0x18) | (*(ptr+0x19)<< 8);
471 unsigned char *data = ptr + data_off;
472 unsigned char type;
473 int i;
474
475 if (*data!='P' || *(data+1)!='C' || *(data+2)!='I' || *(data+3)!='R') {
476 break;
477 }
478 type = *(data + 0x14);
479
480 if (type != 0) { /* not PC-AT image: find next one */
481 unsigned int image_length;
482 unsigned char indicator = *(data + 0x15);
483 if (indicator & 0x80) /* last image */
484 break;
485 image_length = (*(data + 0x10)
486 | (*(data + 0x11) << 8)) << 9;
487 ptr = ptr + image_length;
488 continue;
489 }
490 /* OK, we have a PC Image */
491 length = (*(ptr + 2) << 9);
492 scratch = (unsigned char *)malloc(length);
493 /* don't use memcpy() here: Reading from bus! */
494 for (i=0;i<length;i++)
495 *(scratch + i)=*(ptr + i);
496 break;
497 }
498
499 if (pciP != CurrentPci)
500 PciWrite32(0x4,enablePci,pciP->Slot.l);
501
502 /* unmap/close/disable PCI bios mem */
503 munmap(mem, biosSize);
504 close(mem_fd);
505 /* disable and restore mapping */
506 writePci(pciP->Slot.l | 0x30, pciP->RomBase & ~(CARD32)1);
507
508 if (scratch && length) {
509 memcpy((unsigned char *)V_BIOS, scratch, length);
510 free(scratch);
511 }
512
513 restoreMem(pciP);
514 return length;
515 }
516
517 CARD32
518 findPci(CARD16 slotBX)
519 {
520 CARD32 slot = slotBX << 8;
521
522 if (slot == (CurrentPci->Slot.l & ~PCI_EN))
523 return (CurrentPci->Slot.l | PCI_EN);
524 else {
525 #if !SHOW_ALL_DEV
526 PciBusPtr pBus = CurrentPci->pBus;
527 while (pBus) {
528 if (slot == (pBus->Slot.l & ~PCI_EN))
529 return pBus->Slot.l | PCI_EN;
530 pBus = pBus->next;
531 }
532 #else
533 PciStructPtr pPci = PciStruct;
534 while (pPci) {
535 if (slot == (pPci->Slot.l & ~PCI_EN))
536 return pPci->Slot.l | PCI_EN;
537 pPci = pPci->next;
538 }
539 #endif
540 }
541 return 0;
542 }
543
544 CARD16
545 pciSlotBX(PciStructPtr pPci)
546 {
547 return (CARD16)((pPci->Slot.l >> 8) & 0xFFFF);
548 }
549
550 PciStructPtr
551 findPciDevice(CARD16 vendorID, CARD16 deviceID, char n)
552 {
553 PciStructPtr pPci = CurrentPci;
554 n++;
555
556 while (pPci) {
557 if ((pPci->VendorID == vendorID) && (pPci->DeviceID == deviceID)) {
558 if (!(--n)) break;
559 }
560 pPci = pPci->next;
561 }
562 return pPci;
563 }
564
565 PciStructPtr
566 findPciClass(CARD8 intf, CARD8 subClass, CARD16 class, char n)
567 {
568 PciStructPtr pPci = CurrentPci;
569 n++;
570
571 while (pPci) {
572 if ((pPci->Interface == intf) && (pPci->SubClass == subClass)
573 && (pPci->BaseClass == class)) {
574 if (!(--n)) break;
575 }
576 pPci = pPci->next;
577 }
578 return pPci;
579 }
580
581 static void
582 readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func, CARD32 *reg)
583 {
584 CARD32 config_cmd = PCI_EN | (bus<<16) |
585 (dev<<11) | (func<<8);
586 int i;
587
588 for (i = 0; i<64;i+=4) {
589 #ifdef __alpha__
590 reg[i] = axpPciCfgRead(config_cmd | i);
591 #else
592 outl(PCI_MODE1_ADDRESS_REG, config_cmd | i);
593 reg[i] = inl(PCI_MODE1_DATA_REG);
594 #endif
595
596 }
597 }
598
599 static int
600 checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func)
601 {
602 CARD32 config_cmd = PCI_EN | (bus<<16) |
603 (dev<<11) | (func<<8);
604 CARD32 reg;
605 #ifdef __alpha__
606 reg = axpPciCfgRead(config_cmd);
607 #else
608 outl(PCI_MODE1_ADDRESS_REG, config_cmd);
609 reg = inl(PCI_MODE1_DATA_REG);
610 #endif
611 if (reg != 0xFFFFFFFF)
612 return 1;
613 else
614 return 0;
615 }
616
617 static int
618 checkSlotCfg2(CARD32 bus, int dev)
619 {
620 CARD32 val;
621
622 outb(PCI_MODE2_ENABLE_REG, 0xF1);
623 outb(PCI_MODE2_FORWARD_REG, bus);
624 val = inl(dev << 8);
625 outb(PCI_MODE2_FORWARD_REG, 0x00);
626 outb(PCI_MODE2_ENABLE_REG, 0x00);
627 if (val == 0xFFFFFFFF)
628 return 0;
629 if (val == 0xF0F0F0F0)
630 return 0;
631 return 1;
632 }
633
634 static void
635 readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg)
636 {
637 int i;
638
639 outb(PCI_MODE2_ENABLE_REG, 0xF1);
640 outb(PCI_MODE2_FORWARD_REG, bus);
641 for (i = 0; i<64;i+=4) {
642 reg[i] = inl((dev << 8) + i);
643 }
644 outb(PCI_MODE2_ENABLE_REG, 0x00);
645 }
646
647 static CARD8
648 interpretConfigSpace(CARD32 *reg, int busidx, CARD8 dev, CARD8 func)
649 {
650 CARD32 config_cmd;
651 CARD16 vendor, device;
652 CARD8 baseclass, subclass;
653 CARD8 primary, secondary;
654 CARD8 header, interface;
655 int i;
656
657 config_cmd = PCI_EN | busidx<<16 |
658 (dev<<11) | (func<<8);
659
660 for (i = 0x10; i < 0x28; i+=4) {
661 if (IS_MEM32(reg[i]))
662 if ((reg[i] & 0xFFFFFFF0) < pciMinMemReg)
663 pciMinMemReg = (reg[i] & 0xFFFFFFF0);
664 #ifdef __alpha__
665 if (IS_MEM64(reg[i])) {
666 unsigned long addr = reg[i] |
667 (unsigned long)(reg[i+4]) << 32;
668 if ((addr & ~0xfL) < pciMinMemReg)
669 pciMinMemReg = (addr & ~0xfL);
670 i+=4;
671 }
672 #endif
673 }
674 vendor = reg[0] & 0xFFFF;
675 device = reg[0] >> 16;
676 baseclass = reg[8] >> 24;
677 subclass = (reg[8] >> 16) & 0xFF;
678 interface = (reg[8] >> 8) & 0xFF;
679
680 header = (reg[0x0c] >> 16) & 0xff;
681 if (BRIDGE_CLASS(baseclass)) {
682 if (BRIDGE_PCI_CLASS(subclass)) {
683 PciBusPtr pbp = malloc(sizeof(PciBusRec));
684 primary = reg[0x18] & 0xFF;
685 secondary = (reg[0x18] >> 8) & 0xFF;
686 pbp->bctl = reg[0x3c];
687 pbp->primary = primary;
688 pbp->secondary = secondary;
689 pbp->Slot.l = config_cmd;
690 pbp->next = PciBuses;
691 PciBuses = pbp;
692 numbus++;
693 } else if (BRIDGE_HOST_CLASS(subclass)
694 && (hostbridges++ > 1)) {
695 numbus++;
696 }
697 } else if (VIDEO_CLASS(baseclass,subclass)) {
698 PciStructPtr pcp = malloc(sizeof(PciStructRec));
699 pcp->RomBase = reg[0x30];
700 pcp->cmd_st = reg[4];
701 pcp->active = (reg[4] & 0x03) == 3 ? 1 : 0;
702 pcp->VendorID = vendor;
703 pcp->DeviceID = device;
704 pcp->Interface = interface;
705 pcp->BaseClass = baseclass;
706 pcp->SubClass = subclass;
707 pcp->Slot.l = config_cmd;
708 pcp->bus = busidx;
709 pcp->dev = dev;
710 pcp->func = func;
711 pcp->next = PciStruct;
712 PciStruct = pcp;
713 }
714 if ((func == 0)
715 && ((header & PCI_MULTIFUNC_DEV) == 0))
716 func = 8;
717 else
718 func++;
719 return func;
720 }
721
722 static CARD32 remapMEM_val;
723 static int remapMEM_num;
724
725 static int /* map it on some other video device */
726 remapMem(PciStructPtr pciP, int num, CARD32 size)
727 {
728 PciStructPtr pciPtr = PciStruct;
729 int i;
730 CARD32 org;
731 CARD32 val;
732 CARD32 size_n;
733
734 org = PciRead32(num + 0x10,pciP->Slot.l);
735
736 while (pciPtr) {
737 for (i = 0; i < 20; i=i+4) {
738
739 val = PciRead32(i + 0x10,pciPtr->Slot.l);
740 /* don't map it on itself */
741 if ((org & 0xfffffff0) == (val & 0xfffffff0))
742 continue;
743 if (val && !(val & 1))
744 PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l);
745 else
746 continue;
747 size_n = PciRead32(i + 0x10,pciPtr->Slot.l);
748 PciWrite32(i + 0x10,val,pciPtr->Slot.l);
749 size_n = ~(CARD32)(size_n & 0xfffffff0) + 1;
750
751 if (size_n >= size) {
752 PciWrite32(num + 0x10,val,pciP->Slot.l);
753 return 1;
754 }
755 }
756 pciPtr = pciPtr->next;
757 }
758 /* last resort: try to go below lowest PCI mem address */
759 val = ((pciMinMemReg & ~(CARD32)(size - 1)) - size);
760 if (val > 0x7fffffff) {
761 PciWrite32(num + 0x10,val, pciP->Slot.l);
762 return 1;
763 }
764
765 return 0;
766 }
767
768 static void
769 restoreMem(PciStructPtr pciP)
770 {
771 if (remapMEM_val == 0) return;
772 PciWrite32(remapMEM_num + 0x10,remapMEM_val,pciP->Slot.l);
773 return;
774 }
775
776 static CARD32
777 findBIOSMap(PciStructPtr pciP, CARD32 *biosSize)
778 {
779 PciStructPtr pciPtr = PciStruct;
780 int i;
781 CARD32 val;
782 CARD32 size = 4*1024; /* should be fixed: size seems _really_ to be undefined below */
783
784 PciWrite32(0x30,0xffffffff,pciP->Slot.l);
785 *biosSize = PciRead32(0x30,pciP->Slot.l);
786 PciWrite32(0x30,pciP->RomBase,pciP->Slot.l);
787 *biosSize = ~(*biosSize & 0xFFFFFF00) + 1;
788 if (*biosSize > (1024 * 1024 * 16)) {
789 *biosSize = 1024 * 1024 * 16;
790 }
791 while (pciPtr) {
792 if (pciPtr->bus != pciP->bus) {
793 pciPtr = pciPtr->next;
794 continue;
795 }
796 for (i = 0; i < 20; i=i+4) {
797
798 val = PciRead32(i + 0x10,pciPtr->Slot.l);
799 if (!(val & 1))
800
801 PciWrite32(i + 0x10,0xffffffff,pciPtr->Slot.l);
802 else
803 continue;
804 size = PciRead32(i + 0x10,pciPtr->Slot.l);
805 PciWrite32(i + 0x10,val,pciPtr->Slot.l);
806 size = ~(CARD32)(size & 0xFFFFFFF0) + 1;
807 if (size >= *biosSize) {
808 if (pciP == pciPtr) { /* if same device remap ram*/
809 if (!(remapMem(pciP,i,size)))
810 continue;
811 remapMEM_val = val;
812 remapMEM_num = i;
813 } else {
814 remapMEM_val = 0;
815 }
816 return val & 0xFFFFFF00;
817 }
818 }
819 pciPtr = pciPtr->next;
820 }
821 remapMEM_val = 0;
822 /* very last resort */
823 if (pciP->bus == 0 && (pciMinMemReg > *biosSize))
824 return (pciMinMemReg - size) & ~(size - 1);
825
826 return 0;
827 }
828
829 int
830 cfg1out(CARD16 addr, CARD32 val)
831 {
832 if (addr == 0xCF8) {
833 PciCfg1Addr = val;
834 return 1;
835 } else if (addr == 0xCFC) {
836 writePci(PciCfg1Addr, val);
837 return 1;
838 }
839 return 0;
840 }
841
842 int
843 cfg1in(CARD16 addr, CARD32 *val)
844 {
845 if (addr == 0xCF8) {
846 *val = PciCfg1Addr;
847 return 1;
848 } else if (addr == 0xCFC) {
849 *val = readPci(PciCfg1Addr);
850 return 1;
851 }
852 return 0;
853 }
854
855 PciStructPtr
856 findPciByIDs(int bus, int dev, int func)
857 {
858 PciStructPtr pciP = PciList;
859
860 while (pciP) {
861 if (pciP->bus == (unsigned) bus && pciP->dev == (unsigned) dev && pciP->func == (unsigned) func)
862 return pciP;
863 pciP = pciP->next;
864 }
865 return NULL;
866 }