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