2 Copyright © 2004-2013, 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 *****************************************************************************************/
54 static void setLong(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
, ULONG value
)
56 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
58 HIDD_PCIDriver_WriteConfigLong(dev
->driver
, dev
->bus
, dev
->dev
, dev
->sub
, reg
, value
);
61 static void setWord(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
, UWORD value
)
63 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
65 HIDD_PCIDriver_WriteConfigWord(dev
->driver
, dev
->bus
, dev
->dev
, dev
->sub
, reg
, value
);
68 static void setByte(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
, UBYTE value
)
70 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
72 HIDD_PCIDriver_WriteConfigByte(dev
->driver
, dev
->bus
, dev
->dev
, dev
->sub
, reg
, value
);
75 static ULONG
getLong(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
)
77 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
79 return HIDD_PCIDriver_ReadConfigLong(dev
->driver
, dev
->bus
, dev
->dev
, dev
->sub
, reg
);
82 static UWORD
getWord(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
)
84 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
86 return HIDD_PCIDriver_ReadConfigWord(dev
->driver
, dev
->bus
, dev
->dev
, dev
->sub
, reg
);
89 static UBYTE
getByte(OOP_Class
*cl
, OOP_Object
*o
, ULONG reg
)
91 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
93 return HIDD_PCIDriver_ReadConfigByte(dev
->driver
, dev
->bus
, dev
->dev
, dev
->sub
, reg
);
96 /* Returns offset of capability area in config area or 0 if capability is not present */
97 static UBYTE
findCapabilityOffset(OOP_Class
* cl
, OOP_Object
*o
, UBYTE capability
)
99 UWORD where
= 0x34; /* First cap list entry */
102 /* Check if capabilities present at all */
103 if ((getWord(cl
, o
, PCICS_STATUS
) & PCISTF_CAPABILITIES
) != PCISTF_CAPABILITIES
)
106 /* Iterate over capabilities */
109 where
= getByte(cl
, o
, where
);
115 capid
= getByte(cl
, o
, where
);
120 if (capid
== capability
) return (UBYTE
)where
;
122 where
+= 1; /* next cap */
128 /* Returns offset of PCI Express extended capability area in config area or 0 if capability is not present */
129 static UWORD
findExpressExtendedCapabilityOffset(OOP_Class
* cl
, OOP_Object
*o
, UWORD capability
)
131 UWORD where
= 0x100; /* First PCI Express extended cap list entry */
136 caphdr
= getLong(cl
, o
, where
);
138 if ((caphdr
& 0xffff) == capability
) return (UWORD
)where
;
140 where
= (caphdr
>>20)&~3;
146 UBYTE
PCIDev__Hidd_PCIDevice__ReadConfigByte(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_ReadConfigByte
*msg
)
148 return getByte(cl
, o
, msg
->reg
);
151 UWORD
PCIDev__Hidd_PCIDevice__ReadConfigWord(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_ReadConfigWord
*msg
)
153 return getWord(cl
, o
, msg
->reg
);
156 ULONG
PCIDev__Hidd_PCIDevice__ReadConfigLong(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_ReadConfigLong
*msg
)
158 return getLong(cl
, o
, msg
->reg
);
161 VOID
PCIDev__Hidd_PCIDevice__WriteConfigByte(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_WriteConfigByte
*msg
)
163 setByte(cl
, o
, msg
->reg
, msg
->val
);
166 VOID
PCIDev__Hidd_PCIDevice__WriteConfigWord(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_WriteConfigWord
*msg
)
168 setWord(cl
, o
, msg
->reg
, msg
->val
);
171 VOID
PCIDev__Hidd_PCIDevice__WriteConfigLong(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_PCIDevice_WriteConfigLong
*msg
)
173 setLong(cl
, o
, msg
->reg
, msg
->val
);
176 /*****************************************************************************************
179 moHidd_PCIDevice_AddInterrupt
182 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDevice_AddInterrupt *Msg);
184 OOP_Object *HIDD_PCIDriver_AddInterrupt(OOP_Object *obj, OOP_Object *device,
185 struct Interrupt *interrupt);
191 Add interrupt handler for the device.
194 obj - Pointer to device object.
195 interrupt - Interrupt structure to add.
198 TRUE it succesful or FALSE on failure.
207 moHidd_PCIDevice_RemoveInterrupt
211 *****************************************************************************************/
213 BOOL
PCIDev__Hidd_PCIDevice__AddInterrupt(OOP_Class
*cl
, OOP_Object
*o
,
214 struct pHidd_PCIDevice_AddInterrupt
*msg
)
216 tDeviceData
*dev
= OOP_INST_DATA(cl
, o
);
218 return HIDD_PCIDriver_AddInterrupt(dev
->driver
, o
, msg
->interrupt
);
221 /*****************************************************************************************
224 moHidd_PCIDevice_RemoveInterrupt
227 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDevice_RemoveInterrupt *Msg);
229 OOP_Object *HIDD_PCIDevice_RemoveInterrupt(OOP_Object *obj, OOP_Object *device,
230 struct Interrupt *interrupt);
236 Remove interrupt handler from the device.
239 obj - Pointer to the device object.
240 interrupt - Interrupt structure to remove.
252 moHidd_PCIDevice_AddInterrupt
256 *****************************************************************************************/
258 VOID
PCIDev__Hidd_PCIDevice__RemoveInterrupt(OOP_Class
*cl
, OOP_Object
*o
,
259 struct pHidd_PCIDevice_RemoveInterrupt
*msg
)
261 tDeviceData
*dev
= OOP_INST_DATA(cl
, o
);
263 return HIDD_PCIDriver_RemoveInterrupt(dev
->driver
, o
, msg
->interrupt
);
266 /*****************************************************************************************
269 moHidd_PCIDevice_Obtain
272 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDevice_Obtain *Msg);
274 OOP_Object *HIDD_PCIDevice_Obtain(OOP_Object *obj, CONST_STRPTR owner);
280 Lock the device for exclusive use.
283 obj - Pointer to the device object.
284 owner - A string identifying the owner.
287 NULL on success or string identifying current owner.
296 moHidd_PCIDevice_Release
300 *****************************************************************************************/
302 CONST_STRPTR
PCIDev__Hidd_PCIDevice__Obtain(OOP_Class
*cl
, OOP_Object
*o
,
303 struct pHidd_PCIDevice_Obtain
*msg
)
305 tDeviceData
*dev
= OOP_INST_DATA(cl
, o
);
306 CONST_STRPTR current
= NULL
;
309 * FIXME: Actually this is just atomic compare and swap.
310 * I believe it should be impemented in assembler.
311 * Ouch, on Amiga such operations are unsafe, at least
312 * in CHIP memory. Too bad...
314 ObtainSemaphore(&dev
->ownerLock
);
316 /* While we are using semaphore, owner name is embedded in its node */
317 if (dev
->ownerLock
.ss_Link
.ln_Name
)
318 current
= dev
->ownerLock
.ss_Link
.ln_Name
;
320 dev
->ownerLock
.ss_Link
.ln_Name
= (STRPTR
)msg
->owner
;
322 ReleaseSemaphore(&dev
->ownerLock
);
327 /*****************************************************************************************
330 moHidd_PCIDevice_Release
333 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDevice_Release *Msg);
335 OOP_Object *HIDD_PCIDevice_Release(OOP_Object *obj);
341 Release ownership of the device.
344 obj - Pointer to the device object.
350 You should call this function only on devices owned by you. Doing
351 this on someone else's devices will not do any good things.
358 moHidd_PCIDevice_Obtain
362 *****************************************************************************************/
364 VOID
PCIDev__Hidd_PCIDevice__Release(OOP_Class
*cl
, OOP_Object
*o
,
365 struct pHidd_PCIDevice_Release
*msg
)
367 tDeviceData
*dev
= OOP_INST_DATA(cl
, o
);
369 dev
->ownerLock
.ss_Link
.ln_Name
= NULL
;
373 PCIDevice::New method is invoked by base pci class. It passes to the device
374 class information about the driver this class should use and location of
375 created device on the PCI bus handled by given driver.
377 OOP_Object
*PCIDev__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
381 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
384 struct TagItem
*tag
, *tags
;
385 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
, o
);
386 OOP_Object
*driver
= NULL
;
388 InitSemaphore(&dev
->ownerLock
);
390 tags
=(struct TagItem
*)msg
->attrList
;
393 Get all information passed by pci class calling OOP_NewObject()
395 while((tag
= NextTagItem(&tags
)))
399 if (IS_PCIDEV_ATTR(tag
->ti_Tag
, idx
))
403 case aoHidd_PCIDevice_Driver
:
404 dev
->driver
= (OOP_Object
*)tag
->ti_Data
;
405 driver
= dev
->driver
;
408 case aoHidd_PCIDevice_Bus
:
409 dev
->bus
= tag
->ti_Data
;
412 case aoHidd_PCIDevice_Dev
:
413 dev
->dev
= tag
->ti_Data
;
416 case aoHidd_PCIDevice_Sub
:
417 dev
->sub
= tag
->ti_Data
;
424 If driver is passed (*HAS TO* be passed) acquire some unchangeable
425 information regarding given device
432 Get the header type in order to determine whether it is a
435 ht
= getByte(cl
, o
, PCICS_HEADERTYPE
) & PCIHT_MASK
;
437 if (ht
== PCIHT_BRIDGE
)
440 dev
->subbus
= getByte(cl
, o
, PCIBR_SUBBUS
);
443 /* Get all constant ID's */
444 dev
->VendorID
= getWord(cl
, o
, PCICS_VENDOR
);
445 dev
->ProductID
= getWord(cl
, o
, PCICS_PRODUCT
);
447 dev
->RevisionID
= getByte(cl
, o
, PCICS_REVISION
);
448 dev
->Interface
= getByte(cl
, o
, PCICS_PROGIF
);
449 dev
->SubClass
= getByte(cl
, o
, PCICS_SUBCLASS
);
450 dev
->Class
= getByte(cl
, o
, PCICS_CLASS
);
452 dev
->SubsysVID
= getWord(cl
, o
, PCICS_SUBVENDOR
);
453 dev
->SubsystemID
= getWord(cl
, o
, PCICS_SUBSYSTEM
);
455 dev
->IRQLine
= getByte(cl
, o
, PCICS_INT_PIN
);
459 dev
->INTLine
= getByte(cl
, o
, PCICS_INT_LINE
);
461 else dev
->INTLine
= 0;
463 dev
->HeaderType
= ht
;
465 getPCIClassDesc(dev
->Class
, dev
->SubClass
, dev
->Interface
,
466 &dev
->strClass
, &dev
->strSubClass
, &dev
->strInterface
);
468 /* Satisfy BUG watchers ;) */
469 D(bug("[PCIDevice] %02x.%02x.%x = %04.4lx:%04.4lx (%s %s %s)\n",
470 dev
->bus
, dev
->dev
, dev
->sub
,
471 dev
->VendorID
, dev
->ProductID
,
472 dev
->strClass
, dev
->strSubClass
, dev
->strInterface
));
473 D(bug("[PCIDevice] > IRQ %u INT %u\n", dev
->IRQLine
, dev
->INTLine
));
475 // print out a warning to the user in case the interrupt line is not assigned by BIOS
476 if (dev
->INTLine
== 255 && !dev
->isBridge
)
477 bug("[PCIDevice] WARNING: Interrupt line is not assigned! Device may freeze or malfunction at use!\n");
479 /* Read two first base addresses */
480 for (i
= 0; i
< 2; i
++)
482 dev
->BaseReg
[i
].addr
= getLong(cl
, o
, PCICS_BAR0
+ (i
<< 2));
483 dev
->BaseReg
[i
].size
= sizePCIBaseReg(driver
, PSD(cl
), dev
->bus
,
484 dev
->dev
, dev
->sub
, i
);
487 /* Address and size of ROM */
488 dev
->RomBase
= getLong(cl
, o
, PCICS_EXPROM_BASE
);
489 dev
->RomSize
= sizePCIBaseReg(driver
, PSD(cl
), dev
->bus
,
490 dev
->dev
, dev
->sub
, (PCICS_EXPROM_BASE
- PCICS_BAR0
) >> 2);
493 Bridges specify only first two base addresses. If not bridge,
498 for (i
= 2; i
< 6; i
++)
500 dev
->BaseReg
[i
].addr
= getLong(cl
, o
, PCICS_BAR0
+ (i
<< 2));
501 dev
->BaseReg
[i
].size
= sizePCIBaseReg(driver
, PSD(cl
), dev
->bus
,
502 dev
->dev
, dev
->sub
, i
);
512 PCIDevice::Get method splitted into few parts in order to make switch'es shorter.
515 static void dispatch_generic(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
518 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
520 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
524 case aoHidd_PCIDevice_Driver
:
525 *msg
->storage
= (IPTR
)dev
->driver
;
528 case aoHidd_PCIDevice_Bus
:
529 *msg
->storage
= (IPTR
)dev
->bus
;
532 case aoHidd_PCIDevice_Dev
:
533 *msg
->storage
= (IPTR
)dev
->dev
;
536 case aoHidd_PCIDevice_Sub
:
537 *msg
->storage
= (IPTR
)dev
->sub
;
540 case aoHidd_PCIDevice_VendorID
:
541 *msg
->storage
= (IPTR
)dev
->VendorID
;
544 case aoHidd_PCIDevice_ProductID
:
545 *msg
->storage
= (IPTR
)dev
->ProductID
;
548 case aoHidd_PCIDevice_RevisionID
:
549 *msg
->storage
= (IPTR
)dev
->RevisionID
;
552 case aoHidd_PCIDevice_Interface
:
553 *msg
->storage
= (IPTR
)dev
->Interface
;
556 case aoHidd_PCIDevice_Class
:
557 *msg
->storage
= (IPTR
)dev
->Class
;
560 case aoHidd_PCIDevice_SubClass
:
561 *msg
->storage
= (IPTR
)dev
->SubClass
;
564 case aoHidd_PCIDevice_SubsystemVendorID
:
565 *msg
->storage
= (IPTR
)dev
->SubsysVID
;
568 case aoHidd_PCIDevice_SubsystemID
:
569 *msg
->storage
= (IPTR
)dev
->SubsystemID
;
572 case aoHidd_PCIDevice_INTLine
:
573 *msg
->storage
= (IPTR
)dev
->INTLine
;
576 case aoHidd_PCIDevice_IRQLine
:
577 *msg
->storage
= (IPTR
)dev
->IRQLine
;
580 case aoHidd_PCIDevice_RomBase
:
581 *msg
->storage
= (IPTR
)dev
->RomBase
;
584 case aoHidd_PCIDevice_RomSize
:
585 *msg
->storage
= (IPTR
)dev
->RomSize
;
590 static void dispatch_base(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
593 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
595 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
600 case aoHidd_PCIDevice_Base0
: id
= 0; break;
601 case aoHidd_PCIDevice_Base1
: id
= 1; break;
602 case aoHidd_PCIDevice_Base2
: id
= 2; break;
603 case aoHidd_PCIDevice_Base3
: id
= 3; break;
604 case aoHidd_PCIDevice_Base4
: id
= 4; break;
605 case aoHidd_PCIDevice_Base5
: id
= 5; break;
608 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
609 if (dev
->isBridge
&& id
>= 2) { *msg
->storage
= 0; return; }
611 *msg
->storage
= (IPTR
)dev
->BaseReg
[id
].addr
;
612 if ((dev
->BaseReg
[id
].addr
& PCIBAR_MASK_TYPE
)==PCIBAR_TYPE_IO
)
615 *msg
->storage
&= PCIBAR_MASK_IO
;
616 OOP_GetAttr(dev
->driver
, aHidd_PCIDriver_IOBase
, &IOBase
);
617 *msg
->storage
+= IOBase
;
621 *msg
->storage
&= PCIBAR_MASK_MEM
;
625 static void dispatch_type(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
628 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
630 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
635 case aoHidd_PCIDevice_Type0
: id
= 0; break;
636 case aoHidd_PCIDevice_Type1
: id
= 1; break;
637 case aoHidd_PCIDevice_Type2
: id
= 2; break;
638 case aoHidd_PCIDevice_Type3
: id
= 3; break;
639 case aoHidd_PCIDevice_Type4
: id
= 4; break;
640 case aoHidd_PCIDevice_Type5
: id
= 5; break;
643 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
644 if (dev
->isBridge
&& id
>= 2) { *msg
->storage
= 0; return; }
646 *msg
->storage
= (IPTR
)dev
->BaseReg
[id
].addr
;
647 if ((dev
->BaseReg
[id
].addr
& PCIBAR_MASK_TYPE
)==PCIBAR_TYPE_IO
)
649 *msg
->storage
&= ~PCIBAR_MASK_IO
;
653 *msg
->storage
&= ~PCIBAR_MASK_MEM
;
657 static void dispatch_size(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
660 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
662 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
667 case aoHidd_PCIDevice_Size0
: id
= 0; break;
668 case aoHidd_PCIDevice_Size1
: id
= 1; break;
669 case aoHidd_PCIDevice_Size2
: id
= 2; break;
670 case aoHidd_PCIDevice_Size3
: id
= 3; break;
671 case aoHidd_PCIDevice_Size4
: id
= 4; break;
672 case aoHidd_PCIDevice_Size5
: id
= 5; break;
675 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
676 if (dev
->isBridge
&& id
>= 2) { *msg
->storage
= 0; return;}
678 *msg
->storage
= (IPTR
)dev
->BaseReg
[id
].size
;
681 static void dispatch_pci2pcibridge(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
684 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
688 /* If device is not a PCI-PCI bridge, do nothing */
689 if (!dev
->isBridge
) { *msg
->storage
= 0; return; }
691 control
= getWord(cl
, o
, PCIBR_CONTROL
);
693 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
697 case aoHidd_PCIDevice_isBridge
:
698 *msg
->storage
= dev
->isBridge
;
701 case aoHidd_PCIDevice_SubBus
:
702 *msg
->storage
= dev
->subbus
;
705 case aoHidd_PCIDevice_MemoryBase
:
706 *msg
->storage
= getWord(cl
, o
, PCIBR_MEMBASE
) << 16;
709 case aoHidd_PCIDevice_MemoryLimit
:
710 *msg
->storage
= getWord(cl
, o
, PCIBR_MEMLIMIT
) << 16;
713 case aoHidd_PCIDevice_PrefetchableBase
:
714 *msg
->storage
= getWord(cl
, o
, PCIBR_PREFETCHBASE
) << 16;
717 case aoHidd_PCIDevice_PrefetchableLimit
:
718 *msg
->storage
= getWord(cl
, o
, PCIBR_PREFETCHLIMIT
) << 16;
721 case aoHidd_PCIDevice_IOBase
:
722 *msg
->storage
= getByte(cl
, o
, PCIBR_IOBASE
) << 8;
725 case aoHidd_PCIDevice_IOLimit
:
726 *msg
->storage
= getByte(cl
, o
, PCIBR_IOLIMIT
) << 8;
729 case aoHidd_PCIDevice_ISAEnable
:
730 *msg
->storage
= (control
& PCICTRLF_ISAENABLE
) == PCICTRLF_ISAENABLE
;
733 case aoHidd_PCIDevice_VGAEnable
:
734 *msg
->storage
= (control
& PCICTRLF_VGAENABLE
) == PCICTRLF_VGAENABLE
;
739 static void dispatch_capability(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
742 UBYTE capability
= 0;
743 //tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
745 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
749 case aoHidd_PCIDevice_CapabilityPowerManagement
: capability
= PCICAP_POWER_MANAGEMENT
;break;
750 case aoHidd_PCIDevice_CapabilityAGP
: capability
= PCICAP_AGP
;break;
751 case aoHidd_PCIDevice_CapabilityVitalProductData
: capability
= PCICAP_VITAL_PRODUCT_DATA
;break;
752 case aoHidd_PCIDevice_CapabilitySlotID
: capability
= PCICAP_SLOT_ID
;break;
753 case aoHidd_PCIDevice_CapabilityMSI
: capability
= PCICAP_MSI
;break;
754 case aoHidd_PCIDevice_CapabilityCPCIHotSwap
: capability
= PCICAP_CPCI_HOT_SWAP
;break;
755 case aoHidd_PCIDevice_CapabilityPCIX
: capability
= PCICAP_PCIX
;break;
756 case aoHidd_PCIDevice_CapabilityHyperTransport
: capability
= PCICAP_HYPER_TRANSPORT
;break;
757 case aoHidd_PCIDevice_CapabilityVendorSpecific
: capability
= PCICAP_VENDOR_SPECIFIC
;break;
758 case aoHidd_PCIDevice_CapabilityDebugPort
: capability
= PCICAP_DEBUG_PORT
;break;
759 case aoHidd_PCIDevice_CapabilityCPCICRC
: capability
= PCICAP_CPCI_CR
;break;
760 case aoHidd_PCIDevice_CapabilityHotPlugController
: capability
= PCICAP_HOT_PLUG_CONTROLLER
;break;
761 case aoHidd_PCIDevice_CapabilitySSVPID
: capability
= PCICAP_SSVPID
;break;
762 case aoHidd_PCIDevice_CapabilityAGP3
: capability
= PCICAP_AGP3
;break;
763 case aoHidd_PCIDevice_CapabilityPCIE
: capability
= PCICAP_PCIE
;break;
764 case aoHidd_PCIDevice_CapabilityMSIX
: capability
= PCICAP_MSIX
;break;
765 case aoHidd_PCIDevice_CapabilityAdvancedFeatures
: capability
= PCICAP_ADVANCED_FEATURES
;break;
768 *msg
->storage
= findCapabilityOffset(cl
, o
, capability
);
771 static void dispatch_extendedcapability(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
774 UWORD capability
= 0;
775 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
778 OOP_GetAttr(dev
->driver
, aHidd_PCIDevice_CapabilityPCIE
, &isPCIE
);
779 if(!isPCIE
) { *msg
->storage
= 0; return; }
781 idx
= msg
->attrID
- HiddPCIDeviceAttrBase
;
785 case aoHidd_PCIDevice_ExtendedCapabilityAER
: capability
= PCIEECAP_AER
;break;
786 case aoHidd_PCIDevice_ExtendedCapabilityVC
: capability
= PCIEECAP_VC
;break;
787 case aoHidd_PCIDevice_ExtendedCapabilitySerialNumber
: capability
= PCIEECAP_SER
;break;
788 case aoHidd_PCIDevice_ExtendedCapabilityPowerBudgeting
: capability
= PCIEECAP_PWR_BUDGET
;break;
791 *msg
->storage
= findExpressExtendedCapabilityOffset(cl
, o
, capability
);
794 typedef void (*dispatcher_t
)(OOP_Class
*, OOP_Object
*, struct pRoot_Get
*);
796 static const dispatcher_t Dispatcher
[num_Hidd_PCIDevice_Attrs
] =
798 [aoHidd_PCIDevice_Driver
] = dispatch_generic
,
799 [aoHidd_PCIDevice_Bus
] = dispatch_generic
,
800 [aoHidd_PCIDevice_Dev
] = dispatch_generic
,
801 [aoHidd_PCIDevice_Sub
] = dispatch_generic
,
802 [aoHidd_PCIDevice_VendorID
] = dispatch_generic
,
803 [aoHidd_PCIDevice_ProductID
] = dispatch_generic
,
804 [aoHidd_PCIDevice_RevisionID
] = dispatch_generic
,
805 [aoHidd_PCIDevice_Interface
] = dispatch_generic
,
806 [aoHidd_PCIDevice_Class
] = dispatch_generic
,
807 [aoHidd_PCIDevice_SubClass
] = dispatch_generic
,
808 [aoHidd_PCIDevice_SubsystemVendorID
] = dispatch_generic
,
809 [aoHidd_PCIDevice_SubsystemID
] = dispatch_generic
,
810 [aoHidd_PCIDevice_INTLine
] = dispatch_generic
,
811 [aoHidd_PCIDevice_IRQLine
] = dispatch_generic
,
812 [aoHidd_PCIDevice_RomBase
] = dispatch_generic
,
813 [aoHidd_PCIDevice_RomSize
] = dispatch_generic
,
814 [aoHidd_PCIDevice_Base0
] = dispatch_base
,
815 [aoHidd_PCIDevice_Base1
] = dispatch_base
,
816 [aoHidd_PCIDevice_Base2
] = dispatch_base
,
817 [aoHidd_PCIDevice_Base3
] = dispatch_base
,
818 [aoHidd_PCIDevice_Base4
] = dispatch_base
,
819 [aoHidd_PCIDevice_Base5
] = dispatch_base
,
820 [aoHidd_PCIDevice_Size0
] = dispatch_size
,
821 [aoHidd_PCIDevice_Size1
] = dispatch_size
,
822 [aoHidd_PCIDevice_Size2
] = dispatch_size
,
823 [aoHidd_PCIDevice_Size3
] = dispatch_size
,
824 [aoHidd_PCIDevice_Size4
] = dispatch_size
,
825 [aoHidd_PCIDevice_Size5
] = dispatch_size
,
826 [aoHidd_PCIDevice_Type0
] = dispatch_type
,
827 [aoHidd_PCIDevice_Type1
] = dispatch_type
,
828 [aoHidd_PCIDevice_Type2
] = dispatch_type
,
829 [aoHidd_PCIDevice_Type3
] = dispatch_type
,
830 [aoHidd_PCIDevice_Type4
] = dispatch_type
,
831 [aoHidd_PCIDevice_Type5
] = dispatch_type
,
833 /* Bridge attributes */
834 [aoHidd_PCIDevice_isBridge
] = dispatch_pci2pcibridge
,
835 [aoHidd_PCIDevice_SubBus
] = dispatch_pci2pcibridge
,
836 [aoHidd_PCIDevice_MemoryBase
] = dispatch_pci2pcibridge
,
837 [aoHidd_PCIDevice_MemoryLimit
] = dispatch_pci2pcibridge
,
838 [aoHidd_PCIDevice_PrefetchableBase
] = dispatch_pci2pcibridge
,
839 [aoHidd_PCIDevice_PrefetchableLimit
] = dispatch_pci2pcibridge
,
840 [aoHidd_PCIDevice_IOBase
] = dispatch_pci2pcibridge
,
841 [aoHidd_PCIDevice_IOLimit
] = dispatch_pci2pcibridge
,
842 [aoHidd_PCIDevice_ISAEnable
] = dispatch_pci2pcibridge
,
843 [aoHidd_PCIDevice_VGAEnable
] = dispatch_pci2pcibridge
,
846 [aoHidd_PCIDevice_CapabilityPowerManagement
] = dispatch_capability
,
847 [aoHidd_PCIDevice_CapabilityAGP
] = dispatch_capability
,
848 [aoHidd_PCIDevice_CapabilityVitalProductData
] = dispatch_capability
,
849 [aoHidd_PCIDevice_CapabilitySlotID
] = dispatch_capability
,
850 [aoHidd_PCIDevice_CapabilityMSI
] = dispatch_capability
,
851 [aoHidd_PCIDevice_CapabilityCPCIHotSwap
] = dispatch_capability
,
852 [aoHidd_PCIDevice_CapabilityPCIX
] = dispatch_capability
,
853 [aoHidd_PCIDevice_CapabilityHyperTransport
] = dispatch_capability
,
854 [aoHidd_PCIDevice_CapabilityVendorSpecific
] = dispatch_capability
,
855 [aoHidd_PCIDevice_CapabilityDebugPort
] = dispatch_capability
,
856 [aoHidd_PCIDevice_CapabilityCPCICRC
] = dispatch_capability
,
857 [aoHidd_PCIDevice_CapabilityHotPlugController
] = dispatch_capability
,
858 [aoHidd_PCIDevice_CapabilitySSVPID
] = dispatch_capability
,
859 [aoHidd_PCIDevice_CapabilityAGP3
] = dispatch_capability
,
860 [aoHidd_PCIDevice_CapabilityPCIE
] = dispatch_capability
,
861 [aoHidd_PCIDevice_CapabilityMSIX
] = dispatch_capability
,
862 [aoHidd_PCIDevice_CapabilityAdvancedFeatures
] = dispatch_capability
,
864 /* Extended capabilities */
865 [aoHidd_PCIDevice_ExtendedCapabilityAER
] = dispatch_extendedcapability
,
866 [aoHidd_PCIDevice_ExtendedCapabilityVC
] = dispatch_extendedcapability
,
867 [aoHidd_PCIDevice_ExtendedCapabilitySerialNumber
] = dispatch_extendedcapability
,
868 [aoHidd_PCIDevice_ExtendedCapabilityPowerBudgeting
] = dispatch_extendedcapability
,
871 void PCIDev__Root__Get(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Get
*msg
)
874 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
876 if (IS_PCIDEV_ATTR(msg
->attrID
, idx
))
878 if (Dispatcher
[idx
] != NULL
)
879 Dispatcher
[idx
](cl
, o
, msg
);
882 case aoHidd_PCIDevice_isMEM
:
884 (getWord(cl
, o
, PCICS_COMMAND
) &
886 == PCICMF_MEMDECODE
);
889 case aoHidd_PCIDevice_isIO
:
891 (getWord(cl
, o
, PCICS_COMMAND
) &
896 case aoHidd_PCIDevice_isMaster
:
898 (getWord(cl
, o
, PCICS_COMMAND
) &
900 == PCICMF_BUSMASTER
);
903 case aoHidd_PCIDevice_paletteSnoop
:
905 (getWord(cl
, o
, PCICS_COMMAND
) &
910 case aoHidd_PCIDevice_is66MHz
:
912 (getWord(cl
, o
, PCICS_STATUS
) &
917 case aoHidd_PCIDevice_ClassDesc
:
918 *msg
->storage
= (IPTR
)dev
->strClass
;
921 case aoHidd_PCIDevice_SubClassDesc
:
922 *msg
->storage
= (IPTR
)dev
->strSubClass
;
925 case aoHidd_PCIDevice_InterfaceDesc
:
926 *msg
->storage
= (IPTR
)dev
->strInterface
;
928 case aoHidd_PCIDevice_IRQStatus
:
930 (getWord(cl
, o
, PCICS_STATUS
) &
931 PCISTF_INTERRUPT_STATUS
)
932 == PCISTF_INTERRUPT_STATUS
);
934 case aoHidd_PCIDevice_CapabilitiesPresent
:
936 (getWord(cl
, o
, PCICS_STATUS
) &
938 == PCISTF_CAPABILITIES
);
941 case aoHidd_PCIDevice_Owner
:
942 *msg
->storage
= (IPTR
)dev
->ownerLock
.ss_Link
.ln_Name
;
946 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
952 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
956 void PCIDev__Root__Set(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_Set
*msg
)
959 tDeviceData
*dev
= (tDeviceData
*)OOP_INST_DATA(cl
,o
);
960 struct TagItem
*tag
, *tags
;
962 tags
= (struct TagItem
*)msg
->attrList
;
964 while ((tag
= NextTagItem(&tags
)))
966 if (IS_PCIDEV_ATTR(tag
->ti_Tag
, idx
))
970 case aoHidd_PCIDevice_Base0
:
971 setLong(cl
, o
, PCICS_BAR0
, tag
->ti_Data
);
972 dev
->BaseReg
[0].addr
= getLong(cl
, o
, PCICS_BAR0
);
975 case aoHidd_PCIDevice_Base1
:
976 setLong(cl
, o
, PCICS_BAR1
, tag
->ti_Data
);
977 dev
->BaseReg
[1].addr
= getLong(cl
, o
, PCICS_BAR1
);
980 case aoHidd_PCIDevice_Base2
:
983 setLong(cl
, o
, PCICS_BAR2
, tag
->ti_Data
);
984 dev
->BaseReg
[2].addr
= getLong(cl
, o
, PCICS_BAR2
);
988 case aoHidd_PCIDevice_Base3
:
991 setLong(cl
, o
, PCICS_BAR3
, tag
->ti_Data
);
992 dev
->BaseReg
[3].addr
= getLong(cl
, o
, PCICS_BAR3
);
996 case aoHidd_PCIDevice_Base4
:
999 setLong(cl
, o
, PCICS_BAR4
, tag
->ti_Data
);
1000 dev
->BaseReg
[4].addr
= getLong(cl
, o
, PCICS_BAR4
);
1004 case aoHidd_PCIDevice_Base5
:
1007 setLong(cl
, o
, PCICS_BAR5
, tag
->ti_Data
);
1008 dev
->BaseReg
[5].addr
= getLong(cl
, o
, PCICS_BAR5
);
1012 case aoHidd_PCIDevice_RomBase
:
1013 setLong(cl
, o
, PCICS_EXPROM_BASE
, tag
->ti_Data
);
1014 dev
->RomBase
= getLong(cl
, o
, PCICS_EXPROM_BASE
);
1017 case aoHidd_PCIDevice_MemoryBase
:
1018 if (dev
->isBridge
) setWord(cl
, o
, PCIBR_MEMBASE
, tag
->ti_Data
>> 16); break;
1020 case aoHidd_PCIDevice_MemoryLimit
:
1021 if (dev
->isBridge
) setWord(cl
, o
, PCIBR_MEMLIMIT
, tag
->ti_Data
>> 16); break;
1023 case aoHidd_PCIDevice_PrefetchableBase
:
1024 if (dev
->isBridge
) setWord(cl
, o
, PCIBR_PREFETCHBASE
, tag
->ti_Data
>> 16); break;
1026 case aoHidd_PCIDevice_PrefetchableLimit
:
1027 if (dev
->isBridge
) setWord(cl
, o
, PCIBR_PREFETCHLIMIT
, tag
->ti_Data
>> 16); break;
1029 case aoHidd_PCIDevice_IOBase
:
1030 if (dev
->isBridge
) setByte(cl
, o
, PCIBR_IOBASE
, tag
->ti_Data
>> 8); break;
1032 case aoHidd_PCIDevice_IOLimit
:
1033 if (dev
->isBridge
) setByte(cl
, o
, PCIBR_IOLIMIT
, tag
->ti_Data
>> 8); break;
1035 case aoHidd_PCIDevice_isIO
:
1037 UWORD command
= getWord(cl
, o
, PCICS_COMMAND
) & ~PCICMF_IODECODE
;
1039 command
|= PCICMF_IODECODE
;
1040 setWord(cl
, o
, PCICS_COMMAND
, command
);
1044 case aoHidd_PCIDevice_isMEM
:
1046 UWORD command
= getWord(cl
, o
, PCICS_COMMAND
) & ~PCICMF_MEMDECODE
;
1048 command
|= PCICMF_MEMDECODE
;
1049 setWord(cl
, o
, PCICS_COMMAND
, command
);
1053 case aoHidd_PCIDevice_isMaster
:
1055 UWORD command
= getWord(cl
, o
, PCICS_COMMAND
) & ~PCICMF_BUSMASTER
;
1057 command
|= PCICMF_BUSMASTER
;
1058 setWord(cl
, o
, PCICS_COMMAND
, command
);
1062 case aoHidd_PCIDevice_paletteSnoop
:
1064 UWORD command
= getWord(cl
, o
, PCICS_COMMAND
) & ~PCICMF_VGASNOOP
;
1066 command
|= PCICMF_VGASNOOP
;
1067 setWord(cl
, o
, PCICS_COMMAND
, command
);
1071 case aoHidd_PCIDevice_ISAEnable
:
1074 UWORD control
= getWord(cl
, o
, PCIBR_CONTROL
) & ~PCICTRLF_ISAENABLE
;
1076 control
|= PCICTRLF_ISAENABLE
;
1077 setWord(cl
, o
, PCIBR_CONTROL
, control
);
1081 case aoHidd_PCIDevice_VGAEnable
:
1084 UWORD control
= getWord(cl
, o
, PCIBR_CONTROL
) & ~PCICTRLF_VGAENABLE
;
1086 control
|= PCICTRLF_VGAENABLE
;
1087 setWord(cl
, o
, PCIBR_CONTROL
, control
);
1092 bug("[PCIDevice] Trying to set nonsettable attribute %d!\n", idx
);