Don't print warning about unassigned interrupt lines on bridges.
[AROS.git] / rom / hidds / hidd.pci / pcideviceclass.c
blob66b48b8bacf7bb079faefda560f176ea9cf1cb92
1 /*
2 Copyright © 2004-2012, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: PCI device class
6 Lang: English
7 */
9 #include <exec/types.h>
10 #include <hidd/pci.h>
11 #include <oop/oop.h>
12 #include <utility/tagitem.h>
13 #include <proto/exec.h>
14 #include <proto/utility.h>
15 #include <proto/oop.h>
17 #include "pci.h"
18 #include "pciutil.h"
20 #include <aros/debug.h>
22 #undef HiddPCIDeviceAttrBase
23 #define HiddPCIDeviceAttrBase (PSD(cl)->hiddPCIDeviceAB)
24 #undef HiddPCIDriverAttrBase
25 #define HiddPCIDriverAttrBase (PSD(cl)->hiddPCIDriverAB)
27 static void setLong(OOP_Class *cl, OOP_Object *o, ULONG reg, ULONG value)
29 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
30 OOP_Object *driver = dev->driver;
32 struct pHidd_PCIDriver_WriteConfigLong msg;
34 msg.mID = PSD(cl)->mid_WL;
35 msg.bus = dev->bus;
36 msg.dev = dev->dev;
37 msg.sub = dev->sub;
38 msg.reg = reg;
39 msg.val = value;
41 OOP_DoMethod(driver, (OOP_Msg)&msg);
44 static void setWord(OOP_Class *cl, OOP_Object *o, ULONG reg, UWORD value)
46 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
47 OOP_Object *driver = dev->driver;
49 struct pHidd_PCIDriver_WriteConfigWord msg;
51 msg.mID = PSD(cl)->mid_WW;
52 msg.bus = dev->bus;
53 msg.dev = dev->dev;
54 msg.sub = dev->sub;
55 msg.reg = reg;
56 msg.val = value;
58 OOP_DoMethod(driver, (OOP_Msg)&msg);
61 static void setByte(OOP_Class *cl, OOP_Object *o, ULONG reg, UBYTE value)
63 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
64 OOP_Object *driver = dev->driver;
66 struct pHidd_PCIDriver_WriteConfigByte msg;
68 msg.mID = PSD(cl)->mid_WB;
69 msg.bus = dev->bus;
70 msg.dev = dev->dev;
71 msg.sub = dev->sub;
72 msg.reg = reg;
73 msg.val = value;
75 OOP_DoMethod(driver, (OOP_Msg)&msg);
78 static ULONG getLong(OOP_Class *cl, OOP_Object *o, ULONG reg)
80 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
81 OOP_Object *driver = dev->driver;
83 struct pHidd_PCIDriver_ReadConfigLong msg;
85 msg.mID = PSD(cl)->mid_RL;
86 msg.bus = dev->bus;
87 msg.dev = dev->dev;
88 msg.sub = dev->sub;
89 msg.reg = reg;
91 return OOP_DoMethod(driver, (OOP_Msg)&msg);
94 static UWORD getWord(OOP_Class *cl, OOP_Object *o, ULONG reg)
96 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
97 OOP_Object *driver = dev->driver;
99 struct pHidd_PCIDriver_ReadConfigWord msg;
101 msg.mID = PSD(cl)->mid_RW;
102 msg.bus = dev->bus;
103 msg.dev = dev->dev;
104 msg.sub = dev->sub;
105 msg.reg = reg;
107 return OOP_DoMethod(driver, (OOP_Msg)&msg);
110 static UBYTE getByte(OOP_Class *cl, OOP_Object *o, ULONG reg)
112 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
113 OOP_Object *driver = dev->driver;
115 struct pHidd_PCIDriver_ReadConfigByte msg;
117 msg.mID = PSD(cl)->mid_RB;
118 msg.bus = dev->bus;
119 msg.dev = dev->dev;
120 msg.sub = dev->sub;
121 msg.reg = reg;
123 return OOP_DoMethod(driver, (OOP_Msg)&msg);
126 /* Returns offset of capability area in config area or 0 of capability is not present */
127 static UBYTE findCapabilityOffset(OOP_Class * cl, OOP_Object *o, UBYTE capability)
129 UWORD where = 0x34; /* First cap list entry */
130 UBYTE capid = 0;
132 /* Check if capabilities present at all */
133 if ((getWord(cl, o, PCICS_STATUS) & PCISTF_CAPABILITIES) != PCISTF_CAPABILITIES)
134 return 0;
136 /* Iterate over capabilities */
137 while(where < 0xff)
139 where = getByte(cl, o, where);
141 if (where < 0x40)
142 break;
144 where &= ~3;
145 capid = getByte(cl, o, where);
147 if (capid == 0xff)
148 break;
150 if (capid == capability) return (UBYTE)where;
152 where += 1; /* next cap */
155 return 0;
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);
190 PCIDevice::New method is invoked by base pci class. It passes to the device
191 class information about the driver this class should use and location of
192 created device on the PCI bus handled by given driver.
194 OOP_Object *PCIDev__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
196 int i;
198 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
199 if (o)
201 struct TagItem *tag, *tags;
202 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl, o);
203 OOP_Object *driver = NULL;
205 tags=(struct TagItem *)msg->attrList;
208 Get all information passed by pci class calling OOP_NewObject()
210 while((tag = NextTagItem(&tags)))
212 ULONG idx;
214 if (IS_PCIDEV_ATTR(tag->ti_Tag, idx))
216 switch(idx)
218 case aoHidd_PCIDevice_Driver:
219 dev->driver = (OOP_Object*)tag->ti_Data;
220 driver = dev->driver;
221 break;
223 case aoHidd_PCIDevice_Bus:
224 dev->bus = tag->ti_Data;
225 break;
227 case aoHidd_PCIDevice_Dev:
228 dev->dev = tag->ti_Data;
229 break;
231 case aoHidd_PCIDevice_Sub:
232 dev->sub = tag->ti_Data;
233 break;
239 If driver is passed (*HAS TO* be passed) acquire some unchangeable
240 information regarding given device
242 if (driver)
244 UBYTE ht;
247 Get the header type in order to determine whether it is a
248 device or bridge
250 ht = getByte(cl, o, PCICS_HEADERTYPE) & PCIHT_MASK;
251 dev->isBridge = 0;
252 if (ht == PCIHT_BRIDGE)
254 dev->isBridge = 1;
255 dev->subbus = getByte(cl, o, PCIBR_SUBBUS);
258 /* Get all constant ID's */
259 dev->VendorID = getWord(cl, o, PCICS_VENDOR);
260 dev->ProductID = getWord(cl, o, PCICS_PRODUCT);
262 dev->RevisionID = getByte(cl, o, PCICS_REVISION);
263 dev->Interface = getByte(cl, o, PCICS_PROGIF);
264 dev->SubClass = getByte(cl, o, PCICS_SUBCLASS);
265 dev->Class = getByte(cl, o, PCICS_CLASS);
267 dev->SubsysVID = getWord(cl, o, PCICS_SUBVENDOR);
268 dev->SubsystemID = getWord(cl, o, PCICS_SUBSYSTEM);
270 dev->IRQLine = getByte(cl, o, PCICS_INT_PIN);
272 if (dev->IRQLine)
274 dev->INTLine = getByte(cl, o, PCICS_INT_LINE);
276 else dev->INTLine = 0;
278 dev->HeaderType = ht;
280 getPCIClassDesc(dev->Class, dev->SubClass, dev->Interface,
281 &dev->strClass, &dev->strSubClass, &dev->strInterface);
283 /* Satisfy BUG watchers ;) */
284 D(bug("[PCIDevice] %02x.%02x.%x = %04.4lx:%04.4lx (%s %s %s)\n",
285 dev->bus, dev->dev, dev->sub,
286 dev->VendorID, dev->ProductID,
287 dev->strClass, dev->strSubClass, dev->strInterface));
288 D(bug("[PCIDevice] > IRQ %u INT %u\n", dev->IRQLine, dev->INTLine));
290 // print out a warning to the user in case the interrupt line is not assigned by BIOS
291 if (dev->INTLine == 255 && !dev->isBridge)
292 bug("[PCIDevice] WARNING: Interrupt line is not assigned! Device may freeze or malfunction at use!\n");
294 /* Read two first base addresses */
295 for (i = 0; i < 2; i++)
297 dev->BaseReg[i].addr = getLong(cl, o, PCICS_BAR0 + (i << 2));
298 dev->BaseReg[i].size = sizePCIBaseReg(driver, PSD(cl), dev->bus,
299 dev->dev, dev->sub, i);
302 /* Address and size of ROM */
303 dev->RomBase = getLong(cl, o, PCICS_EXPROM_BASE);
304 dev->RomSize = sizePCIBaseReg(driver, PSD(cl), dev->bus,
305 dev->dev, dev->sub, (PCICS_EXPROM_BASE - PCICS_BAR0) >> 2);
308 Bridges specify only first two base addresses. If not bridge,
309 check the rest now
311 if (! dev->isBridge)
313 for (i = 2; i < 6; i++)
315 dev->BaseReg[i].addr = getLong(cl, o, PCICS_BAR0 + (i << 2));
316 dev->BaseReg[i].size = sizePCIBaseReg(driver, PSD(cl), dev->bus,
317 dev->dev, dev->sub, i);
323 return o;
327 PCIDevice::Get method splitted into few parts in order to make switch'es shorter.
330 static void dispatch_generic(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
332 ULONG idx;
333 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
335 idx = msg->attrID - HiddPCIDeviceAttrBase;
337 switch(idx)
339 case aoHidd_PCIDevice_Driver:
340 *msg->storage = (IPTR)dev->driver;
341 break;
343 case aoHidd_PCIDevice_Bus:
344 *msg->storage = (IPTR)dev->bus;
345 break;
347 case aoHidd_PCIDevice_Dev:
348 *msg->storage = (IPTR)dev->dev;
349 break;
351 case aoHidd_PCIDevice_Sub:
352 *msg->storage = (IPTR)dev->sub;
353 break;
355 case aoHidd_PCIDevice_VendorID:
356 *msg->storage = (IPTR)dev->VendorID;
357 break;
359 case aoHidd_PCIDevice_ProductID:
360 *msg->storage = (IPTR)dev->ProductID;
361 break;
363 case aoHidd_PCIDevice_RevisionID:
364 *msg->storage = (IPTR)dev->RevisionID;
365 break;
367 case aoHidd_PCIDevice_Interface:
368 *msg->storage = (IPTR)dev->Interface;
369 break;
371 case aoHidd_PCIDevice_Class:
372 *msg->storage = (IPTR)dev->Class;
373 break;
375 case aoHidd_PCIDevice_SubClass:
376 *msg->storage = (IPTR)dev->SubClass;
377 break;
379 case aoHidd_PCIDevice_SubsystemVendorID:
380 *msg->storage = (IPTR)dev->SubsysVID;
381 break;
383 case aoHidd_PCIDevice_SubsystemID:
384 *msg->storage = (IPTR)dev->SubsystemID;
385 break;
387 case aoHidd_PCIDevice_INTLine:
388 *msg->storage = (IPTR)dev->INTLine;
389 break;
391 case aoHidd_PCIDevice_IRQLine:
392 *msg->storage = (IPTR)dev->IRQLine;
393 break;
395 case aoHidd_PCIDevice_RomBase:
396 *msg->storage = (IPTR)dev->RomBase;
397 break;
399 case aoHidd_PCIDevice_RomSize:
400 *msg->storage = (IPTR)dev->RomSize;
401 break;
405 static void dispatch_base(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
407 ULONG idx,id;
408 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
410 idx = msg->attrID - HiddPCIDeviceAttrBase;
411 id = 0;
413 switch(idx)
415 case aoHidd_PCIDevice_Base0: id = 0; break;
416 case aoHidd_PCIDevice_Base1: id = 1; break;
417 case aoHidd_PCIDevice_Base2: id = 2; break;
418 case aoHidd_PCIDevice_Base3: id = 3; break;
419 case aoHidd_PCIDevice_Base4: id = 4; break;
420 case aoHidd_PCIDevice_Base5: id = 5; break;
423 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
424 if (dev->isBridge && id >= 2) { *msg->storage = 0; return; }
426 *msg->storage = (IPTR)dev->BaseReg[id].addr;
427 if ((dev->BaseReg[id].addr & PCIBAR_MASK_TYPE)==PCIBAR_TYPE_IO)
429 IPTR IOBase = 0;
430 *msg->storage &= PCIBAR_MASK_IO;
431 OOP_GetAttr(dev->driver, aHidd_PCIDriver_IOBase, &IOBase);
432 *msg->storage += IOBase;
434 else
436 *msg->storage &= PCIBAR_MASK_MEM;
440 static void dispatch_type(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
442 ULONG idx,id;
443 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
445 idx = msg->attrID - HiddPCIDeviceAttrBase;
446 id = 0;
448 switch(idx)
450 case aoHidd_PCIDevice_Type0: id = 0; break;
451 case aoHidd_PCIDevice_Type1: id = 1; break;
452 case aoHidd_PCIDevice_Type2: id = 2; break;
453 case aoHidd_PCIDevice_Type3: id = 3; break;
454 case aoHidd_PCIDevice_Type4: id = 4; break;
455 case aoHidd_PCIDevice_Type5: id = 5; break;
458 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
459 if (dev->isBridge && id >= 2) { *msg->storage = 0; return; }
461 *msg->storage = (IPTR)dev->BaseReg[id].addr;
462 if ((dev->BaseReg[id].addr & PCIBAR_MASK_TYPE)==PCIBAR_TYPE_IO)
464 *msg->storage &= ~PCIBAR_MASK_IO;
466 else
468 *msg->storage &= ~PCIBAR_MASK_MEM;
472 static void dispatch_size(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
474 ULONG idx,id;
475 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
477 idx = msg->attrID - HiddPCIDeviceAttrBase;
478 id = 0;
480 switch(idx)
482 case aoHidd_PCIDevice_Size0: id = 0; break;
483 case aoHidd_PCIDevice_Size1: id = 1; break;
484 case aoHidd_PCIDevice_Size2: id = 2; break;
485 case aoHidd_PCIDevice_Size3: id = 3; break;
486 case aoHidd_PCIDevice_Size4: id = 4; break;
487 case aoHidd_PCIDevice_Size5: id = 5; break;
490 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
491 if (dev->isBridge && id >= 2) { *msg->storage = 0; return;}
493 *msg->storage = (IPTR)dev->BaseReg[id].size;
496 static void dispatch_pci2pcibridge(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
498 ULONG idx;
499 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
501 UWORD control;
503 /* If device is not a PCI-PCI bridge, do nothing */
504 if (!dev->isBridge) { *msg->storage = 0; return; }
506 control = getWord(cl, o, PCIBR_CONTROL);
508 idx = msg->attrID - HiddPCIDeviceAttrBase;
510 switch(idx)
512 case aoHidd_PCIDevice_isBridge:
513 *msg->storage = dev->isBridge;
514 break;
516 case aoHidd_PCIDevice_SubBus:
517 *msg->storage = dev->subbus;
518 break;
520 case aoHidd_PCIDevice_MemoryBase:
521 *msg->storage = getWord(cl, o, PCIBR_MEMBASE) << 16;
522 break;
524 case aoHidd_PCIDevice_MemoryLimit:
525 *msg->storage = getWord(cl, o, PCIBR_MEMLIMIT) << 16;
526 break;
528 case aoHidd_PCIDevice_PrefetchableBase:
529 *msg->storage = getWord(cl, o, PCIBR_PREFETCHBASE) << 16;
530 break;
532 case aoHidd_PCIDevice_PrefetchableLimit:
533 *msg->storage = getWord(cl, o, PCIBR_PREFETCHLIMIT) << 16;
534 break;
536 case aoHidd_PCIDevice_IOBase:
537 *msg->storage = getByte(cl, o, PCIBR_IOBASE) << 8;
538 break;
540 case aoHidd_PCIDevice_IOLimit:
541 *msg->storage = getByte(cl, o, PCIBR_IOLIMIT) << 8;
542 break;
544 case aoHidd_PCIDevice_ISAEnable:
545 *msg->storage = (control & PCICTRLF_ISAENABLE) == PCICTRLF_ISAENABLE;
546 break;
548 case aoHidd_PCIDevice_VGAEnable:
549 *msg->storage = (control & PCICTRLF_VGAENABLE) == PCICTRLF_VGAENABLE;
550 break;
554 static void dispatch_capability(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
556 ULONG idx;
557 UBYTE capability = 0;
558 //tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
560 idx = msg->attrID - HiddPCIDeviceAttrBase;
562 switch(idx)
564 case aoHidd_PCIDevice_CapabilityPowerManagement: capability = PCICAP_POWER_MANAGEMENT;break;
565 case aoHidd_PCIDevice_CapabilityAGP: capability = PCICAP_AGP;break;
566 case aoHidd_PCIDevice_CapabilityVitalProductData: capability = PCICAP_VITAL_PRODUCT_DATA;break;
567 case aoHidd_PCIDevice_CapabilitySlotID: capability = PCICAP_SLOT_ID;break;
568 case aoHidd_PCIDevice_CapabilityMSI: capability = PCICAP_MSI;break;
569 case aoHidd_PCIDevice_CapabilityCPCIHotSwap: capability = PCICAP_CPCI_HOT_SWAP;break;
570 case aoHidd_PCIDevice_CapabilityPCIX: capability = PCICAP_PCIX;break;
571 case aoHidd_PCIDevice_CapabilityHyperTransport: capability = PCICAP_HYPER_TRANSPORT;break;
572 case aoHidd_PCIDevice_CapabilityVendorSpecific: capability = PCICAP_VENDOR_SPECIFIC;break;
573 case aoHidd_PCIDevice_CapabilityDebugPort: capability = PCICAP_DEBUG_PORT;break;
574 case aoHidd_PCIDevice_CapabilityCPCICRC: capability = PCICAP_CPCI_CR;break;
575 case aoHidd_PCIDevice_CapabilityHotPlugController: capability = PCICAP_HOT_PLUG_CONTROLLER;break;
576 case aoHidd_PCIDevice_CapabilitySSVPID: capability = PCICAP_SSVPID;break;
577 case aoHidd_PCIDevice_CapabilityAGP3: capability = PCICAP_AGP3;break;
578 case aoHidd_PCIDevice_CapabilityPCIE: capability = PCICAP_PCIE;break;
579 case aoHidd_PCIDevice_CapabilityMSIX: capability = PCICAP_MSIX;break;
580 case aoHidd_PCIDevice_CapabilityAdvancedFeatures: capability = PCICAP_ADVANCED_FEATURES;break;
583 *msg->storage = findCapabilityOffset(cl, o, capability);
586 typedef void (*dispatcher_t)(OOP_Class *, OOP_Object *, struct pRoot_Get *);
588 static const dispatcher_t Dispatcher[num_Hidd_PCIDevice_Attrs] =
590 [aoHidd_PCIDevice_Driver] = dispatch_generic,
591 [aoHidd_PCIDevice_Bus] = dispatch_generic,
592 [aoHidd_PCIDevice_Dev] = dispatch_generic,
593 [aoHidd_PCIDevice_Sub] = dispatch_generic,
594 [aoHidd_PCIDevice_VendorID] = dispatch_generic,
595 [aoHidd_PCIDevice_ProductID] = dispatch_generic,
596 [aoHidd_PCIDevice_RevisionID] = dispatch_generic,
597 [aoHidd_PCIDevice_Interface] = dispatch_generic,
598 [aoHidd_PCIDevice_Class] = dispatch_generic,
599 [aoHidd_PCIDevice_SubClass] = dispatch_generic,
600 [aoHidd_PCIDevice_SubsystemVendorID] = dispatch_generic,
601 [aoHidd_PCIDevice_SubsystemID] = dispatch_generic,
602 [aoHidd_PCIDevice_INTLine] = dispatch_generic,
603 [aoHidd_PCIDevice_IRQLine] = dispatch_generic,
604 [aoHidd_PCIDevice_RomBase] = dispatch_generic,
605 [aoHidd_PCIDevice_RomSize] = dispatch_generic,
606 [aoHidd_PCIDevice_Base0] = dispatch_base,
607 [aoHidd_PCIDevice_Base1] = dispatch_base,
608 [aoHidd_PCIDevice_Base2] = dispatch_base,
609 [aoHidd_PCIDevice_Base3] = dispatch_base,
610 [aoHidd_PCIDevice_Base4] = dispatch_base,
611 [aoHidd_PCIDevice_Base5] = dispatch_base,
612 [aoHidd_PCIDevice_Size0] = dispatch_size,
613 [aoHidd_PCIDevice_Size1] = dispatch_size,
614 [aoHidd_PCIDevice_Size2] = dispatch_size,
615 [aoHidd_PCIDevice_Size3] = dispatch_size,
616 [aoHidd_PCIDevice_Size4] = dispatch_size,
617 [aoHidd_PCIDevice_Size5] = dispatch_size,
618 [aoHidd_PCIDevice_Type0] = dispatch_type,
619 [aoHidd_PCIDevice_Type1] = dispatch_type,
620 [aoHidd_PCIDevice_Type2] = dispatch_type,
621 [aoHidd_PCIDevice_Type3] = dispatch_type,
622 [aoHidd_PCIDevice_Type4] = dispatch_type,
623 [aoHidd_PCIDevice_Type5] = dispatch_type,
625 /* Bridge attributes */
626 [aoHidd_PCIDevice_isBridge] = dispatch_pci2pcibridge,
627 [aoHidd_PCIDevice_SubBus] = dispatch_pci2pcibridge,
628 [aoHidd_PCIDevice_MemoryBase] = dispatch_pci2pcibridge,
629 [aoHidd_PCIDevice_MemoryLimit] = dispatch_pci2pcibridge,
630 [aoHidd_PCIDevice_PrefetchableBase] = dispatch_pci2pcibridge,
631 [aoHidd_PCIDevice_PrefetchableLimit] = dispatch_pci2pcibridge,
632 [aoHidd_PCIDevice_IOBase] = dispatch_pci2pcibridge,
633 [aoHidd_PCIDevice_IOLimit] = dispatch_pci2pcibridge,
634 [aoHidd_PCIDevice_ISAEnable] = dispatch_pci2pcibridge,
635 [aoHidd_PCIDevice_VGAEnable] = dispatch_pci2pcibridge,
637 /* Capabilities */
638 [aoHidd_PCIDevice_CapabilityPowerManagement] = dispatch_capability,
639 [aoHidd_PCIDevice_CapabilityAGP] = dispatch_capability,
640 [aoHidd_PCIDevice_CapabilityVitalProductData] = dispatch_capability,
641 [aoHidd_PCIDevice_CapabilitySlotID] = dispatch_capability,
642 [aoHidd_PCIDevice_CapabilityMSI] = dispatch_capability,
643 [aoHidd_PCIDevice_CapabilityCPCIHotSwap] = dispatch_capability,
644 [aoHidd_PCIDevice_CapabilityPCIX] = dispatch_capability,
645 [aoHidd_PCIDevice_CapabilityHyperTransport] = dispatch_capability,
646 [aoHidd_PCIDevice_CapabilityVendorSpecific] = dispatch_capability,
647 [aoHidd_PCIDevice_CapabilityDebugPort] = dispatch_capability,
648 [aoHidd_PCIDevice_CapabilityCPCICRC] = dispatch_capability,
649 [aoHidd_PCIDevice_CapabilityHotPlugController] = dispatch_capability,
650 [aoHidd_PCIDevice_CapabilitySSVPID] = dispatch_capability,
651 [aoHidd_PCIDevice_CapabilityAGP3] = dispatch_capability,
652 [aoHidd_PCIDevice_CapabilityPCIE] = dispatch_capability,
653 [aoHidd_PCIDevice_CapabilityMSIX] = dispatch_capability,
654 [aoHidd_PCIDevice_CapabilityAdvancedFeatures] = dispatch_capability,
657 void PCIDev__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
659 ULONG idx;
660 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
662 if (IS_PCIDEV_ATTR(msg->attrID, idx))
664 if (Dispatcher[idx] != NULL)
665 Dispatcher[idx](cl, o, msg);
666 else switch(idx)
668 case aoHidd_PCIDevice_isMEM:
669 *msg->storage = (
670 (getWord(cl, o, PCICS_COMMAND) &
671 PCICMF_MEMDECODE)
672 == PCICMF_MEMDECODE);
673 break;
675 case aoHidd_PCIDevice_isIO:
676 *msg->storage = (
677 (getWord(cl, o, PCICS_COMMAND) &
678 PCICMF_IODECODE)
679 == PCICMF_IODECODE);
680 break;
682 case aoHidd_PCIDevice_isMaster:
683 *msg->storage = (
684 (getWord(cl, o, PCICS_COMMAND) &
685 PCICMF_BUSMASTER)
686 == PCICMF_BUSMASTER);
687 break;
689 case aoHidd_PCIDevice_paletteSnoop:
690 *msg->storage = (
691 (getWord(cl, o, PCICS_COMMAND) &
692 PCICMF_VGASNOOP)
693 == PCICMF_VGASNOOP);
694 break;
696 case aoHidd_PCIDevice_is66MHz:
697 *msg->storage = (
698 (getWord(cl, o, PCICS_STATUS) &
699 PCISTF_66MHZ)
700 == PCISTF_66MHZ);
701 break;
703 case aoHidd_PCIDevice_ClassDesc:
704 *msg->storage = (IPTR)dev->strClass;
705 break;
707 case aoHidd_PCIDevice_SubClassDesc:
708 *msg->storage = (IPTR)dev->strSubClass;
709 break;
711 case aoHidd_PCIDevice_InterfaceDesc:
712 *msg->storage = (IPTR)dev->strInterface;
713 break;
714 case aoHidd_PCIDevice_IRQStatus:
715 *msg->storage = (
716 (getWord(cl, o, PCICS_STATUS) &
717 PCISTF_INTERRUPT_STATUS)
718 == PCISTF_INTERRUPT_STATUS);
719 break;
720 case aoHidd_PCIDevice_CapabilitiesPresent:
721 *msg->storage = (
722 (getWord(cl, o, PCICS_STATUS) &
723 PCISTF_CAPABILITIES)
724 == PCISTF_CAPABILITIES);
725 break;
727 default:
728 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
729 break;
732 else
734 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
738 void PCIDev__Root__Set(OOP_Class *cl, OOP_Object *o, struct pRoot_Set *msg)
740 ULONG idx;
741 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
742 struct TagItem *tag, *tags;
744 tags = (struct TagItem *)msg->attrList;
746 while ((tag = NextTagItem(&tags)))
748 if (IS_PCIDEV_ATTR(tag->ti_Tag, idx))
750 switch(idx)
752 case aoHidd_PCIDevice_Base0:
753 setLong(cl, o, PCICS_BAR0, tag->ti_Data);
754 dev->BaseReg[0].addr = getLong(cl, o, PCICS_BAR0);
755 break;
757 case aoHidd_PCIDevice_Base1:
758 setLong(cl, o, PCICS_BAR1, tag->ti_Data);
759 dev->BaseReg[1].addr = getLong(cl, o, PCICS_BAR1);
760 break;
762 case aoHidd_PCIDevice_Base2:
763 if (!dev->isBridge)
765 setLong(cl, o, PCICS_BAR2, tag->ti_Data);
766 dev->BaseReg[2].addr = getLong(cl, o, PCICS_BAR2);
768 break;
770 case aoHidd_PCIDevice_Base3:
771 if (!dev->isBridge)
773 setLong(cl, o, PCICS_BAR3, tag->ti_Data);
774 dev->BaseReg[3].addr = getLong(cl, o, PCICS_BAR3);
776 break;
778 case aoHidd_PCIDevice_Base4:
779 if (!dev->isBridge)
781 setLong(cl, o, PCICS_BAR4, tag->ti_Data);
782 dev->BaseReg[4].addr = getLong(cl, o, PCICS_BAR4);
784 break;
786 case aoHidd_PCIDevice_Base5:
787 if (!dev->isBridge)
789 setLong(cl, o, PCICS_BAR5, tag->ti_Data);
790 dev->BaseReg[5].addr = getLong(cl, o, PCICS_BAR5);
792 break;
794 case aoHidd_PCIDevice_RomBase:
795 setLong(cl, o, PCICS_EXPROM_BASE, tag->ti_Data);
796 dev->RomBase = getLong(cl, o, PCICS_EXPROM_BASE);
797 break;
799 case aoHidd_PCIDevice_MemoryBase:
800 if (dev->isBridge) setWord(cl, o, PCIBR_MEMBASE, tag->ti_Data >> 16); break;
802 case aoHidd_PCIDevice_MemoryLimit:
803 if (dev->isBridge) setWord(cl, o, PCIBR_MEMLIMIT, tag->ti_Data >> 16); break;
805 case aoHidd_PCIDevice_PrefetchableBase:
806 if (dev->isBridge) setWord(cl, o, PCIBR_PREFETCHBASE, tag->ti_Data >> 16); break;
808 case aoHidd_PCIDevice_PrefetchableLimit:
809 if (dev->isBridge) setWord(cl, o, PCIBR_PREFETCHLIMIT, tag->ti_Data >> 16); break;
811 case aoHidd_PCIDevice_IOBase:
812 if (dev->isBridge) setByte(cl, o, PCIBR_IOBASE, tag->ti_Data >> 8); break;
814 case aoHidd_PCIDevice_IOLimit:
815 if (dev->isBridge) setByte(cl, o, PCIBR_IOLIMIT, tag->ti_Data >> 8); break;
817 case aoHidd_PCIDevice_isIO:
819 UWORD command = getWord(cl, o, PCICS_COMMAND) & ~PCICMF_IODECODE;
820 if (tag->ti_Data)
821 command |= PCICMF_IODECODE;
822 setWord(cl, o, PCICS_COMMAND, command);
824 break;
826 case aoHidd_PCIDevice_isMEM:
828 UWORD command = getWord(cl, o, PCICS_COMMAND) & ~PCICMF_MEMDECODE;
829 if (tag->ti_Data)
830 command |= PCICMF_MEMDECODE;
831 setWord(cl, o, PCICS_COMMAND, command);
833 break;
835 case aoHidd_PCIDevice_isMaster:
837 UWORD command = getWord(cl, o, PCICS_COMMAND) & ~PCICMF_BUSMASTER;
838 if (tag->ti_Data)
839 command |= PCICMF_BUSMASTER;
840 setWord(cl, o, PCICS_COMMAND, command);
842 break;
844 case aoHidd_PCIDevice_paletteSnoop:
846 UWORD command = getWord(cl, o, PCICS_COMMAND) & ~PCICMF_VGASNOOP;
847 if (tag->ti_Data)
848 command |= PCICMF_VGASNOOP;
849 setWord(cl, o, PCICS_COMMAND, command);
851 break;
853 case aoHidd_PCIDevice_ISAEnable:
854 if (dev->isBridge)
856 UWORD control = getWord(cl, o, PCIBR_CONTROL) & ~PCICTRLF_ISAENABLE;
857 if (tag->ti_Data)
858 control |= PCICTRLF_ISAENABLE;
859 setWord(cl, o, PCIBR_CONTROL, control);
861 break;
863 case aoHidd_PCIDevice_VGAEnable:
864 if (dev->isBridge)
866 UWORD control = getWord(cl, o, PCIBR_CONTROL) & ~PCICTRLF_VGAENABLE;
867 if (tag->ti_Data)
868 control |= PCICTRLF_VGAENABLE;
869 setWord(cl, o, PCIBR_CONTROL, control);
871 break;
873 default:
874 bug("[PCIDevice] Trying to set nonsettable attribute %d!\n", idx);
875 break;