2 Copyright © 2004-2016, The AROS Development Team. All rights reserved.
9 #include <exec/types.h>
12 #include <utility/tagitem.h>
13 #include <proto/exec.h>
14 #include <proto/utility.h>
15 #include <proto/oop.h>
21 #include <aros/debug.h>
23 /*****************************************************************************************
26 aoHidd_PCIDevice_Owner
35 Returns name of current device's owner or NULL if the device is
39 This attribute is provided for diagnostics utilities like PCITool.
40 There is no need to check current owner before attempting to own
41 the device. moHidd_PCIDevice_Obtain method performs this check
42 and owns the device atomically.
52 *****************************************************************************************/
53 static IPTR
hasExtendedConfig(OOP_Class
*cl
, OOP_Object
*o
)
55 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
57 return dev
->extendedconfig
;
60 static void setLong(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
, ULONG value
)
62 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
64 HIDD_PCIDriver_WriteConfigLong(dev
->driver
, (OOP_Object
*)dev
, dev
->bus
, dev
->dev
, dev
->sub
, reg
, value
);
67 static void setWord(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
, UWORD value
)
69 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
71 HIDD_PCIDriver_WriteConfigWord(dev
->driver
, (OOP_Object
*)dev
, dev
->bus
, dev
->dev
, dev
->sub
, reg
, value
);
74 static void setByte(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
, UBYTE value
)
76 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
78 HIDD_PCIDriver_WriteConfigByte(dev
->driver
, (OOP_Object
*)dev
, dev
->bus
, dev
->dev
, dev
->sub
, reg
, value
);
81 static ULONG
getLong(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
)
83 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
85 return HIDD_PCIDriver_ReadConfigLong(dev
->driver
, (OOP_Object
*)dev
, dev
->bus
, dev
->dev
, dev
->sub
, reg
);
88 static UWORD
getWord(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
)
90 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
92 return HIDD_PCIDriver_ReadConfigWord(dev
->driver
, (OOP_Object
*)dev
, dev
->bus
, dev
->dev
, dev
->sub
, reg
);
95 static UBYTE
getByte(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
)
97 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
99 return HIDD_PCIDriver_ReadConfigByte(dev
->driver
, (OOP_Object
*)dev
, dev
->bus
, dev
->dev
, dev
->sub
, reg
);
102 /* Returns offset of capability area in config area or 0 if capability is not present */
103 static UBYTE
findCapabilityOffset(OOP_Class
* cl
, OOP_Object
*o
, UBYTE capability
)
105 UWORD where
= 0x34; /* First cap list entry */
108 /* Check if capabilities present at all */
109 if ((getWord(cl
, o
, PCICS_STATUS
) & PCISTF_CAPABILITIES
) != PCISTF_CAPABILITIES
)
112 /* Iterate over capabilities */
115 where
= getByte(cl
, o
, where
);
121 capid
= getByte(cl
, o
, where
);
126 if (capid
== capability
) return (UBYTE
)where
;
128 where
+= 1; /* next cap */
134 /* Returns offset of PCI Express extended capability or 0 if capability is not present */
135 static UWORD
findExpressExtendedCapabilityOffset(OOP_Class
* cl
, OOP_Object
*o
, UWORD capability
)
137 UWORD where
= 0x100; /* First PCI Express extended cap list entry */
140 while((where
> 0xff) && (where
< 0xfff))
142 caphdr
= getLong(cl
, o
, where
);
143 if( (caphdr
== -1) || (caphdr
== 0)) return 0;
145 if ((caphdr
& 0xffff) == capability
) return (UWORD
)where
;
147 where
= (caphdr
>>20)&~3;
153 BOOL
PCIDev__Hidd_PCIDevice__HasExtendedConfig(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_HasExtendedConfig
*msg
)
155 return hasExtendedConfig(cl
, o
);
158 UBYTE
PCIDev__Hidd_PCIDevice__ReadConfigByte(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_ReadConfigByte
*msg
)
160 return getByte(cl
, o
, msg
->reg
);
163 UWORD
PCIDev__Hidd_PCIDevice__ReadConfigWord(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_ReadConfigWord
*msg
)
165 return getWord(cl
, o
, msg
->reg
);
168 ULONG
PCIDev__Hidd_PCIDevice__ReadConfigLong(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_ReadConfigLong
*msg
)
170 return getLong(cl
, o
, msg
->reg
);
173 VOID
PCIDev__Hidd_PCIDevice__WriteConfigByte(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_WriteConfigByte
*msg
)
175 setByte(cl
, o
, msg
->reg
, msg
->val
);
178 VOID
PCIDev__Hidd_PCIDevice__WriteConfigWord(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_WriteConfigWord
*msg
)
180 setWord(cl
, o
, msg
->reg
, msg
->val
);
183 VOID
PCIDev__Hidd_PCIDevice__WriteConfigLong(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_WriteConfigLong
*msg
)
185 setLong(cl
, o
, msg
->reg
, msg
->val
);
188 /*****************************************************************************************
191 moHidd_PCIDevice_AddInterrupt
194 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDevice_AddInterrupt *Msg);
196 OOP_Object *HIDD_PCIDriver_AddInterrupt(OOP_Object *obj, OOP_Object *device,
197 struct Interrupt *interrupt);
203 Add interrupt handler for the device.
206 obj - Pointer to device object.
207 interrupt - Interrupt structure to add.
210 TRUE it successful or FALSE on failure.
219 moHidd_PCIDevice_RemoveInterrupt
223 *****************************************************************************************/
225 BOOL
PCIDev__Hidd_PCIDevice__AddInterrupt(OOP_Class
*cl
, OOP_Object
*o
,
226 struct pHidd_PCIDevice_AddInterrupt
*msg
)
228 tDeviceData
*dev
= OOP_INST_DATA(cl
, o
);
230 return HIDD_PCIDriver_AddInterrupt(dev
->driver
, o
, msg
->interrupt
);
233 /*****************************************************************************************
236 moHidd_PCIDevice_RemoveInterrupt
239 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDevice_RemoveInterrupt *Msg);
241 OOP_Object *HIDD_PCIDevice_RemoveInterrupt(OOP_Object *obj, OOP_Object *device,
242 struct Interrupt *interrupt);
248 Remove interrupt handler from the device.
251 obj - Pointer to the device object.
252 interrupt - Interrupt structure to remove.
264 moHidd_PCIDevice_AddInterrupt
268 *****************************************************************************************/
270 VOID
PCIDev__Hidd_PCIDevice__RemoveInterrupt(OOP_Class
*cl
, OOP_Object
*o
,
271 struct pHidd_PCIDevice_RemoveInterrupt
*msg
)
273 tDeviceData
*dev
= OOP_INST_DATA(cl
, o
);
275 return HIDD_PCIDriver_RemoveInterrupt(dev
->driver
, o
, msg
->interrupt
);
278 /*****************************************************************************************
281 moHidd_PCIDevice_Obtain
284 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDevice_Obtain *Msg);
286 OOP_Object *HIDD_PCIDevice_Obtain(OOP_Object *obj, CONST_STRPTR owner);
292 Lock the device for exclusive use.
295 obj - Pointer to the device object.
296 owner - A string identifying the owner.
299 NULL on success or string identifying current owner.
308 moHidd_PCIDevice_Release
312 *****************************************************************************************/
314 CONST_STRPTR
PCIDev__Hidd_PCIDevice__Obtain(OOP_Class
*cl
, OOP_Object
*o
,
315 struct pHidd_PCIDevice_Obtain
*msg
)
317 tDeviceData
*dev
= OOP_INST_DATA(cl
, o
);
318 CONST_STRPTR current
= NULL
;
321 * FIXME: Actually this is just atomic compare and swap.
322 * I believe it should be impemented in assembler.
323 * Ouch, on Amiga such operations are unsafe, at least
324 * in CHIP memory. Too bad...
326 ObtainSemaphore(&dev
->ownerLock
);
328 /* While we are using semaphore, owner name is embedded in its node */
329 if (dev
->ownerLock
.ss_Link
.ln_Name
)
330 current
= dev
->ownerLock
.ss_Link
.ln_Name
;
332 dev
->ownerLock
.ss_Link
.ln_Name
= (STRPTR
)msg
->owner
;
334 ReleaseSemaphore(&dev
->ownerLock
);
339 /*****************************************************************************************
342 moHidd_PCIDevice_Release
345 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDevice_Release *Msg);
347 OOP_Object *HIDD_PCIDevice_Release(OOP_Object *obj);
353 Release ownership of the device.
356 obj - Pointer to the device object.
362 You should call this function only on devices owned by you. Doing
363 this on someone else's devices will not do any good things.
370 moHidd_PCIDevice_Obtain
374 *****************************************************************************************/
376 VOID
PCIDev__Hidd_PCIDevice__Release(OOP_Class
*cl
, OOP_Object
*o
,
377 struct pHidd_PCIDevice_Release
*msg
)
379 tDeviceData
*dev
= OOP_INST_DATA(cl
, o
);
381 dev
->ownerLock
.ss_Link
.ln_Name
= NULL
;
385 PCIDevice::New method is invoked by base pci class. It passes to the device
386 class information about the driver this class should use and location of
387 created device on the PCI bus handled by given driver.
389 OOP_Object
*PCIDev__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
393 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
396 struct TagItem
*tag
, *tags
;
397 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
, o
);
398 OOP_Object
*driver
= NULL
;
400 InitSemaphore(&dev
->ownerLock
);
402 tags
=(struct TagItem
*)msg
->attrList
;
405 Get all information passed by pci class calling OOP_NewObject()
407 while((tag
= NextTagItem(&tags
)))
411 if (IS_PCIDEV_ATTR(tag
->ti_Tag
, idx
))
415 case aoHidd_PCIDevice_Driver
:
416 dev
->driver
= (OOP_Object
*)tag
->ti_Data
;
417 driver
= dev
->driver
;
420 case aoHidd_PCIDevice_Bus
:
421 dev
->bus
= tag
->ti_Data
;
424 case aoHidd_PCIDevice_Dev
:
425 dev
->dev
= tag
->ti_Data
;
428 case aoHidd_PCIDevice_Sub
:
429 dev
->sub
= tag
->ti_Data
;
432 case aoHidd_PCIDevice_ExtendedConfig
:
433 dev
->extendedconfig
= tag
->ti_Data
;
440 If driver is passed (*HAS TO* be passed) acquire some unchangeable
441 information regarding given device
448 Get the header type in order to determine whether it is a
451 ht
= getByte(cl
, o
, PCICS_HEADERTYPE
) & PCIHT_MASK
;
453 if (ht
== PCIHT_BRIDGE
)
456 dev
->subbus
= getByte(cl
, o
, PCIBR_SUBBUS
);
459 /* Get all constant ID's */
460 dev
->VendorID
= getWord(cl
, o
, PCICS_VENDOR
);
461 dev
->ProductID
= getWord(cl
, o
, PCICS_PRODUCT
);
463 dev
->RevisionID
= getByte(cl
, o
, PCICS_REVISION
);
464 dev
->Interface
= getByte(cl
, o
, PCICS_PROGIF
);
465 dev
->SubClass
= getByte(cl
, o
, PCICS_SUBCLASS
);
466 dev
->Class
= getByte(cl
, o
, PCICS_CLASS
);
468 dev
->SubsysVID
= getWord(cl
, o
, PCICS_SUBVENDOR
);
469 dev
->SubsystemID
= getWord(cl
, o
, PCICS_SUBSYSTEM
);
471 dev
->IRQLine
= getByte(cl
, o
, PCICS_INT_PIN
);
475 dev
->INTLine
= getByte(cl
, o
, PCICS_INT_LINE
);
477 else dev
->INTLine
= 0;
479 dev
->HeaderType
= ht
;
481 getPCIClassDesc(dev
->Class
, dev
->SubClass
, dev
->Interface
,
482 &dev
->strClass
, &dev
->strSubClass
, &dev
->strInterface
);
484 /* Satisfy BUG watchers ;) */
485 D(bug("[PCIDevice] %02x.%02x.%x = %04.4lx:%04.4lx (%s %s %s)\n",
486 dev
->bus
, dev
->dev
, dev
->sub
,
487 dev
->VendorID
, dev
->ProductID
,
488 dev
->strClass
, dev
->strSubClass
, dev
->strInterface
));
489 D(bug("[PCIDevice] > IRQ %u INT %u\n", dev
->IRQLine
, dev
->INTLine
));
491 // print out a warning to the user in case the interrupt line is not assigned by BIOS
492 if (dev
->INTLine
== 255 && !dev
->isBridge
)
493 bug("[PCIDevice] WARNING: Interrupt line is not assigned! Device may freeze or malfunction at use!\n");
495 /* Read two first base addresses */
496 for (i
= 0; i
< 2; i
++)
498 dev
->BaseReg
[i
].addr
= getLong(cl
, o
, PCICS_BAR0
+ (i
<< 2));
499 dev
->BaseReg
[i
].size
= sizePCIBaseReg(driver
, PSD(cl
), dev
, dev
->bus
,
500 dev
->dev
, dev
->sub
, i
);
503 /* Address and size of ROM */
504 dev
->RomBase
= getLong(cl
, o
, PCICS_EXPROM_BASE
);
505 dev
->RomSize
= sizePCIBaseReg(driver
, PSD(cl
), dev
, dev
->bus
,
506 dev
->dev
, dev
->sub
, (PCICS_EXPROM_BASE
- PCICS_BAR0
) >> 2);
509 Bridges specify only first two base addresses. If not bridge,
514 for (i
= 2; i
< 6; i
++)
516 dev
->BaseReg
[i
].addr
= getLong(cl
, o
, PCICS_BAR0
+ (i
<< 2));
517 dev
->BaseReg
[i
].size
= sizePCIBaseReg(driver
, PSD(cl
), dev
, dev
->bus
,
518 dev
->dev
, dev
->sub
, i
);
528 PCIDevice::Get method splitted into few parts in order to make switch'es shorter.
531 static void dispatch_generic(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
534 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
536 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
540 case aoHidd_PCIDevice_Driver
:
541 *msg
->storage
= (IPTR
)dev
->driver
;
544 case aoHidd_PCIDevice_Bus
:
545 *msg
->storage
= (IPTR
)dev
->bus
;
548 case aoHidd_PCIDevice_Dev
:
549 *msg
->storage
= (IPTR
)dev
->dev
;
552 case aoHidd_PCIDevice_Sub
:
553 *msg
->storage
= (IPTR
)dev
->sub
;
556 case aoHidd_PCIDevice_VendorID
:
557 *msg
->storage
= (IPTR
)dev
->VendorID
;
560 case aoHidd_PCIDevice_ProductID
:
561 *msg
->storage
= (IPTR
)dev
->ProductID
;
564 case aoHidd_PCIDevice_RevisionID
:
565 *msg
->storage
= (IPTR
)dev
->RevisionID
;
568 case aoHidd_PCIDevice_Interface
:
569 *msg
->storage
= (IPTR
)dev
->Interface
;
572 case aoHidd_PCIDevice_Class
:
573 *msg
->storage
= (IPTR
)dev
->Class
;
576 case aoHidd_PCIDevice_SubClass
:
577 *msg
->storage
= (IPTR
)dev
->SubClass
;
580 case aoHidd_PCIDevice_SubsystemVendorID
:
581 *msg
->storage
= (IPTR
)dev
->SubsysVID
;
584 case aoHidd_PCIDevice_SubsystemID
:
585 *msg
->storage
= (IPTR
)dev
->SubsystemID
;
588 case aoHidd_PCIDevice_IRQLine
:
589 *msg
->storage
= (IPTR
)dev
->IRQLine
;
592 case aoHidd_PCIDevice_RomBase
:
593 *msg
->storage
= (IPTR
)dev
->RomBase
;
596 case aoHidd_PCIDevice_RomSize
:
597 *msg
->storage
= (IPTR
)dev
->RomSize
;
600 case aoHidd_PCIDevice_ExtendedConfig
:
601 *msg
->storage
= (IPTR
)dev
->extendedconfig
;
604 case aoHidd_PCIDevice_ConfigSize
:
605 if(dev
->extendedconfig
) {
606 *msg
->storage
= 4096;
615 static void dispatch_base(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
618 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
620 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
625 case aoHidd_PCIDevice_Base0
: id
= 0; break;
626 case aoHidd_PCIDevice_Base1
: id
= 1; break;
627 case aoHidd_PCIDevice_Base2
: id
= 2; break;
628 case aoHidd_PCIDevice_Base3
: id
= 3; break;
629 case aoHidd_PCIDevice_Base4
: id
= 4; break;
630 case aoHidd_PCIDevice_Base5
: id
= 5; break;
633 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
634 if (dev
->isBridge
&& id
>= 2) { *msg
->storage
= 0; return; }
636 *msg
->storage
= (IPTR
)dev
->BaseReg
[id
].addr
;
637 if ((dev
->BaseReg
[id
].addr
& PCIBAR_MASK_TYPE
)==PCIBAR_TYPE_IO
)
640 *msg
->storage
&= PCIBAR_MASK_IO
;
641 OOP_GetAttr(dev
->driver
, aHidd_PCIDriver_IOBase
, &IOBase
);
642 *msg
->storage
+= IOBase
;
646 *msg
->storage
&= PCIBAR_MASK_MEM
;
650 static void dispatch_type(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
653 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
655 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
660 case aoHidd_PCIDevice_Type0
: id
= 0; break;
661 case aoHidd_PCIDevice_Type1
: id
= 1; break;
662 case aoHidd_PCIDevice_Type2
: id
= 2; break;
663 case aoHidd_PCIDevice_Type3
: id
= 3; break;
664 case aoHidd_PCIDevice_Type4
: id
= 4; break;
665 case aoHidd_PCIDevice_Type5
: id
= 5; break;
668 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
669 if (dev
->isBridge
&& id
>= 2) { *msg
->storage
= 0; return; }
671 *msg
->storage
= (IPTR
)dev
->BaseReg
[id
].addr
;
672 if ((dev
->BaseReg
[id
].addr
& PCIBAR_MASK_TYPE
)==PCIBAR_TYPE_IO
)
674 *msg
->storage
&= ~PCIBAR_MASK_IO
;
678 *msg
->storage
&= ~PCIBAR_MASK_MEM
;
682 static void dispatch_size(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
685 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
687 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
692 case aoHidd_PCIDevice_Size0
: id
= 0; break;
693 case aoHidd_PCIDevice_Size1
: id
= 1; break;
694 case aoHidd_PCIDevice_Size2
: id
= 2; break;
695 case aoHidd_PCIDevice_Size3
: id
= 3; break;
696 case aoHidd_PCIDevice_Size4
: id
= 4; break;
697 case aoHidd_PCIDevice_Size5
: id
= 5; break;
700 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
701 if (dev
->isBridge
&& id
>= 2) { *msg
->storage
= 0; return;}
703 *msg
->storage
= (IPTR
)dev
->BaseReg
[id
].size
;
706 static void dispatch_pci2pcibridge(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
709 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
713 /* If device is not a PCI-PCI bridge, do nothing */
714 if (!dev
->isBridge
) { *msg
->storage
= 0; return; }
716 control
= getWord(cl
, o
, PCIBR_CONTROL
);
718 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
722 case aoHidd_PCIDevice_isBridge
:
723 *msg
->storage
= dev
->isBridge
;
726 case aoHidd_PCIDevice_SubBus
:
727 *msg
->storage
= dev
->subbus
;
730 case aoHidd_PCIDevice_MemoryBase
:
731 *msg
->storage
= getWord(cl
, o
, PCIBR_MEMBASE
) << 16;
734 case aoHidd_PCIDevice_MemoryLimit
:
735 *msg
->storage
= getWord(cl
, o
, PCIBR_MEMLIMIT
) << 16;
738 case aoHidd_PCIDevice_PrefetchableBase
:
739 *msg
->storage
= getWord(cl
, o
, PCIBR_PREFETCHBASE
) << 16;
742 case aoHidd_PCIDevice_PrefetchableLimit
:
743 *msg
->storage
= getWord(cl
, o
, PCIBR_PREFETCHLIMIT
) << 16;
746 case aoHidd_PCIDevice_IOBase
:
747 *msg
->storage
= getByte(cl
, o
, PCIBR_IOBASE
) << 8;
750 case aoHidd_PCIDevice_IOLimit
:
751 *msg
->storage
= getByte(cl
, o
, PCIBR_IOLIMIT
) << 8;
754 case aoHidd_PCIDevice_ISAEnable
:
755 *msg
->storage
= (control
& PCICTRLF_ISAENABLE
) == PCICTRLF_ISAENABLE
;
758 case aoHidd_PCIDevice_VGAEnable
:
759 *msg
->storage
= (control
& PCICTRLF_VGAENABLE
) == PCICTRLF_VGAENABLE
;
764 static void dispatch_capability(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
767 UBYTE capability
= 0;
768 //tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
770 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
774 case aoHidd_PCIDevice_CapabilityPowerManagement
: capability
= PCICAP_POWER_MANAGEMENT
;break;
775 case aoHidd_PCIDevice_CapabilityAGP
: capability
= PCICAP_AGP
;break;
776 case aoHidd_PCIDevice_CapabilityVitalProductData
: capability
= PCICAP_VITAL_PRODUCT_DATA
;break;
777 case aoHidd_PCIDevice_CapabilitySlotID
: capability
= PCICAP_SLOT_ID
;break;
778 case aoHidd_PCIDevice_CapabilityMSI
: capability
= PCICAP_MSI
;break;
779 case aoHidd_PCIDevice_CapabilityCPCIHotSwap
: capability
= PCICAP_CPCI_HOT_SWAP
;break;
780 case aoHidd_PCIDevice_CapabilityPCIX
: capability
= PCICAP_PCIX
;break;
781 case aoHidd_PCIDevice_CapabilityHyperTransport
: capability
= PCICAP_HYPER_TRANSPORT
;break;
782 case aoHidd_PCIDevice_CapabilityVendorSpecific
: capability
= PCICAP_VENDOR_SPECIFIC
;break;
783 case aoHidd_PCIDevice_CapabilityDebugPort
: capability
= PCICAP_DEBUG_PORT
;break;
784 case aoHidd_PCIDevice_CapabilityCPCICRC
: capability
= PCICAP_CPCI_CR
;break;
785 case aoHidd_PCIDevice_CapabilityHotPlugController
: capability
= PCICAP_HOT_PLUG_CONTROLLER
;break;
786 case aoHidd_PCIDevice_CapabilitySSVPID
: capability
= PCICAP_SSVPID
;break;
787 case aoHidd_PCIDevice_CapabilityAGP3
: capability
= PCICAP_AGP3
;break;
788 case aoHidd_PCIDevice_CapabilityPCIE
: capability
= PCICAP_PCIE
;break;
789 case aoHidd_PCIDevice_CapabilityMSIX
: capability
= PCICAP_MSIX
;break;
790 case aoHidd_PCIDevice_CapabilityAdvancedFeatures
: capability
= PCICAP_ADVANCED_FEATURES
;break;
793 *msg
->storage
= findCapabilityOffset(cl
, o
, capability
);
796 static void dispatch_extendedcapability(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
799 UWORD capability
= 0;
801 if(!hasExtendedConfig(cl
, o
))
803 D(bug("[PCIDevice] HasExtendedConfig = NULL\n"));
808 D(bug("[PCIDevice] HasExtendedConfig != NULL!\n"));
810 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
814 case aoHidd_PCIDevice_ExtendedCapabilityAER
: capability
= PCIEECAP_AER
;break;
815 case aoHidd_PCIDevice_ExtendedCapabilityVC
: capability
= PCIEECAP_VC
;break;
816 case aoHidd_PCIDevice_ExtendedCapabilitySerialNumber
: capability
= PCIEECAP_SER
;break;
817 case aoHidd_PCIDevice_ExtendedCapabilityPowerBudgeting
: capability
= PCIEECAP_PWR_BUDGET
;break;
820 *msg
->storage
= findExpressExtendedCapabilityOffset(cl
, o
, capability
);
825 typedef void (*dispatcher_t
)(OOP_Class
*, OOP_Object
*, struct pRoot_Get
*);
827 static const dispatcher_t Dispatcher
[num_Hidd_PCIDevice_Attrs
] =
829 [aoHidd_PCIDevice_Driver
] = dispatch_generic
,
830 [aoHidd_PCIDevice_Bus
] = dispatch_generic
,
831 [aoHidd_PCIDevice_Dev
] = dispatch_generic
,
832 [aoHidd_PCIDevice_Sub
] = dispatch_generic
,
833 [aoHidd_PCIDevice_VendorID
] = dispatch_generic
,
834 [aoHidd_PCIDevice_ProductID
] = dispatch_generic
,
835 [aoHidd_PCIDevice_RevisionID
] = dispatch_generic
,
836 [aoHidd_PCIDevice_Interface
] = dispatch_generic
,
837 [aoHidd_PCIDevice_Class
] = dispatch_generic
,
838 [aoHidd_PCIDevice_SubClass
] = dispatch_generic
,
839 [aoHidd_PCIDevice_SubsystemVendorID
] = dispatch_generic
,
840 [aoHidd_PCIDevice_SubsystemID
] = dispatch_generic
,
841 [aoHidd_PCIDevice_IRQLine
] = dispatch_generic
,
842 [aoHidd_PCIDevice_RomBase
] = dispatch_generic
,
843 [aoHidd_PCIDevice_RomSize
] = dispatch_generic
,
844 [aoHidd_PCIDevice_ExtendedConfig
] = dispatch_generic
,
845 [aoHidd_PCIDevice_ConfigSize
] = dispatch_generic
,
846 [aoHidd_PCIDevice_Base0
] = dispatch_base
,
847 [aoHidd_PCIDevice_Base1
] = dispatch_base
,
848 [aoHidd_PCIDevice_Base2
] = dispatch_base
,
849 [aoHidd_PCIDevice_Base3
] = dispatch_base
,
850 [aoHidd_PCIDevice_Base4
] = dispatch_base
,
851 [aoHidd_PCIDevice_Base5
] = dispatch_base
,
852 [aoHidd_PCIDevice_Size0
] = dispatch_size
,
853 [aoHidd_PCIDevice_Size1
] = dispatch_size
,
854 [aoHidd_PCIDevice_Size2
] = dispatch_size
,
855 [aoHidd_PCIDevice_Size3
] = dispatch_size
,
856 [aoHidd_PCIDevice_Size4
] = dispatch_size
,
857 [aoHidd_PCIDevice_Size5
] = dispatch_size
,
858 [aoHidd_PCIDevice_Type0
] = dispatch_type
,
859 [aoHidd_PCIDevice_Type1
] = dispatch_type
,
860 [aoHidd_PCIDevice_Type2
] = dispatch_type
,
861 [aoHidd_PCIDevice_Type3
] = dispatch_type
,
862 [aoHidd_PCIDevice_Type4
] = dispatch_type
,
863 [aoHidd_PCIDevice_Type5
] = dispatch_type
,
865 /* Bridge attributes */
866 [aoHidd_PCIDevice_isBridge
] = dispatch_pci2pcibridge
,
867 [aoHidd_PCIDevice_SubBus
] = dispatch_pci2pcibridge
,
868 [aoHidd_PCIDevice_MemoryBase
] = dispatch_pci2pcibridge
,
869 [aoHidd_PCIDevice_MemoryLimit
] = dispatch_pci2pcibridge
,
870 [aoHidd_PCIDevice_PrefetchableBase
] = dispatch_pci2pcibridge
,
871 [aoHidd_PCIDevice_PrefetchableLimit
] = dispatch_pci2pcibridge
,
872 [aoHidd_PCIDevice_IOBase
] = dispatch_pci2pcibridge
,
873 [aoHidd_PCIDevice_IOLimit
] = dispatch_pci2pcibridge
,
874 [aoHidd_PCIDevice_ISAEnable
] = dispatch_pci2pcibridge
,
875 [aoHidd_PCIDevice_VGAEnable
] = dispatch_pci2pcibridge
,
878 [aoHidd_PCIDevice_CapabilityPowerManagement
] = dispatch_capability
,
879 [aoHidd_PCIDevice_CapabilityAGP
] = dispatch_capability
,
880 [aoHidd_PCIDevice_CapabilityVitalProductData
] = dispatch_capability
,
881 [aoHidd_PCIDevice_CapabilitySlotID
] = dispatch_capability
,
882 [aoHidd_PCIDevice_CapabilityMSI
] = dispatch_capability
,
883 [aoHidd_PCIDevice_CapabilityCPCIHotSwap
] = dispatch_capability
,
884 [aoHidd_PCIDevice_CapabilityPCIX
] = dispatch_capability
,
885 [aoHidd_PCIDevice_CapabilityHyperTransport
] = dispatch_capability
,
886 [aoHidd_PCIDevice_CapabilityVendorSpecific
] = dispatch_capability
,
887 [aoHidd_PCIDevice_CapabilityDebugPort
] = dispatch_capability
,
888 [aoHidd_PCIDevice_CapabilityCPCICRC
] = dispatch_capability
,
889 [aoHidd_PCIDevice_CapabilityHotPlugController
] = dispatch_capability
,
890 [aoHidd_PCIDevice_CapabilitySSVPID
] = dispatch_capability
,
891 [aoHidd_PCIDevice_CapabilityAGP3
] = dispatch_capability
,
892 [aoHidd_PCIDevice_CapabilityPCIE
] = dispatch_capability
,
893 [aoHidd_PCIDevice_CapabilityMSIX
] = dispatch_capability
,
894 [aoHidd_PCIDevice_CapabilityAdvancedFeatures
] = dispatch_capability
,
896 /* Extended capabilities */
897 [aoHidd_PCIDevice_ExtendedCapabilityAER
] = dispatch_extendedcapability
,
898 [aoHidd_PCIDevice_ExtendedCapabilityVC
] = dispatch_extendedcapability
,
899 [aoHidd_PCIDevice_ExtendedCapabilitySerialNumber
] = dispatch_extendedcapability
,
900 [aoHidd_PCIDevice_ExtendedCapabilityPowerBudgeting
] = dispatch_extendedcapability
,
903 void PCIDev__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
906 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
908 if (IS_PCIDEV_ATTR(msg
->attrID
, idx
))
910 if (Dispatcher
[idx
] != NULL
)
911 Dispatcher
[idx
](cl
, o
, msg
);
914 case aoHidd_PCIDevice_isMEM
:
916 (getWord(cl
, o
, PCICS_COMMAND
) &
918 == PCICMF_MEMDECODE
);
921 case aoHidd_PCIDevice_isIO
:
923 (getWord(cl
, o
, PCICS_COMMAND
) &
928 case aoHidd_PCIDevice_isMaster
:
930 (getWord(cl
, o
, PCICS_COMMAND
) &
932 == PCICMF_BUSMASTER
);
935 case aoHidd_PCIDevice_paletteSnoop
:
937 (getWord(cl
, o
, PCICS_COMMAND
) &
942 case aoHidd_PCIDevice_is66MHz
:
944 (getWord(cl
, o
, PCICS_STATUS
) &
949 case aoHidd_PCIDevice_ClassDesc
:
950 *msg
->storage
= (IPTR
)dev
->strClass
;
953 case aoHidd_PCIDevice_SubClassDesc
:
954 *msg
->storage
= (IPTR
)dev
->strSubClass
;
957 case aoHidd_PCIDevice_InterfaceDesc
:
958 *msg
->storage
= (IPTR
)dev
->strInterface
;
961 case aoHidd_PCIDevice_INTLine
:
962 *msg
->storage
= getByte(cl
, o
, PCICS_INT_LINE
);
965 case aoHidd_PCIDevice_IRQStatus
:
967 (getWord(cl
, o
, PCICS_STATUS
) &
968 PCISTF_INTERRUPT_STATUS
)
969 == PCISTF_INTERRUPT_STATUS
);
972 case aoHidd_PCIDevice_CapabilitiesPresent
:
974 (getWord(cl
, o
, PCICS_STATUS
) &
976 == PCISTF_CAPABILITIES
);
979 case aoHidd_PCIDevice_Owner
:
980 *msg
->storage
= (IPTR
)dev
->ownerLock
.ss_Link
.ln_Name
;
984 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
990 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
994 void PCIDev__Root__Set(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Set
*msg
)
997 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
998 struct TagItem
*tag
, *tags
;
1000 tags
= (struct TagItem
*)msg
->attrList
;
1002 while ((tag
= NextTagItem(&tags
)))
1004 if (IS_PCIDEV_ATTR(tag
->ti_Tag
, idx
))
1008 case aoHidd_PCIDevice_Base0
:
1009 setLong(cl
, o
, PCICS_BAR0
, tag
->ti_Data
);
1010 dev
->BaseReg
[0].addr
= getLong(cl
, o
, PCICS_BAR0
);
1013 case aoHidd_PCIDevice_Base1
:
1014 setLong(cl
, o
, PCICS_BAR1
, tag
->ti_Data
);
1015 dev
->BaseReg
[1].addr
= getLong(cl
, o
, PCICS_BAR1
);
1018 case aoHidd_PCIDevice_Base2
:
1021 setLong(cl
, o
, PCICS_BAR2
, tag
->ti_Data
);
1022 dev
->BaseReg
[2].addr
= getLong(cl
, o
, PCICS_BAR2
);
1026 case aoHidd_PCIDevice_Base3
:
1029 setLong(cl
, o
, PCICS_BAR3
, tag
->ti_Data
);
1030 dev
->BaseReg
[3].addr
= getLong(cl
, o
, PCICS_BAR3
);
1034 case aoHidd_PCIDevice_Base4
:
1037 setLong(cl
, o
, PCICS_BAR4
, tag
->ti_Data
);
1038 dev
->BaseReg
[4].addr
= getLong(cl
, o
, PCICS_BAR4
);
1042 case aoHidd_PCIDevice_Base5
:
1045 setLong(cl
, o
, PCICS_BAR5
, tag
->ti_Data
);
1046 dev
->BaseReg
[5].addr
= getLong(cl
, o
, PCICS_BAR5
);
1050 case aoHidd_PCIDevice_RomBase
:
1051 setLong(cl
, o
, PCICS_EXPROM_BASE
, tag
->ti_Data
);
1052 dev
->RomBase
= getLong(cl
, o
, PCICS_EXPROM_BASE
);
1055 case aoHidd_PCIDevice_MemoryBase
:
1056 if (dev
->isBridge
) setWord(cl
, o
, PCIBR_MEMBASE
, tag
->ti_Data
>> 16);
1059 case aoHidd_PCIDevice_MemoryLimit
:
1060 if (dev
->isBridge
) setWord(cl
, o
, PCIBR_MEMLIMIT
, tag
->ti_Data
>> 16);
1063 case aoHidd_PCIDevice_PrefetchableBase
:
1064 if (dev
->isBridge
) setWord(cl
, o
, PCIBR_PREFETCHBASE
, tag
->ti_Data
>> 16);
1067 case aoHidd_PCIDevice_PrefetchableLimit
:
1068 if (dev
->isBridge
) setWord(cl
, o
, PCIBR_PREFETCHLIMIT
, tag
->ti_Data
>> 16);
1071 case aoHidd_PCIDevice_IOBase
:
1072 if (dev
->isBridge
) setByte(cl
, o
, PCIBR_IOBASE
, tag
->ti_Data
>> 8);
1075 case aoHidd_PCIDevice_IOLimit
:
1076 if (dev
->isBridge
) setByte(cl
, o
, PCIBR_IOLIMIT
, tag
->ti_Data
>> 8);
1079 case aoHidd_PCIDevice_isIO
:
1081 UWORD command
= getWord(cl
, o
, PCICS_COMMAND
) & ~PCICMF_IODECODE
;
1083 command
|= PCICMF_IODECODE
;
1084 setWord(cl
, o
, PCICS_COMMAND
, command
);
1088 case aoHidd_PCIDevice_isMEM
:
1090 UWORD command
= getWord(cl
, o
, PCICS_COMMAND
) & ~PCICMF_MEMDECODE
;
1092 command
|= PCICMF_MEMDECODE
;
1093 setWord(cl
, o
, PCICS_COMMAND
, command
);
1097 case aoHidd_PCIDevice_isMaster
:
1099 UWORD command
= getWord(cl
, o
, PCICS_COMMAND
) & ~PCICMF_BUSMASTER
;
1101 command
|= PCICMF_BUSMASTER
;
1102 setWord(cl
, o
, PCICS_COMMAND
, command
);
1106 case aoHidd_PCIDevice_paletteSnoop
:
1108 UWORD command
= getWord(cl
, o
, PCICS_COMMAND
) & ~PCICMF_VGASNOOP
;
1110 command
|= PCICMF_VGASNOOP
;
1111 setWord(cl
, o
, PCICS_COMMAND
, command
);
1115 case aoHidd_PCIDevice_ISAEnable
:
1118 UWORD control
= getWord(cl
, o
, PCIBR_CONTROL
) & ~PCICTRLF_ISAENABLE
;
1120 control
|= PCICTRLF_ISAENABLE
;
1121 setWord(cl
, o
, PCIBR_CONTROL
, control
);
1125 case aoHidd_PCIDevice_VGAEnable
:
1128 UWORD control
= getWord(cl
, o
, PCIBR_CONTROL
) & ~PCICTRLF_VGAENABLE
;
1130 control
|= PCICTRLF_VGAENABLE
;
1131 setWord(cl
, o
, PCIBR_CONTROL
, control
);
1136 bug("[PCIDevice] Trying to set nonsettable attribute %d!\n", idx
);