make the linux-ppc packags be in synch with other platforms
[tangerine.git] / arch / common / hidd.pci / pcideviceclass.c
blob71e7534070cf7c16c3ae17f46acabe074bf71568
1 /*
2 Copyright © 2004-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: PCI device class
6 Lang: English
7 */
9 /*
10 * 2008-03-30 T. Wiszkowski Corrected typo and added InterruptStatus, CapabilitiesPresent attributes
13 #include <exec/types.h>
14 #include <hidd/pci.h>
15 #include <oop/oop.h>
17 #include <utility/tagitem.h>
19 #include <proto/exec.h>
20 #include <proto/utility.h>
21 #include <proto/oop.h>
23 #include "pci.h"
24 #include "pciutil.h"
26 #define DEBUG 1
27 #include <aros/debug.h>
29 #ifdef HiddPCIDeviceAttrBase
30 #undef HiddPCIDeviceAttrBase
31 #endif // HiddPCIDeviceAttrBase
33 #define HiddPCIDeviceAttrBase (PSD(cl)->hiddPCIDeviceAB)
35 static void setLong(OOP_Class *cl, OOP_Object *o, ULONG reg, ULONG value)
37 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
38 OOP_Object *driver = dev->driver;
40 struct pHidd_PCIDriver_WriteConfigLong msg;
42 msg.mID = PSD(cl)->mid_WL;
43 msg.bus = dev->bus;
44 msg.dev = dev->dev;
45 msg.sub = dev->sub;
46 msg.reg = reg;
47 msg.val = value;
49 OOP_DoMethod(driver, (OOP_Msg)&msg);
52 static void setWord(OOP_Class *cl, OOP_Object *o, ULONG reg, UWORD value)
54 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
55 OOP_Object *driver = dev->driver;
57 struct pHidd_PCIDriver_WriteConfigWord msg;
59 msg.mID = PSD(cl)->mid_WW;
60 msg.bus = dev->bus;
61 msg.dev = dev->dev;
62 msg.sub = dev->sub;
63 msg.reg = reg;
64 msg.val = value;
66 OOP_DoMethod(driver, (OOP_Msg)&msg);
69 static void setByte(OOP_Class *cl, OOP_Object *o, ULONG reg, UBYTE value)
71 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
72 OOP_Object *driver = dev->driver;
74 struct pHidd_PCIDriver_WriteConfigByte msg;
76 msg.mID = PSD(cl)->mid_WB;
77 msg.bus = dev->bus;
78 msg.dev = dev->dev;
79 msg.sub = dev->sub;
80 msg.reg = reg;
81 msg.val = value;
83 OOP_DoMethod(driver, (OOP_Msg)&msg);
86 static ULONG getLong(OOP_Class *cl, OOP_Object *o, ULONG reg)
88 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
89 OOP_Object *driver = dev->driver;
91 struct pHidd_PCIDriver_ReadConfigLong msg;
93 msg.mID = PSD(cl)->mid_RL;
94 msg.bus = dev->bus;
95 msg.dev = dev->dev;
96 msg.sub = dev->sub;
97 msg.reg = reg;
99 return OOP_DoMethod(driver, (OOP_Msg)&msg);
102 static UWORD getWord(OOP_Class *cl, OOP_Object *o, ULONG reg)
104 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
105 OOP_Object *driver = dev->driver;
107 struct pHidd_PCIDriver_ReadConfigWord msg;
109 msg.mID = PSD(cl)->mid_RW;
110 msg.bus = dev->bus;
111 msg.dev = dev->dev;
112 msg.sub = dev->sub;
113 msg.reg = reg;
115 return OOP_DoMethod(driver, (OOP_Msg)&msg);
118 static UBYTE getByte(OOP_Class *cl, OOP_Object *o, ULONG reg)
120 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
121 OOP_Object *driver = dev->driver;
123 struct pHidd_PCIDriver_ReadConfigByte msg;
125 msg.mID = PSD(cl)->mid_RB;
126 msg.bus = dev->bus;
127 msg.dev = dev->dev;
128 msg.sub = dev->sub;
129 msg.reg = reg;
131 return OOP_DoMethod(driver, (OOP_Msg)&msg);
134 UBYTE PCIDev__Hidd_PCIDevice__ReadConfigByte(OOP_Class *cl, OOP_Object *o, struct pHidd_PCIDevice_ReadConfigByte *msg)
136 return getByte(cl, o, msg->reg);
139 UWORD PCIDev__Hidd_PCIDevice__ReadConfigWord(OOP_Class *cl, OOP_Object *o, struct pHidd_PCIDevice_ReadConfigWord *msg)
141 return getWord(cl, o, msg->reg);
144 UBYTE PCIDev__Hidd_PCIDevice__ReadConfigLong(OOP_Class *cl, OOP_Object *o, struct pHidd_PCIDevice_ReadConfigLong *msg)
146 return getLong(cl, o, msg->reg);
149 VOID PCIDev__Hidd_PCIDevice__WriteConfigByte(OOP_Class *cl, OOP_Object *o, struct pHidd_PCIDevice_WriteConfigByte *msg)
151 setByte(cl, o, msg->reg, msg->val);
154 VOID PCIDev__Hidd_PCIDevice__WriteConfigWord(OOP_Class *cl, OOP_Object *o, struct pHidd_PCIDevice_WriteConfigWord *msg)
156 setWord(cl, o, msg->reg, msg->val);
159 VOID PCIDev__Hidd_PCIDevice__WriteConfigLong(OOP_Class *cl, OOP_Object *o, struct pHidd_PCIDevice_WriteConfigLong *msg)
161 setLong(cl, o, msg->reg, msg->val);
166 PCIDevice::New method is invoked by base pci class. It passes to the device
167 class information about the driver this class should use and location of
168 created device on the PCI bus handled by given driver.
170 OOP_Object *PCIDev__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
172 int i;
174 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
175 if (o)
177 struct TagItem *tags, *tag;
178 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl, o);
179 OOP_Object *driver = NULL;
181 tags=msg->attrList;
184 Get all information passed by pci class calling OOP_NewObject()
186 while((tag = NextTagItem((struct TagItem **)&tags)))
188 ULONG idx;
190 if (IS_PCIDEV_ATTR(tag->ti_Tag, idx))
192 switch(idx)
194 case aoHidd_PCIDevice_Driver:
195 dev->driver = (OOP_Object*)tag->ti_Data;
196 driver = dev->driver;
197 break;
199 case aoHidd_PCIDevice_Bus:
200 dev->bus = tag->ti_Data;
201 break;
203 case aoHidd_PCIDevice_Dev:
204 dev->dev = tag->ti_Data;
205 break;
207 case aoHidd_PCIDevice_Sub:
208 dev->sub = tag->ti_Data;
209 break;
215 If driver is passed (*HAS TO* be passed) acquire some unchangeable
216 information regarding given device
218 if (driver)
220 UBYTE ht;
223 Get the header type in order to determine whether it is a
224 device or bridge
226 ht = getByte(cl, o, PCICS_HEADERTYPE) & PCIHT_MASK;
227 dev->isBridge = 0;
228 if (ht == PCIHT_BRIDGE)
230 dev->isBridge = 1;
231 dev->subbus = getByte(cl, o, PCIBR_SUBBUS);
234 /* Get all constant ID's */
235 dev->VendorID = getWord(cl, o, PCICS_VENDOR);
236 dev->ProductID = getWord(cl, o, PCICS_PRODUCT);
238 dev->RevisionID = getByte(cl, o, PCICS_REVISION);
239 dev->Interface = getByte(cl, o, PCICS_PROGIF);
240 dev->SubClass = getByte(cl, o, PCICS_SUBCLASS);
241 dev->Class = getByte(cl, o, PCICS_CLASS);
243 dev->SubsysVID = getWord(cl, o, PCICS_SUBVENDOR);
244 dev->SubsystemID = getWord(cl, o, PCICS_SUBSYSTEM);
246 dev->IRQLine = getByte(cl, o, PCICS_INT_PIN);
248 if (dev->IRQLine)
250 dev->INTLine = getByte(cl, o, PCICS_INT_LINE);
252 else dev->INTLine = 0;
254 dev->HeaderType = ht;
256 getPCIClassDesc(dev->Class, dev->SubClass, dev->Interface,
257 &dev->strClass, &dev->strSubClass, &dev->strInterface);
259 /* Satisfy BUG watchers ;) */
260 D(bug("[PCIDevice] %02x.%02x.%x = %04.4lx:%04.4lx (%s %s %s)\n",
261 dev->bus, dev->dev, dev->sub,
262 dev->VendorID, dev->ProductID,
263 dev->strClass, dev->strSubClass, dev->strInterface));
265 /* Read two first base addresses */
266 for (i = 0; i < 2; i++)
268 dev->BaseReg[i].addr = getLong(cl, o, PCICS_BAR0 + (i << 2));
269 dev->BaseReg[i].size = sizePCIBaseReg(driver, PSD(cl), dev->bus,
270 dev->dev, dev->sub, i);
273 /* Address and size of ROM */
274 dev->RomBase = getLong(cl, o, PCICS_EXPROM_BASE);
275 dev->RomSize = sizePCIBaseReg(driver, PSD(cl), dev->bus,
276 dev->dev, dev->sub, (PCICS_EXPROM_BASE - PCICS_BAR0) >> 2);
279 Bridges specify only first two base addresses. If not bridge,
280 check the rest now
282 if (! dev->isBridge)
284 for (i = 2; i < 6; i++)
286 dev->BaseReg[i].addr = getLong(cl, o, PCICS_BAR0 + (i << 2));
287 dev->BaseReg[i].size = sizePCIBaseReg(driver, PSD(cl), dev->bus,
288 dev->dev, dev->sub, i);
294 return o;
298 PCIDevice::Get method splitted into few parts in order to make switch'es shorter.
301 static const void dispatch_generic(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
303 ULONG idx;
304 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
306 idx = msg->attrID - HiddPCIDeviceAttrBase;
308 switch(idx)
310 case aoHidd_PCIDevice_Driver:
311 *msg->storage = (IPTR)dev->driver;
312 break;
314 case aoHidd_PCIDevice_Bus:
315 *msg->storage = (IPTR)dev->bus;
316 break;
318 case aoHidd_PCIDevice_Dev:
319 *msg->storage = (IPTR)dev->dev;
320 break;
322 case aoHidd_PCIDevice_Sub:
323 *msg->storage = (IPTR)dev->sub;
324 break;
326 case aoHidd_PCIDevice_VendorID:
327 *msg->storage = (IPTR)dev->VendorID;
328 break;
330 case aoHidd_PCIDevice_ProductID:
331 *msg->storage = (IPTR)dev->ProductID;
332 break;
334 case aoHidd_PCIDevice_RevisionID:
335 *msg->storage = (IPTR)dev->RevisionID;
336 break;
338 case aoHidd_PCIDevice_Interface:
339 *msg->storage = (IPTR)dev->Interface;
340 break;
342 case aoHidd_PCIDevice_Class:
343 *msg->storage = (IPTR)dev->Class;
344 break;
346 case aoHidd_PCIDevice_SubClass:
347 *msg->storage = (IPTR)dev->SubClass;
348 break;
350 case aoHidd_PCIDevice_SubsystemVendorID:
351 *msg->storage = (IPTR)dev->SubsysVID;
352 break;
354 case aoHidd_PCIDevice_SubsystemID:
355 *msg->storage = (IPTR)dev->SubsystemID;
356 break;
358 case aoHidd_PCIDevice_INTLine:
359 *msg->storage = (IPTR)dev->INTLine;
360 break;
362 case aoHidd_PCIDevice_IRQLine:
363 *msg->storage = (IPTR)dev->IRQLine;
364 break;
366 case aoHidd_PCIDevice_RomBase:
367 *msg->storage = (IPTR)dev->RomBase;
368 break;
370 case aoHidd_PCIDevice_RomSize:
371 *msg->storage = (IPTR)dev->RomSize;
372 break;
376 static const void dispatch_base(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
378 ULONG idx,id;
379 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
381 idx = msg->attrID - HiddPCIDeviceAttrBase;
382 id = 0;
384 switch(idx)
386 case aoHidd_PCIDevice_Base0: id = 0; break;
387 case aoHidd_PCIDevice_Base1: id = 1; break;
388 case aoHidd_PCIDevice_Base2: id = 2; break;
389 case aoHidd_PCIDevice_Base3: id = 3; break;
390 case aoHidd_PCIDevice_Base4: id = 4; break;
391 case aoHidd_PCIDevice_Base5: id = 5; break;
394 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
395 if (dev->isBridge && id >= 2) { *msg->storage = 0; return; }
397 *msg->storage = (IPTR)dev->BaseReg[id].addr;
398 if ((dev->BaseReg[id].addr & PCIBAR_MASK_TYPE)==PCIBAR_TYPE_IO)
400 *msg->storage &= PCIBAR_MASK_IO;
402 else
404 *msg->storage &= PCIBAR_MASK_MEM;
408 static const void dispatch_type(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
410 ULONG idx,id;
411 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
413 idx = msg->attrID - HiddPCIDeviceAttrBase;
414 id = 0;
416 switch(idx)
418 case aoHidd_PCIDevice_Type0: id = 0; break;
419 case aoHidd_PCIDevice_Type1: id = 1; break;
420 case aoHidd_PCIDevice_Type2: id = 2; break;
421 case aoHidd_PCIDevice_Type3: id = 3; break;
422 case aoHidd_PCIDevice_Type4: id = 4; break;
423 case aoHidd_PCIDevice_Type5: id = 5; break;
426 /* Do not allow reading of more than two base addresses in case of PCI-PCI bridges */
427 if (dev->isBridge && id >= 2) { *msg->storage = 0; return; }
429 *msg->storage = (IPTR)dev->BaseReg[id].addr;
430 if ((dev->BaseReg[id].addr & PCIBAR_MASK_TYPE)==PCIBAR_TYPE_IO)
432 *msg->storage &= ~PCIBAR_MASK_IO;
434 else
436 *msg->storage &= ~PCIBAR_MASK_MEM;
440 static const void dispatch_size(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_Size0: id = 0; break;
451 case aoHidd_PCIDevice_Size1: id = 1; break;
452 case aoHidd_PCIDevice_Size2: id = 2; break;
453 case aoHidd_PCIDevice_Size3: id = 3; break;
454 case aoHidd_PCIDevice_Size4: id = 4; break;
455 case aoHidd_PCIDevice_Size5: 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].size;
464 static const void dispatch_pci2pcibridge(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
466 ULONG idx;
467 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
469 UWORD control;
471 /* If device is not a PCI-PCI bridge, do nothing */
472 if (!dev->isBridge) { *msg->storage = 0; return; }
474 control = getWord(cl, o, PCIBR_CONTROL);
476 idx = msg->attrID - HiddPCIDeviceAttrBase;
478 switch(idx)
480 case aoHidd_PCIDevice_isBridge:
481 *msg->storage = dev->isBridge;
482 break;
484 case aoHidd_PCIDevice_SubBus:
485 *msg->storage = dev->subbus;
486 break;
488 case aoHidd_PCIDevice_MemoryBase:
489 *msg->storage = getWord(cl, o, PCIBR_MEMBASE) << 16;
490 break;
492 case aoHidd_PCIDevice_MemoryLimit:
493 *msg->storage = getWord(cl, o, PCIBR_MEMLIMIT) << 16;
494 break;
496 case aoHidd_PCIDevice_PrefetchableBase:
497 *msg->storage = getWord(cl, o, PCIBR_PREFETCHBASE) << 16;
498 break;
500 case aoHidd_PCIDevice_PrefetchableLimit:
501 *msg->storage = getWord(cl, o, PCIBR_PREFETCHLIMIT) << 16;
502 break;
504 case aoHidd_PCIDevice_IOBase:
505 *msg->storage = getByte(cl, o, PCIBR_IOBASE) << 8;
506 break;
508 case aoHidd_PCIDevice_IOLimit:
509 *msg->storage = getByte(cl, o, PCIBR_IOLIMIT) << 8;
510 break;
512 case aoHidd_PCIDevice_ISAEnable:
513 *msg->storage = (control & PCICTRLF_ISAENABLE) == PCICTRLF_ISAENABLE;
514 break;
516 case aoHidd_PCIDevice_VGAEnable:
517 *msg->storage = (control & PCICTRLF_VGAENABLE) == PCICTRLF_VGAENABLE;
518 break;
522 const static void (*Dispatcher[num_Hidd_PCIDevice_Attrs])(OOP_Class *, OOP_Object *, struct pRoot_Get *) __attribute__((section(".rodata"))) =
524 [aoHidd_PCIDevice_Driver] = dispatch_generic,
525 [aoHidd_PCIDevice_Bus] = dispatch_generic,
526 [aoHidd_PCIDevice_Dev] = dispatch_generic,
527 [aoHidd_PCIDevice_Sub] = dispatch_generic,
528 [aoHidd_PCIDevice_VendorID] = dispatch_generic,
529 [aoHidd_PCIDevice_ProductID] = dispatch_generic,
530 [aoHidd_PCIDevice_RevisionID] = dispatch_generic,
531 [aoHidd_PCIDevice_Interface] = dispatch_generic,
532 [aoHidd_PCIDevice_Class] = dispatch_generic,
533 [aoHidd_PCIDevice_SubClass] = dispatch_generic,
534 [aoHidd_PCIDevice_SubsystemVendorID] = dispatch_generic,
535 [aoHidd_PCIDevice_SubsystemID] = dispatch_generic,
536 [aoHidd_PCIDevice_INTLine] = dispatch_generic,
537 [aoHidd_PCIDevice_IRQLine] = dispatch_generic,
538 [aoHidd_PCIDevice_RomBase] = dispatch_generic,
539 [aoHidd_PCIDevice_RomSize] = dispatch_generic,
540 [aoHidd_PCIDevice_Base0] = dispatch_base,
541 [aoHidd_PCIDevice_Base1] = dispatch_base,
542 [aoHidd_PCIDevice_Base2] = dispatch_base,
543 [aoHidd_PCIDevice_Base3] = dispatch_base,
544 [aoHidd_PCIDevice_Base4] = dispatch_base,
545 [aoHidd_PCIDevice_Base5] = dispatch_base,
546 [aoHidd_PCIDevice_Size0] = dispatch_size,
547 [aoHidd_PCIDevice_Size1] = dispatch_size,
548 [aoHidd_PCIDevice_Size2] = dispatch_size,
549 [aoHidd_PCIDevice_Size3] = dispatch_size,
550 [aoHidd_PCIDevice_Size4] = dispatch_size,
551 [aoHidd_PCIDevice_Size5] = dispatch_size,
552 [aoHidd_PCIDevice_Type0] = dispatch_type,
553 [aoHidd_PCIDevice_Type1] = dispatch_type,
554 [aoHidd_PCIDevice_Type2] = dispatch_type,
555 [aoHidd_PCIDevice_Type3] = dispatch_type,
556 [aoHidd_PCIDevice_Type4] = dispatch_type,
557 [aoHidd_PCIDevice_Type5] = dispatch_type,
559 /* Bridge attributes */
560 [aoHidd_PCIDevice_isBridge] = dispatch_pci2pcibridge,
561 [aoHidd_PCIDevice_SubBus] = dispatch_pci2pcibridge,
562 [aoHidd_PCIDevice_MemoryBase] = dispatch_pci2pcibridge,
563 [aoHidd_PCIDevice_MemoryLimit] = dispatch_pci2pcibridge,
564 [aoHidd_PCIDevice_PrefetchableBase] = dispatch_pci2pcibridge,
565 [aoHidd_PCIDevice_PrefetchableLimit] = dispatch_pci2pcibridge,
566 [aoHidd_PCIDevice_IOBase] = dispatch_pci2pcibridge,
567 [aoHidd_PCIDevice_IOLimit] = dispatch_pci2pcibridge,
568 [aoHidd_PCIDevice_ISAEnable] = dispatch_pci2pcibridge,
569 [aoHidd_PCIDevice_VGAEnable] = dispatch_pci2pcibridge,
573 void PCIDev__Root__Get(OOP_Class *cl, OOP_Object *o, struct pRoot_Get *msg)
575 ULONG idx;
576 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
578 if (IS_PCIDEV_ATTR(msg->attrID, idx))
580 if (Dispatcher[idx] != NULL)
581 Dispatcher[idx](cl, o, msg);
582 else switch(idx)
584 case aoHidd_PCIDevice_isMEM:
585 *msg->storage = (
586 (getWord(cl, o, PCICS_COMMAND) &
587 PCICMF_MEMDECODE)
588 == PCICMF_MEMDECODE);
589 break;
591 case aoHidd_PCIDevice_isIO:
592 *msg->storage = (
593 (getWord(cl, o, PCICS_COMMAND) &
594 PCICMF_IODECODE)
595 == PCICMF_IODECODE);
596 break;
598 case aoHidd_PCIDevice_isMaster:
599 *msg->storage = (
600 (getWord(cl, o, PCICS_COMMAND) &
601 PCICMF_BUSMASTER)
602 == PCICMF_BUSMASTER);
603 break;
605 case aoHidd_PCIDevice_paletteSnoop:
606 *msg->storage = (
607 (getWord(cl, o, PCICS_COMMAND) &
608 PCICMF_VGASNOOP)
609 == PCICMF_VGASNOOP);
610 break;
612 case aoHidd_PCIDevice_is66MHz:
613 *msg->storage = (
614 (getWord(cl, o, PCICS_STATUS) &
615 PCISTF_66MHZ)
616 == PCISTF_66MHZ);
617 break;
619 case aoHidd_PCIDevice_ClassDesc:
620 *msg->storage = (IPTR)dev->strClass;
621 break;
623 case aoHidd_PCIDevice_SubClassDesc:
624 *msg->storage = (IPTR)dev->strSubClass;
625 break;
627 case aoHidd_PCIDevice_InterfaceDesc:
628 *msg->storage = (IPTR)dev->strInterface;
629 break;
631 case aoHidd_PCIDevice_IRQStatus:
632 *msg->storage = (
633 (getWord(cl, o, PCICS_STATUS) &
634 PCISTF_INTERRUPT_STATUS)
635 == PCISTF_INTERRUPT_STATUS);
636 break;
638 case aoHidd_PCIDevice_CapabilitiesPresent:
639 *msg->storage = (
640 (getWord(cl, o, PCICS_STATUS) &
641 PCISTF_CAPABILITIES)
642 == PCISTF_CAPABILITIES);
643 break;
645 default:
646 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
647 break;
650 else
652 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
656 void PCIDev__Root__Set(OOP_Class *cl, OOP_Object *o, struct pRoot_Set *msg)
658 ULONG idx;
659 tDeviceData *dev = (tDeviceData *)OOP_INST_DATA(cl,o);
660 struct TagItem *tags, *tag;
662 tags = msg->attrList;
664 while ((tag = NextTagItem(&tags)))
666 if (IS_PCIDEV_ATTR(tag->ti_Tag, idx))
668 switch(idx)
670 case aoHidd_PCIDevice_Base0:
671 setLong(cl, o, PCICS_BAR0, tag->ti_Data);
672 dev->BaseReg[0].addr = getLong(cl, o, PCICS_BAR0);
673 break;
675 case aoHidd_PCIDevice_Base1:
676 setLong(cl, o, PCICS_BAR1, tag->ti_Data);
677 dev->BaseReg[1].addr = getLong(cl, o, PCICS_BAR1);
678 break;
680 case aoHidd_PCIDevice_Base2:
681 if (!dev->isBridge)
683 setLong(cl, o, PCICS_BAR2, tag->ti_Data);
684 dev->BaseReg[2].addr = getLong(cl, o, PCICS_BAR2);
686 break;
688 case aoHidd_PCIDevice_Base3:
689 if (!dev->isBridge)
691 setLong(cl, o, PCICS_BAR3, tag->ti_Data);
692 dev->BaseReg[3].addr = getLong(cl, o, PCICS_BAR3);
694 break;
696 case aoHidd_PCIDevice_Base4:
697 if (!dev->isBridge)
699 setLong(cl, o, PCICS_BAR4, tag->ti_Data);
700 dev->BaseReg[4].addr = getLong(cl, o, PCICS_BAR4);
702 break;
704 case aoHidd_PCIDevice_Base5:
705 if (!dev->isBridge)
707 setLong(cl, o, PCICS_BAR5, tag->ti_Data);
708 dev->BaseReg[5].addr = getLong(cl, o, PCICS_BAR5);
710 break;
712 case aoHidd_PCIDevice_RomBase:
713 setLong(cl, o, PCICS_EXPROM_BASE, tag->ti_Data);
714 dev->RomBase = getLong(cl, o, PCICS_EXPROM_BASE);
715 break;
717 case aoHidd_PCIDevice_MemoryBase:
718 if (dev->isBridge) setWord(cl, o, PCIBR_MEMBASE, tag->ti_Data >> 16); break;
720 case aoHidd_PCIDevice_MemoryLimit:
721 if (dev->isBridge) setWord(cl, o, PCIBR_MEMLIMIT, tag->ti_Data >> 16); break;
723 case aoHidd_PCIDevice_PrefetchableBase:
724 if (dev->isBridge) setWord(cl, o, PCIBR_PREFETCHBASE, tag->ti_Data >> 16); break;
726 case aoHidd_PCIDevice_PrefetchableLimit:
727 if (dev->isBridge) setWord(cl, o, PCIBR_PREFETCHLIMIT, tag->ti_Data >> 16); break;
729 case aoHidd_PCIDevice_IOBase:
730 if (dev->isBridge) setByte(cl, o, PCIBR_IOBASE, tag->ti_Data >> 8); break;
732 case aoHidd_PCIDevice_IOLimit:
733 if (dev->isBridge) setByte(cl, o, PCIBR_IOLIMIT, tag->ti_Data >> 8); break;
735 case aoHidd_PCIDevice_isIO:
737 UWORD command = getWord(cl, o, PCICS_COMMAND) & ~PCICMF_IODECODE;
738 if (tag->ti_Data)
739 command |= PCICMF_IODECODE;
740 setWord(cl, o, PCICS_COMMAND, command);
742 break;
744 case aoHidd_PCIDevice_isMEM:
746 UWORD command = getWord(cl, o, PCICS_COMMAND) & ~PCICMF_MEMDECODE;
747 if (tag->ti_Data)
748 command |= PCICMF_MEMDECODE;
749 setWord(cl, o, PCICS_COMMAND, command);
751 break;
753 case aoHidd_PCIDevice_isMaster:
755 UWORD command = getWord(cl, o, PCICS_COMMAND) & ~PCICMF_BUSMASTER;
756 if (tag->ti_Data)
757 command |= PCICMF_BUSMASTER;
758 setWord(cl, o, PCICS_COMMAND, command);
760 break;
762 case aoHidd_PCIDevice_paletteSnoop:
764 UWORD command = getWord(cl, o, PCICS_COMMAND) & ~PCICMF_VGASNOOP;
765 if (tag->ti_Data)
766 command |= PCICMF_VGASNOOP;
767 setWord(cl, o, PCICS_COMMAND, command);
769 break;
771 case aoHidd_PCIDevice_ISAEnable:
772 if (dev->isBridge)
774 UWORD control = getWord(cl, o, PCIBR_CONTROL) & ~PCICTRLF_ISAENABLE;
775 if (tag->ti_Data)
776 control |= PCICTRLF_ISAENABLE;
777 setWord(cl, o, PCIBR_CONTROL, control);
779 break;
781 case aoHidd_PCIDevice_VGAEnable:
782 if (dev->isBridge)
784 UWORD control = getWord(cl, o, PCIBR_CONTROL) & ~PCICTRLF_VGAENABLE;
785 if (tag->ti_Data)
786 control |= PCICTRLF_VGAENABLE;
787 setWord(cl, o, PCIBR_CONTROL, control);
789 break;
791 default:
792 bug("[PCIDevice] Trying to set nonsettable attribute %d!\n", idx);
793 break;