]> git.ipfire.org Git - u-boot.git/blame - board/MAI/bios_emulator/scitech/src/v86bios/pci.c
* Code cleanup:
[u-boot.git] / board / MAI / bios_emulator / scitech / src / v86bios / pci.c
CommitLineData
c7de829c
WD
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
44PciStructPtr PciStruct = NULL;
45PciBusPtr PciBuses = NULL;
46PciStructPtr CurrentPci = NULL;
47PciStructPtr PciList = NULL;
48PciStructPtr BootBios = NULL;
49int pciMaxBus = 0;
50
51static CARD32 PciCfg1Addr;
52
53static void readConfigSpaceCfg1(CARD32 bus, CARD32 dev, CARD32 func,
8bde7f77 54 CARD32 *reg);
c7de829c
WD
55static int checkSlotCfg1(CARD32 bus, CARD32 dev, CARD32 func);
56static int checkSlotCfg2(CARD32 bus, int dev);
57static void readConfigSpaceCfg2(CARD32 bus, int dev, CARD32 *reg);
58static CARD8 interpretConfigSpace(CARD32 *reg, int busidx,
8bde7f77 59 CARD8 dev, CARD8 func);
c7de829c
WD
60static CARD32 findBIOSMap(PciStructPtr pciP, CARD32 *biosSize);
61static 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
70CARD32
71axpPciCfgRead(CARD32 tag)
72{
73 int bus, dfn;
74 CARD32 val = 0xffffffff;
8bde7f77 75
c7de829c
WD
76 bus = PCI_BUS_FROM_TAG(tag);
77 dfn = PCI_DFN_FROM_TAG(tag);
8bde7f77 78
c7de829c
WD
79 syscall(__NR_pciconfig_read, bus, dfn, tag & 0xff, 4, &val);
80 return(val);
81}
82
83void
84axpPciCfgWrite(CARD32 tag, CARD32 val)
85{
86 int bus, dfn;
8bde7f77 87
c7de829c
WD
88 bus = PCI_BUS_FROM_TAG(tag);
89 dfn = PCI_DFN_FROM_TAG(tag);
8bde7f77 90
c7de829c
WD
91 syscall(__NR_pciconfig_write, bus, dfn, tag & 0xff, 4, &val);
92}
93
94static CARD32 (*readPci)(CARD32 reg) = axpPciCfgRead;
95static void (*writePci)(CARD32 reg, CARD32 val) = axpPciCfgWrite;
96#else
97static CARD32 readPciCfg1(CARD32 reg);
98static void writePciCfg1(CARD32 reg, CARD32 val);
99static CARD32 readPciCfg2(CARD32 reg);
100static void writePciCfg2(CARD32 reg, CARD32 val);
101
102static CARD32 (*readPci)(CARD32 reg) = readPciCfg1;
103static 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
113static int numbus;
114static int hostbridges = 1;
115static unsigned long pciMinMemReg = ~0;
116
117
c7de829c
WD
118void
119scan_pci(void)
120{
121 unsigned short configtype;
8bde7f77 122
c7de829c
WD
123 CARD32 reg[64];
124 int busidx;
125 CARD8 cardnum;
126 CARD8 func;
127 int idx;
8bde7f77 128
c7de829c
WD
129 int i;
130 PciStructPtr pci1;
131 PciBusPtr pci_b1,pci_b2;
8bde7f77 132
c7de829c
WD
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)) {
8bde7f77
WD
143 configtype = 2;
144 readPci = readPciCfg2;
145 writePci = writePciCfg2;
146 P_printf("PCI says configuration type 2\n");
c7de829c 147 } else {
8bde7f77
WD
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 }
c7de829c
WD
159 }
160#endif
8bde7f77 161
c7de829c 162 if (configtype == 1) {
8bde7f77
WD
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);
c7de829c 185#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc__) || defined(__ia64__)
8bde7f77 186 /* don't use outl() ;-) */
c7de829c 187#else
8bde7f77 188 outl(PCI_MODE1_ADDRESS_REG, 0);
c7de829c
WD
189#endif
190 } else {
8bde7f77
WD
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);
c7de829c 209 }
8bde7f77
WD
210
211
c7de829c
WD
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);
8bde7f77 215
c7de829c
WD
216 /* link buses */
217 pci_b1 = PciBuses;
218 while (pci_b1) {
8bde7f77
WD
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;
c7de829c
WD
227 }
228 pci1 = PciStruct;
229 while (pci1) {
8bde7f77
WD
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;
c7de829c
WD
238 }
239 if (RESORT) {
8bde7f77
WD
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 }
c7de829c
WD
248 }
249 PciList = CurrentPci = PciStruct;
250}
251
252#ifndef __alpha__
253static CARD32
254readPciCfg1(CARD32 reg)
255{
256 CARD32 val;
8bde7f77 257
c7de829c
WD
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
265static void
266writePciCfg1(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
274static CARD32
275readPciCfg2(CARD32 reg)
276{
277 CARD32 val;
278 CARD8 bus = (reg >> 16) & 0xff;
279 CARD8 dev = (reg >> 11) & 0x1f;
280 CARD8 num = reg & 0xff;
8bde7f77 281
c7de829c
WD
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
290static void
291writePciCfg2(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
305void
306pciVideoDisable(void)
307{
308 /* disable VGA routing on bridges */
309 PciBusPtr pbp = PciBuses;
310 PciStructPtr pcp = PciStruct;
8bde7f77 311
c7de829c 312 while (pbp) {
8bde7f77
WD
313 writePci(pbp->Slot.l | 0x3c, pbp->bctl & ~(CARD32)(8<<16));
314 pbp = pbp->next;
c7de829c
WD
315 }
316 /* disable display devices */
317 while (pcp) {
8bde7f77
WD
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;
c7de829c
WD
321 }
322}
323
324void
325pciVideoRestore(void)
326{
327 /* disable VGA routing on bridges */
328 PciBusPtr pbp = PciBuses;
329 PciStructPtr pcp = PciStruct;
8bde7f77 330
c7de829c 331 while (pbp) {
8bde7f77
WD
332 writePci(pbp->Slot.l | 0x3c, pbp->bctl);
333 pbp = pbp->next;
c7de829c
WD
334 }
335 /* disable display devices */
336 while (pcp) {
8bde7f77
WD
337 writePci(pcp->Slot.l | 0x04, pcp->cmd_st);
338 writePci(pcp->Slot.l | 0x30, pcp->RomBase);
339 pcp = pcp->next;
c7de829c
WD
340 }
341}
342
343void
344EnableCurrent()
345{
346 PciBusPtr pbp;
347 PciStructPtr pcp = CurrentPci;
8bde7f77 348
c7de829c 349 pciVideoDisable();
8bde7f77 350
c7de829c
WD
351 pbp = pcp->pBus;
352 while (pbp) { /* enable bridges */
8bde7f77
WD
353 writePci(pbp->Slot.l | 0x3c, pbp->bctl | (CARD32)(8<<16));
354 pbp = pbp->pBus;
c7de829c
WD
355 }
356 writePci(pcp->Slot.l | 0x04, pcp->cmd_st | (CARD32)3);
357 writePci(pcp->Slot.l | 0x30, pcp->RomBase | (CARD32)1);
358}
359
360CARD8
361PciRead8(int offset, CARD32 Slot)
362{
363 int shift = offset & 0x3;
364 offset = offset & 0xFC;
365 return ((readPci(Slot | offset) >> (shift << 3)) & 0xff);
366}
367
368CARD16
369PciRead16(int offset, CARD32 Slot)
370{
371 int shift = offset & 0x2;
372 offset = offset & 0xFC;
373 return ((readPci(Slot | offset) >> (shift << 3)) & 0xffff);
374}
375
376CARD32
377PciRead32(int offset, CARD32 Slot)
378{
379 offset = offset & 0xFC;
380 return (readPci(Slot | offset));
381}
382
383void
384PciWrite8(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
395void
396PciWrite16(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
407void
408PciWrite32(int offset, CARD32 lg, CARD32 Slot)
409{
410 offset = offset & 0xFC;
411 writePci(Slot | offset, lg);
412}
413
414int
415mapPciRom(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) {
8bde7f77
WD
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 }
c7de829c 436 } else {
8bde7f77
WD
437 RomBase = pciP->RomBase & ~(CARD32)0xFF;
438 if (~RomBase + 1 < biosSize || !RomBase)
439 RomBase = findBIOSMap(pciP, &biosSize);
c7de829c
WD
440 }
441
442 P_printf("RomBase: 0x%lx\n",RomBase);
8bde7f77 443
c7de829c 444 if ((mem_fd = open(MEM_FILE,O_RDONLY))<0) {
8bde7f77
WD
445 perror("opening memory");
446 restoreMem(pciP);
447 return (0);
c7de829c
WD
448 }
449
450 PciWrite32(0x30,RomBase | 1,pciP->Slot.l);
451
452#ifdef __alpha__
453 mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
8bde7f77 454 MAP_SHARED, mem_fd, RomBase | _bus_base());
c7de829c
WD
455#else
456 mem = ptr = (unsigned char *)mmap(0, biosSize, PROT_READ,
8bde7f77 457 MAP_SHARED, mem_fd, RomBase);
c7de829c
WD
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) {
8bde7f77
WD
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;
c7de829c
WD
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) {
8bde7f77
WD
511 memcpy((unsigned char *)V_BIOS, scratch, length);
512 free(scratch);
c7de829c 513 }
8bde7f77 514
c7de829c
WD
515 restoreMem(pciP);
516 return length;
517}
518
519CARD32
520findPci(CARD16 slotBX)
521{
522 CARD32 slot = slotBX << 8;
523
524 if (slot == (CurrentPci->Slot.l & ~PCI_EN))
8bde7f77 525 return (CurrentPci->Slot.l | PCI_EN);
c7de829c
WD
526 else {
527#if !SHOW_ALL_DEV
8bde7f77
WD
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 }
c7de829c 535#else
8bde7f77
WD
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 }
c7de829c
WD
543#endif
544 }
545 return 0;
546}
547
548CARD16
549pciSlotBX(PciStructPtr pPci)
550{
551 return (CARD16)((pPci->Slot.l >> 8) & 0xFFFF);
552}
553
554PciStructPtr
555findPciDevice(CARD16 vendorID, CARD16 deviceID, char n)
556{
557 PciStructPtr pPci = CurrentPci;
558 n++;
559
560 while (pPci) {
8bde7f77
WD
561 if ((pPci->VendorID == vendorID) && (pPci->DeviceID == deviceID)) {
562 if (!(--n)) break;
563 }
c7de829c
WD
564 pPci = pPci->next;
565 }
566 return pPci;
567}
568
569PciStructPtr
570findPciClass(CARD8 intf, CARD8 subClass, CARD16 class, char n)
571{
572 PciStructPtr pPci = CurrentPci;
573 n++;
574
575 while (pPci) {
8bde7f77
WD
576 if ((pPci->Interface == intf) && (pPci->SubClass == subClass)
577 && (pPci->BaseClass == class)) {
578 if (!(--n)) break;
579 }
c7de829c
WD
580 pPci = pPci->next;
581 }
582 return pPci;
583}
584
585static void
586readConfigSpaceCfg1(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__
8bde7f77 594 reg[i] = axpPciCfgRead(config_cmd | i);
c7de829c 595#else
8bde7f77
WD
596 outl(PCI_MODE1_ADDRESS_REG, config_cmd | i);
597 reg[i] = inl(PCI_MODE1_DATA_REG);
c7de829c
WD
598#endif
599
600#ifdef V86BIOS_DEBUG
8bde7f77 601 P_printf("0x%lx\n",reg[i]);
c7de829c
WD
602#endif
603 }
604}
605
606static int
607checkSlotCfg1(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__
8bde7f77 613 reg = axpPciCfgRead(config_cmd);
c7de829c 614#else
8bde7f77
WD
615 outl(PCI_MODE1_ADDRESS_REG, config_cmd);
616 reg = inl(PCI_MODE1_DATA_REG);
c7de829c
WD
617#endif
618 if (reg != 0xFFFFFFFF)
8bde7f77 619 return 1;
c7de829c 620 else
8bde7f77 621 return 0;
c7de829c
WD
622}
623
624static int
625checkSlotCfg2(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)
8bde7f77 635 return 0;
c7de829c 636 if (val == 0xF0F0F0F0)
8bde7f77 637 return 0;
c7de829c
WD
638 return 1;
639}
640
641static void
642readConfigSpaceCfg2(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) {
8bde7f77 649 reg[i] = inl((dev << 8) + i);
c7de829c 650#ifdef V86BIOS_DEBUG
8bde7f77 651 P_printf("0x%lx\n",reg[i]);
c7de829c
WD
652#endif
653 }
654 outb(PCI_MODE2_ENABLE_REG, 0x00);
655}
656
657static CARD8
658interpretConfigSpace(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;
8bde7f77 666
c7de829c 667 config_cmd = PCI_EN | busidx<<16 |
8bde7f77 668 (dev<<11) | (func<<8);
c7de829c
WD
669
670 for (i = 0x10; i < 0x28; i+=4) {
8bde7f77
WD
671 if (IS_MEM32(reg[i]))
672 if ((reg[i] & 0xFFFFFFF0) < pciMinMemReg)
673 pciMinMemReg = (reg[i] & 0xFFFFFFF0);
c7de829c 674#ifdef __alpha__
8bde7f77
WD
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 }
c7de829c
WD
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",
8bde7f77 693 baseclass,subclass,interface,header);
c7de829c 694 if (BRIDGE_CLASS(baseclass)) {
8bde7f77
WD
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 }
c7de829c 713 } else if (VIDEO_CLASS(baseclass,subclass)) {
8bde7f77
WD
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;
c7de829c
WD
730 }
731 if ((func == 0)
8bde7f77
WD
732 && ((header & PCI_MULTIFUNC_DEV) == 0))
733 func = 8;
c7de829c 734 else
8bde7f77 735 func++;
c7de829c
WD
736 return func;
737}
738
739static CARD32 remapMEM_val;
740static int remapMEM_num;
741
742static int /* map it on some other video device */
743remapMem(PciStructPtr pciP, int num, CARD32 size)
744{
745 PciStructPtr pciPtr = PciStruct;
746 int i;
747 CARD32 org;
748 CARD32 val;
749 CARD32 size_n;
8bde7f77 750
c7de829c 751 org = PciRead32(num + 0x10,pciP->Slot.l);
8bde7f77 752
c7de829c 753 while (pciPtr) {
8bde7f77
WD
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;
c7de829c
WD
774 }
775 /* last resort: try to go below lowest PCI mem address */
776 val = ((pciMinMemReg & ~(CARD32)(size - 1)) - size);
777 if (val > 0x7fffffff) {
8bde7f77
WD
778 PciWrite32(num + 0x10,val, pciP->Slot.l);
779 return 1;
c7de829c
WD
780 }
781
782 return 0;
783}
784
785static void
786restoreMem(PciStructPtr pciP)
787{
788 if (remapMEM_val == 0) return;
789 PciWrite32(remapMEM_num + 0x10,remapMEM_val,pciP->Slot.l);
790 return;
791}
792
793static CARD32
794findBIOSMap(PciStructPtr pciP, CARD32 *biosSize)
795{
796 PciStructPtr pciPtr = PciStruct;
797 int i;
798 CARD32 val;
799 CARD32 size;
8bde7f77 800
c7de829c
WD
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) {
8bde7f77
WD
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;
c7de829c 827#ifdef V86_BIOS_DEBUG
8bde7f77 828 P_printf("size: 0x%x\n",size);
c7de829c 829#endif
8bde7f77
WD
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;
c7de829c
WD
843 }
844 remapMEM_val = 0;
845 /* very last resort */
8bde7f77 846 if (pciP->bus == 0 && (pciMinMemReg > *biosSize))
c7de829c 847 return (pciMinMemReg - size) & ~(size - 1);
8bde7f77 848
c7de829c
WD
849 return 0;
850}
851
852int
853cfg1out(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
8bde7f77 865int
c7de829c
WD
866cfg1in(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
878void
879list_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"
8bde7f77
WD
885 " subclass: 0x%4.4x\n",pci->bus,pci->dev,pci->func,
886 pci->VendorID,pci->DeviceID,pci->BaseClass,pci->SubClass);
c7de829c
WD
887 pci = pci->next;
888 }
889}
890
891PciStructPtr
892findPciByIDs(int bus, int dev, int func)
893{
894 PciStructPtr pciP = PciList;
8bde7f77 895
c7de829c
WD
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}