]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/MAI/bios_emulator/scitech/src/pm/common/pcilib.c
* Code cleanup:
[people/ms/u-boot.git] / board / MAI / bios_emulator / scitech / src / pm / common / pcilib.c
1 /****************************************************************************
2 *
3 * SciTech OS Portability Manager Library
4 *
5 * ========================================================================
6 *
7 * The contents of this file are subject to the SciTech MGL Public
8 * License Version 1.0 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.scitechsoft.com/mgl-license.txt
11 *
12 * Software distributed under the License is distributed on an
13 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
16 *
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18 *
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
21 *
22 * ========================================================================
23 *
24 * Language: ANSI C
25 * Environment: Any
26 *
27 * Description: Module for interfacing to the PCI bus and configuration
28 * space registers.
29 *
30 ****************************************************************************/
31
32 #include "pmapi.h"
33 #include "pcilib.h"
34 #if !defined(__WIN32_VXD__) && !defined(__NT_DRIVER__)
35 #include <string.h>
36 #endif
37
38 /*---------------------- Macros and type definitions ----------------------*/
39
40 #pragma pack(1)
41
42 /* Length of the memory mapping for the PCI BIOS */
43
44 #define BIOS_LIMIT (128 * 1024L - 1)
45
46 /* Macros for accessing the PCI BIOS functions from 32-bit protected mode */
47
48 #define BIOS32_SIGNATURE (((ulong)'_' << 0) + ((ulong)'3' << 8) + ((ulong)'2' << 16) + ((ulong)'_' << 24))
49 #define PCI_SIGNATURE (((ulong)'P' << 0) + ((ulong)'C' << 8) + ((ulong)'I' << 16) + ((ulong)' ' << 24))
50 #define PCI_SERVICE (((ulong)'$' << 0) + ((ulong)'P' << 8) + ((ulong)'C' << 16) + ((ulong)'I' << 24))
51 #define PCI_BIOS_PRESENT 0xB101
52 #define FIND_PCI_DEVICE 0xB102
53 #define FIND_PCI_CLASS 0xB103
54 #define GENERATE_SPECIAL 0xB106
55 #define READ_CONFIG_BYTE 0xB108
56 #define READ_CONFIG_WORD 0xB109
57 #define READ_CONFIG_DWORD 0xB10A
58 #define WRITE_CONFIG_BYTE 0xB10B
59 #define WRITE_CONFIG_WORD 0xB10C
60 #define WRITE_CONFIG_DWORD 0xB10D
61 #define GET_IRQ_ROUTING_OPT 0xB10E
62 #define SET_PCI_IRQ 0xB10F
63
64 /* This is the standard structure used to identify the entry point to the
65 * BIOS32 Service Directory, as documented in PCI 2.1 BIOS Specicition.
66 */
67
68 typedef union {
69 struct {
70 ulong signature; /* _32_ */
71 ulong entry; /* 32 bit physical address */
72 uchar revision; /* Revision level, 0 */
73 uchar length; /* Length in paragraphs should be 01 */
74 uchar checksum; /* All bytes must add up to zero */
75 uchar reserved[5]; /* Must be zero */
76 } fields;
77 char chars[16];
78 } PCI_bios32;
79
80 /* Structure for a far pointer to call the PCI BIOS services with */
81
82 typedef struct {
83 ulong address;
84 ushort segment;
85 } PCIBIOS_entry;
86
87 /* Macros to copy a structure that includes dwSize members */
88
89 #define COPY_STRUCTURE(d,s) memcpy(d,s,MIN((s)->dwSize,(d)->dwSize))
90
91 #pragma pack()
92
93 /*--------------------------- Global variables ----------------------------*/
94
95 static uchar *BIOSImage = NULL; /* BIOS image mapping */
96 static int PCIBIOSVersion = -1;/* PCI BIOS version */
97 static PCIBIOS_entry PCIEntry; /* PCI services entry point */
98 static ulong PCIPhysEntry = 0; /* Physical address */
99
100 /*----------------------------- Implementation ----------------------------*/
101
102 /* External assembler helper functions */
103
104 uchar _ASMAPI _BIOS32_service(ulong service,ulong function,ulong *physBase,ulong *length,ulong *serviceOffset,PCIBIOS_entry entry);
105 ushort _ASMAPI _PCIBIOS_isPresent(ulong i_eax,ulong *o_edx,ushort *o_ax,uchar *o_cl,PCIBIOS_entry entry);
106 ulong _ASMAPI _PCIBIOS_service(ulong r_eax,ulong r_ebx,ulong r_edi,ulong r_ecx,PCIBIOS_entry entry);
107 int _ASMAPI _PCIBIOS_getRouting(PCIRoutingOptionsBuffer *buf,PCIBIOS_entry entry);
108 ibool _ASMAPI _PCIBIOS_setIRQ(int busDev,int intPin,int IRQ,PCIBIOS_entry entry);
109 ulong _ASMAPI _PCIBIOS_specialCycle(int bus,ulong data,PCIBIOS_entry entry);
110 ushort _ASMAPI _PCI_getCS(void);
111
112 /****************************************************************************
113 REMARKS:
114 This functions returns the physical address of the PCI BIOS entry point.
115 ****************************************************************************/
116 ulong _ASMAPI PCIBIOS_getEntry(void)
117 { return PCIPhysEntry; }
118
119 /****************************************************************************
120 PARAMETERS:
121 hwType - Place to store the PCI hardware access mechanism flags
122 lastBus - Place to store the index of the last PCI bus in the system
123
124 RETURNS:
125 Version number of the PCI BIOS found.
126
127 REMARKS:
128 This function determines if the PCI BIOS is present in the system, and if
129 so returns the information returned by the PCI BIOS detect function.
130 ****************************************************************************/
131 static int PCIBIOS_detect(
132 uchar *hwType,
133 uchar *lastBus)
134 {
135 ulong signature;
136 ushort stat,version;
137
138 #ifndef __16BIT__
139 PCIBIOS_entry BIOSEntry = {0};
140 uchar *BIOSEnd;
141 PCI_bios32 *BIOSDir;
142 ulong physBase,length,offset;
143
144 /* Bail if we have already detected no BIOS is present */
145 if (PCIBIOSVersion == 0)
146 return 0;
147
148 /* First scan the memory from 0xE0000 to 0xFFFFF looking for the
149 * BIOS32 service directory, so we can determine if we can call it
150 * from 32-bit protected mode.
151 */
152 if (PCIBIOSVersion == -1) {
153 PCIBIOSVersion = 0;
154 BIOSImage = PM_mapPhysicalAddr(0xE0000,BIOS_LIMIT,false);
155 if (!BIOSImage)
156 return 0;
157 BIOSEnd = BIOSImage + 0x20000;
158 for (BIOSDir = (PCI_bios32*)BIOSImage; BIOSDir < (PCI_bios32*)BIOSEnd; BIOSDir++) {
159 uchar sum;
160 int i,length;
161
162 if (BIOSDir->fields.signature != BIOS32_SIGNATURE)
163 continue;
164 length = BIOSDir->fields.length * 16;
165 if (!length)
166 continue;
167 for (sum = i = 0; i < length ; i++)
168 sum += BIOSDir->chars[i];
169 if (sum != 0)
170 continue;
171 BIOSEntry.address = (ulong)BIOSImage + (BIOSDir->fields.entry - 0xE0000);
172 BIOSEntry.segment = _PCI_getCS();
173 break;
174 }
175
176 /* If we found the BIOS32 directory, call it to get the address of the
177 * PCI services.
178 */
179 if (BIOSEntry.address == 0)
180 return 0;
181 if (_BIOS32_service(PCI_SERVICE,0,&physBase,&length,&offset,BIOSEntry) != 0)
182 return 0;
183 PCIPhysEntry = physBase + offset;
184 PCIEntry.address = (ulong)BIOSImage + (PCIPhysEntry - 0xE0000);
185 PCIEntry.segment = _PCI_getCS();
186 }
187 #endif
188 /* We found the BIOS entry, so now do the version check */
189 version = _PCIBIOS_isPresent(PCI_BIOS_PRESENT,&signature,&stat,lastBus,PCIEntry);
190 if (version > 0 && ((stat >> 8) == 0) && signature == PCI_SIGNATURE) {
191 *hwType = stat & 0xFF;
192 return PCIBIOSVersion = version;
193 }
194 return 0;
195 }
196
197 /****************************************************************************
198 PARAMETERS:
199 info - Array of PCIDeviceInfo structures to check against
200 index - Index of the current device to check
201
202 RETURNS:
203 True if the device is a duplicate, false if not.
204
205 REMARKS:
206 This function goes through the list of all devices preceeding the newly
207 found device in the info structure, and checks that the device is not a
208 duplicate of a previous device. Some devices incorrectly enumerate
209 themselves at different function addresses so we check here to exclude
210 those cases.
211 ****************************************************************************/
212 static ibool CheckDuplicate(
213 PCIDeviceInfo *info,
214 PCIDeviceInfo *prev)
215 {
216 /* Ignore devices with a vendor ID of 0 */
217 if (info->VendorID == 0)
218 return true;
219
220 /* NOTE: We only check against the current device on
221 * the bus to ensure that we do not exclude
222 * multiple controllers of the same device ID.
223 */
224 if (info->slot.p.Bus == prev->slot.p.Bus &&
225 info->slot.p.Device == prev->slot.p.Device &&
226 info->DeviceID == prev->DeviceID)
227 return true;
228 return false;
229 }
230
231 /****************************************************************************
232 PARAMETERS:
233 info - Array of PCIDeviceInfo structures to fill in
234 maxDevices - Maximum number of of devices to enumerate into array
235
236 RETURNS:
237 Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.
238
239 REMARKS:
240 Function to enumerate all available devices on the PCI bus into an array
241 of configuration information blocks.
242 ****************************************************************************/
243 static int PCI_enumerateMech1(
244 PCIDeviceInfo info[])
245 {
246 int bus,device,function,i,numFound = 0;
247 ulong *lp,tmp;
248 PCIslot slot = {{0,0,0,0,0,0,1}};
249 PCIDeviceInfo pci,prev = {0};
250
251 /* Try PCI access mechanism 1 */
252 PM_outpb(0xCFB,0x01);
253 tmp = PM_inpd(0xCF8);
254 PM_outpd(0xCF8,slot.i);
255 if ((PM_inpd(0xCF8) == slot.i) && (PM_inpd(0xCFC) != 0xFFFFFFFFUL)) {
256 /* PCI access mechanism 1 - the preferred mechanism */
257 for (bus = 0; bus < 8; bus++) {
258 slot.p.Bus = bus;
259 for (device = 0; device < 32; device++) {
260 slot.p.Device = device;
261 for (function = 0; function < 8; function++) {
262 slot.p.Function = function;
263 slot.p.Register = 0;
264 PM_outpd(0xCF8,slot.i);
265 if (PM_inpd(0xCFC) != 0xFFFFFFFFUL) {
266 memset(&pci,0,sizeof(pci));
267 pci.dwSize = sizeof(pci);
268 pci.mech1 = 1;
269 pci.slot = slot;
270 lp = (ulong*)&(pci.VendorID);
271 for (i = 0; i < NUM_PCI_REG; i++, lp++) {
272 slot.p.Register = i;
273 PM_outpd(0xCF8,slot.i);
274 *lp = PM_inpd(0xCFC);
275 }
276 if (!CheckDuplicate(&pci,&prev)) {
277 if (info)
278 COPY_STRUCTURE(&info[numFound],&pci);
279 ++numFound;
280 }
281 prev = pci;
282 }
283 }
284 }
285 }
286
287 /* Disable PCI config cycle on exit */
288 PM_outpd(0xCF8,0);
289 return numFound;
290 }
291 PM_outpd(0xCF8,tmp);
292
293 /* No hardware access mechanism 1 found */
294 return 0;
295 }
296
297 /****************************************************************************
298 PARAMETERS:
299 info - Array of PCIDeviceInfo structures to fill in
300 maxDevices - Maximum number of of devices to enumerate into array
301
302 RETURNS:
303 Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.
304
305 REMARKS:
306 Function to enumerate all available devices on the PCI bus into an array
307 of configuration information blocks.
308 ****************************************************************************/
309 static int PCI_enumerateMech2(
310 PCIDeviceInfo info[])
311 {
312 int bus,device,function,i,numFound = 0;
313 ushort deviceIO;
314 ulong *lp;
315 PCIslot slot = {{0,0,0,0,0,0,1}};
316 PCIDeviceInfo pci,prev = {0};
317
318 /* Try PCI access mechanism 2 */
319 PM_outpb(0xCFB,0x00);
320 PM_outpb(0xCF8,0x00);
321 PM_outpb(0xCFA,0x00);
322 if (PM_inpb(0xCF8) == 0x00 && PM_inpb(0xCFB) == 0x00) {
323 /* PCI access mechanism 2 - the older mechanism for legacy busses */
324 for (bus = 0; bus < 2; bus++) {
325 slot.p.Bus = bus;
326 PM_outpb(0xCFA,(uchar)bus);
327 for (device = 0; device < 16; device++) {
328 slot.p.Device = device;
329 deviceIO = 0xC000 + (device << 8);
330 for (function = 0; function < 8; function++) {
331 slot.p.Function = function;
332 slot.p.Register = 0;
333 PM_outpb(0xCF8,(uchar)((function << 1) | 0x10));
334 if (PM_inpd(deviceIO) != 0xFFFFFFFFUL) {
335 memset(&pci,0,sizeof(pci));
336 pci.dwSize = sizeof(pci);
337 pci.mech1 = 0;
338 pci.slot = slot;
339 lp = (ulong*)&(pci.VendorID);
340 for (i = 0; i < NUM_PCI_REG; i++, lp++) {
341 slot.p.Register = i;
342 *lp = PM_inpd(deviceIO + (i << 2));
343 }
344 if (!CheckDuplicate(&pci,&prev)) {
345 if (info)
346 COPY_STRUCTURE(&info[numFound],&pci);
347 ++numFound;
348 }
349 prev = pci;
350 }
351 }
352 }
353 }
354
355 /* Disable PCI config cycle on exit */
356 PM_outpb(0xCF8,0);
357 return numFound;
358 }
359
360 /* No hardware access mechanism 2 found */
361 return 0;
362 }
363
364 /****************************************************************************
365 REMARKS:
366 This functions reads a configuration dword via the PCI BIOS.
367 ****************************************************************************/
368 static ulong PCIBIOS_readDWORD(
369 int index,
370 ulong slot)
371 {
372 return (ulong)_PCIBIOS_service(READ_CONFIG_DWORD,slot >> 8,index,0,PCIEntry);
373 }
374
375 /****************************************************************************
376 PARAMETERS:
377 info - Array of PCIDeviceInfo structures to fill in
378 maxDevices - Maximum number of of devices to enumerate into array
379
380 RETURNS:
381 Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.
382
383 REMARKS:
384 Function to enumerate all available devices on the PCI bus into an array
385 of configuration information blocks.
386 ****************************************************************************/
387 static int PCI_enumerateBIOS(
388 PCIDeviceInfo info[])
389 {
390 uchar hwType,lastBus;
391 int bus,device,function,i,numFound = 0;
392 ulong *lp;
393 PCIslot slot = {{0,0,0,0,0,0,1}};
394 PCIDeviceInfo pci,prev = {0};
395
396 if (PCIBIOS_detect(&hwType,&lastBus)) {
397 /* PCI BIOS access - the ultimate fallback */
398 for (bus = 0; bus <= lastBus; bus++) {
399 slot.p.Bus = bus;
400 for (device = 0; device < 32; device++) {
401 slot.p.Device = device;
402 for (function = 0; function < 8; function++) {
403 slot.p.Function = function;
404 if (PCIBIOS_readDWORD(0,slot.i) != 0xFFFFFFFFUL) {
405 memset(&pci,0,sizeof(pci));
406 pci.dwSize = sizeof(pci);
407 pci.mech1 = 2;
408 pci.slot = slot;
409 lp = (ulong*)&(pci.VendorID);
410 for (i = 0; i < NUM_PCI_REG; i++, lp++)
411 *lp = PCIBIOS_readDWORD(i << 2,slot.i);
412 if (!CheckDuplicate(&pci,&prev)) {
413 if (info)
414 COPY_STRUCTURE(&info[numFound],&pci);
415 ++numFound;
416 }
417 prev = pci;
418 }
419 }
420 }
421 }
422 }
423
424 /* Return number of devices found */
425 return numFound;
426 }
427
428 /****************************************************************************
429 PARAMETERS:
430 info - Array of PCIDeviceInfo structures to fill in
431 maxDevices - Maximum number of of devices to enumerate into array
432
433 RETURNS:
434 Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.
435
436 REMARKS:
437 Function to enumerate all available devices on the PCI bus into an array
438 of configuration information blocks.
439 ****************************************************************************/
440 int _ASMAPI PCI_enumerate(
441 PCIDeviceInfo info[])
442 {
443 int numFound;
444
445 /* First try via the direct access mechanisms which are faster if we
446 * have them (nearly always). The BIOS is used as a fallback, and for
447 * stuff we can't do directly.
448 */
449 if ((numFound = PCI_enumerateMech1(info)) == 0) {
450 if ((numFound = PCI_enumerateMech2(info)) == 0) {
451 if ((numFound = PCI_enumerateBIOS(info)) == 0)
452 return 0;
453 }
454 }
455 return numFound;
456 }
457
458 /****************************************************************************
459 PARAMETERS:
460 info - Array of PCIDeviceInfo structures to fill in
461 maxDevices - Maximum number of of devices to enumerate into array
462
463 RETURNS:
464 Number of PCI devices found and enumerated on the PCI bus, 0 if not PCI.
465
466 REMARKS:
467 Function to enumerate all available devices on the PCI bus into an array
468 of configuration information blocks.
469 ****************************************************************************/
470 int _ASMAPI PCI_getNumDevices(void)
471 {
472 return PCI_enumerate(NULL);
473 }
474
475 /****************************************************************************
476 PARAMETERS:
477 bar - Base address to measure
478 pci - PCI device to access
479
480 RETURNS:
481 Size of the PCI base address in bytes
482
483 REMARKS:
484 This function measures the size of the PCI base address register in bytes,
485 by writing all F's to the register, and reading the value back. The size
486 of the base address is determines by the bits that are hardwired to zero's.
487 ****************************************************************************/
488 ulong _ASMAPI PCI_findBARSize(
489 int bar,
490 PCIDeviceInfo *pci)
491 {
492 ulong base,size = 0;
493
494 base = PCI_accessReg(bar,0,PCI_READ_DWORD,pci);
495 if (base && !(base & 0x1)) {
496 /* For some strange reason some devices don't properly decode
497 * their base address registers (Intel PCI/PCI bridges!), and
498 * we read completely bogus values. We check for that here
499 * and clear out those BAR's.
500 *
501 * We check for that here because at least the low 12 bits
502 * of the address range must be zeros, since the page size
503 * on IA32 processors is always 4Kb.
504 */
505 if ((base & 0xFFF) == 0) {
506 PCI_accessReg(bar,0xFFFFFFFF,PCI_WRITE_DWORD,pci);
507 size = PCI_accessReg(bar,0,PCI_READ_DWORD,pci) & ~0xFF;
508 size = ~size+1;
509 PCI_accessReg(bar,base,PCI_WRITE_DWORD,pci);
510 }
511 }
512 pci->slot.p.Register = 0;
513 return size;
514 }
515
516 /****************************************************************************
517 PARAMETERS:
518 index - DWORD index of the register to access
519 value - Value to write to the register for write access
520 func - Function to implement
521
522 RETURNS:
523 The value read from the register for read operations
524
525 REMARKS:
526 The function code are defined as follows
527
528 code - function
529 0 - Read BYTE
530 1 - Read WORD
531 2 - Read DWORD
532 3 - Write BYTE
533 4 - Write WORD
534 5 - Write DWORD
535 ****************************************************************************/
536 ulong _ASMAPI PCI_accessReg(
537 int index,
538 ulong value,
539 int func,
540 PCIDeviceInfo *info)
541 {
542 int iobase;
543
544 if (info->mech1 == 2) {
545 /* Use PCI BIOS access since we dont have direct hardware access */
546 switch (func) {
547 case PCI_READ_BYTE:
548 return (uchar)_PCIBIOS_service(READ_CONFIG_BYTE,info->slot.i >> 8,index,0,PCIEntry);
549 case PCI_READ_WORD:
550 return (ushort)_PCIBIOS_service(READ_CONFIG_WORD,info->slot.i >> 8,index,0,PCIEntry);
551 case PCI_READ_DWORD:
552 return (ulong)_PCIBIOS_service(READ_CONFIG_DWORD,info->slot.i >> 8,index,0,PCIEntry);
553 case PCI_WRITE_BYTE:
554 _PCIBIOS_service(WRITE_CONFIG_BYTE,info->slot.i >> 8,index,value,PCIEntry);
555 break;
556 case PCI_WRITE_WORD:
557 _PCIBIOS_service(WRITE_CONFIG_WORD,info->slot.i >> 8,index,value,PCIEntry);
558 break;
559 case PCI_WRITE_DWORD:
560 _PCIBIOS_service(WRITE_CONFIG_DWORD,info->slot.i >> 8,index,value,PCIEntry);
561 break;
562 }
563 }
564 else {
565 /* Use direct hardware access mechanisms */
566 if (info->mech1) {
567 /* PCI access mechanism 1 */
568 iobase = 0xCFC + (index & 3);
569 info->slot.p.Register = index >> 2;
570 PM_outpd(0xCF8,info->slot.i);
571 }
572 else {
573 /* PCI access mechanism 2 */
574 PM_outpb(0xCF8,(uchar)((info->slot.p.Function << 1) | 0x10));
575 PM_outpb(0xCFA,(uchar)info->slot.p.Bus);
576 iobase = 0xC000 + (info->slot.p.Device << 8) + index;
577 }
578 switch (func) {
579 case PCI_READ_BYTE:
580 case PCI_READ_WORD:
581 case PCI_READ_DWORD: value = PM_inpd(iobase); break;
582 case PCI_WRITE_BYTE: PM_outpb(iobase,(uchar)value); break;
583 case PCI_WRITE_WORD: PM_outpw(iobase,(ushort)value); break;
584 case PCI_WRITE_DWORD: PM_outpd(iobase,(ulong)value); break;
585 }
586 PM_outpd(0xCF8,0);
587 }
588 return value;
589 }
590
591 /****************************************************************************
592 PARAMETERS:
593 numDevices - Number of devices to query info for
594
595 RETURNS:
596 0 on success, -1 on error, number of devices to enumerate if numDevices = 0
597
598 REMARKS:
599 This function reads the PCI routing information. If you pass a value of
600 0 for numDevices, this function will return with the number of devices
601 needed in the routing buffer that will be filled in by the BIOS.
602 ****************************************************************************/
603 ibool _ASMAPI PCI_getIRQRoutingOptions(
604 int numDevices,
605 PCIRouteInfo *buffer)
606 {
607 PCIRoutingOptionsBuffer buf;
608 int ret;
609
610 if (PCIPhysEntry) {
611 buf.BufferSize = numDevices * sizeof(PCIRouteInfo);
612 buf.DataBuffer = buffer;
613 if ((ret = _PCIBIOS_getRouting(&buf,PCIEntry)) == 0x89)
614 return buf.BufferSize / sizeof(PCIRouteInfo);
615 if (ret != 0)
616 return -1;
617 return 0;
618 }
619
620 /* We currently only support this via the PCI BIOS functions */
621 return -1;
622 }
623
624 /****************************************************************************
625 PARAMETERS:
626 info - PCI device information for the specified device
627 intPin - Value to store in the PCI InterruptPin register
628 IRQ - New ISA IRQ to map the PCI interrupt to (0-15)
629
630 RETURNS:
631 True on success, or false if this function failed.
632
633 REMARKS:
634 This function changes the PCI IRQ routing for the specified device to the
635 desired PCI interrupt and the desired ISA bus compatible IRQ. This function
636 may not be supported by the PCI BIOS, in which case this function will
637 fail.
638 ****************************************************************************/
639 ibool _ASMAPI PCI_setHardwareIRQ(
640 PCIDeviceInfo *info,
641 uint intPin,
642 uint IRQ)
643 {
644 if (PCIPhysEntry) {
645 if (_PCIBIOS_setIRQ(info->slot.i >> 8,intPin,IRQ,PCIEntry)) {
646 info->u.type0.InterruptPin = intPin;
647 info->u.type0.InterruptLine = IRQ;
648 return true;
649 }
650 return false;
651 }
652
653 /* We currently only support this via the PCI BIOS functions */
654 return false;
655 }
656
657 /****************************************************************************
658 PARAMETERS:
659 bus - Bus number to generate the special cycle for
660 specialCycleData - Data to send for the special cyle
661
662 REMARKS:
663 This function generates a special cycle on the specified bus using with
664 the specified data.
665 ****************************************************************************/
666 void _ASMAPI PCI_generateSpecialCyle(
667 uint bus,
668 ulong specialCycleData)
669 {
670 if (PCIPhysEntry)
671 _PCIBIOS_specialCycle(bus,specialCycleData,PCIEntry);
672 /* We currently only support this via the PCI BIOS functions */
673 }
674
675 /****************************************************************************
676 PARAMETERS:
677 info - PCI device information block for device to access
678 index - Index of register to start reading from
679 dst - Place to store the values read from configuration space
680 count - Count of bytes to read from configuration space
681
682 REMARKS:
683 This function is used to read a block of PCI configuration space registers
684 from the configuration space into the passed in data block. This function
685 will properly handle reading non-DWORD aligned data from the configuration
686 space correctly.
687 ****************************************************************************/
688 void _ASMAPI PCI_readRegBlock(
689 PCIDeviceInfo *info,
690 int index,
691 void *dst,
692 int count)
693 {
694 uchar *pb;
695 ulong *pd;
696 int i;
697 int startCount = (index & 3);
698 int middleCount = (count - startCount) >> 2;
699 int endCount = count - middleCount * 4 - startCount;
700
701 for (i = 0,pb = dst; i < startCount; i++, index++) {
702 *pb++ = (uchar)PCI_accessReg(index,0,PCI_READ_BYTE,info);
703 }
704 for (i = 0,pd = (ulong*)pb; i < middleCount; i++, index += 4) {
705 *pd++ = (ulong)PCI_accessReg(index,0,PCI_READ_DWORD,info);
706 }
707 for (i = 0,pb = (uchar*)pd; i < endCount; i++, index++) {
708 *pb++ = (uchar)PCI_accessReg(index,0,PCI_READ_BYTE,info);
709 }
710 }
711
712 /****************************************************************************
713 PARAMETERS:
714 info - PCI device information block for device to access
715 index - Index of register to start reading from
716 dst - Place to store the values read from configuration space
717 count - Count of bytes to read from configuration space
718
719 REMARKS:
720 This function is used to write a block of PCI configuration space registers
721 to the configuration space from the passed in data block. This function
722 will properly handle writing non-DWORD aligned data to the configuration
723 space correctly.
724 ****************************************************************************/
725 void _ASMAPI PCI_writeRegBlock(
726 PCIDeviceInfo *info,
727 int index,
728 void *src,
729 int count)
730 {
731 uchar *pb;
732 ulong *pd;
733 int i;
734 int startCount = (index & 3);
735 int middleCount = (count - startCount) >> 2;
736 int endCount = count - middleCount * 4 - startCount;
737
738 for (i = 0,pb = src; i < startCount; i++, index++) {
739 PCI_accessReg(index,*pb++,PCI_WRITE_BYTE,info);
740 }
741 for (i = 0,pd = (ulong*)pb; i < middleCount; i++, index += 4) {
742 PCI_accessReg(index,*pd++,PCI_WRITE_DWORD,info);
743 }
744 for (i = 0,pb = (uchar*)pd; i < endCount; i++, index++) {
745 PCI_accessReg(index,*pb++,PCI_WRITE_BYTE,info);
746 }
747 }