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