show more relevant debug
[AROS.git] / arch / all-pc / hidds / pcipc / driverclass.c
blobde2782241d43dc1943cb61a605a82c5bf411f128
1 /*
2 Copyright © 2004-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: PCI direct driver for i386 native.
6 Lang: English
7 */
9 #define __OOP_NOATTRBASES__
11 #define DEBUG 0
13 #include <aros/debug.h>
14 #include <aros/symbolsets.h>
15 #include <hidd/pci.h>
16 #include <oop/oop.h>
17 #include <utility/tagitem.h>
19 #include <proto/exec.h>
20 #include <proto/utility.h>
21 #include <proto/oop.h>
22 #include <proto/acpica.h>
24 #include <acpica/acnames.h>
25 #include <acpica/accommon.h>
27 #include "pci.h"
29 #undef HiddPCIDriverAttrBase
30 #undef HiddAttrBase
31 #undef HiddPCIDeviceAttrBase
33 #define HiddPCIDriverAttrBase (PSD(cl)->hiddPCIDriverAB)
34 #define HiddAttrBase (PSD(cl)->hiddAB)
35 #define HiddPCIDeviceAttrBase (PSD(cl)->hidd_PCIDeviceAB)
38 We overload the New method in order to introduce the Hidd Name and
39 HardwareName attributes.
41 OOP_Object *PCPCI__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
43 struct pRoot_New mymsg;
44 struct TagItem mytags[] =
46 { aHidd_Name, (IPTR)"pcipc.hidd" },
47 { aHidd_HardwareName, (IPTR)"IA32 native direct access PCI driver" },
48 { TAG_DONE, 0 }
51 mymsg.mID = msg->mID;
52 mymsg.attrList = mytags;
54 if (msg->attrList)
56 mytags[2].ti_Tag = TAG_MORE;
57 mytags[2].ti_Data = (IPTR)msg->attrList;
60 return (OOP_Object *)OOP_DoSuperMethod(cl, o, &mymsg.mID);
63 IPTR PCPCI__Hidd_PCIDriver__HasExtendedConfig(OOP_Class *cl, OOP_Object *o,
64 struct pHidd_PCIDriver_HasExtendedConfig *msg)
66 IPTR mmio = 0;
68 if(PSD(cl)->pcipc_acpiMcfgTbl) {
70 const ACPI_TABLE_MCFG *mcfg_tbl = (APTR)PSD(cl)->pcipc_acpiMcfgTbl;
71 const ACPI_MCFG_ALLOCATION *mcfg_alloc = (APTR)mcfg_tbl + sizeof(ACPI_TABLE_MCFG);
73 do {
74 if( (msg->bus <= mcfg_alloc->EndBusNumber) && (msg->bus >= mcfg_alloc->StartBusNumber) ) {
77 FIXME: Check the validity of the extended configuration space
80 ULONG *extcap;
82 mmio = ((IPTR)mcfg_alloc->Address) + (((msg->bus&255)<<20) | ((msg->dev&31)<<15) | ((msg->sub&7)<<12));
85 Absence of any Extended Capabilities is required to be indicated
86 by an Extended Capability header with a Capability ID of 0000h,
87 a Capability Version of 0h, and a Next Capability Offset of 0h.
89 For PCI devices OnMyHardware(TM) extended capability header at 0x100 reads 0xffffffff.
91 0xffffffff is non valid extended capability header as it would point
92 the next capability outside configuration space.
94 If we get extended capability header set with all ones then we won't use ECAM.
95 (PCI device in mmio space, not PCIe)
98 extcap = (APTR) (mmio + 0x100);
99 D(bug("HasExtendedConfig: bus %d dev %d sub %d extcap %08x\n", msg->bus, msg->dev, msg->sub, *extcap));
100 if(*extcap == 0xffffffff) {
101 D(bug(" Device is PCI not PCIe\n"));
102 mmio = 0;
105 break;
106 }else{
107 D(bug("HasExtendedConfig: Device not found! bus %d dev %d sub %d \n", msg->bus, msg->dev, msg->sub));
110 mcfg_alloc++;
111 }while((APTR)mcfg_alloc < ((APTR)mcfg_tbl + mcfg_tbl->Header.Length));
114 return mmio;
117 ULONG PCPCI__Hidd_PCIDriver__ReadConfigLong(OOP_Class *cl, OOP_Object *o,
118 struct pHidd_PCIDriver_ReadConfigLong *msg)
121 We NEED the device object as it houses the ExtendedConfig attribute per device.
122 We know that the value stored in ExtendedConfig is the mmio base as returned by PCPCI__Hidd_PCIDriver__HasExtendedConfig.
123 If we get ExtendedConfig we will use ECAM method.
125 While the bus is being enumerated we automagically skip ECAM until ExtendedConfig attribute is set and we have a valid device object.
128 IPTR mmio = 0;
130 OOP_GetAttr(msg->device, aHidd_PCIDevice_ExtendedConfig, &mmio);
131 if(mmio) {
132 /* This is the ECAM access method for long read */
133 volatile ULONG *longreg;
135 longreg = (APTR) (mmio + (msg->reg & 0xffc));
137 D(bug("ECAM.read longreg %p %08x\n", longreg, *longreg));
138 return *longreg;
142 Last good long register without ECAM,
143 macros in CAM methods take care of the alignment.
144 we don't want to return some random value.
146 if(msg->reg < 0x100) {
147 return PSD(cl)->ReadConfigLong(msg->bus, msg->dev, msg->sub, msg->reg);
148 } else {
149 return 0xffffffff;
153 UWORD PCPCI__Hidd_PCIDriver__ReadConfigWord(OOP_Class *cl, OOP_Object *o,
154 struct pHidd_PCIDriver_ReadConfigWord *msg)
156 return ReadConfigWord(PSD(cl), msg->bus, msg->dev, msg->sub, msg->reg);
159 UBYTE PCPCI__Hidd_PCIDriver__ReadConfigByte(OOP_Class *cl, OOP_Object *o,
160 struct pHidd_PCIDriver_ReadConfigByte *msg)
162 pcicfg temp;
164 temp.ul = PSD(cl)->ReadConfigLong(msg->bus, msg->dev, msg->sub, msg->reg);
165 return temp.ub[msg->reg & 3];
168 void PCPCI__Hidd_PCIDriver__WriteConfigLong(OOP_Class *cl, OOP_Object *o,
169 struct pHidd_PCIDriver_WriteConfigLong *msg)
171 IPTR mmio = 0;
173 OOP_GetAttr(msg->device, aHidd_PCIDevice_ExtendedConfig, &mmio);
174 if(mmio) {
175 /* This is the ECAM access method for long write */
176 volatile ULONG *longreg;
177 longreg = (APTR) (mmio + (msg->reg & 0xffc));
178 D(bug("ECAM.write.old longreg %p %08x = %08x\n", longreg, *longreg, msg->val));
179 *longreg = msg->val;
180 D(bug("ECAM.write.new longreg %p %08x == %08x?\n", longreg, *longreg, msg->val));
181 } else {
183 Last good long register without ECAM,
184 macros in CAM methods take care of the alignment.
185 we don't want to store the value in some random address.
187 if(msg->reg < 0x100) {
188 PSD(cl)->WriteConfigLong(msg->bus, msg->dev, msg->sub, msg->reg, msg->val);
193 #undef _psd
195 /* Class initialization and destruction */
197 void PCIPC_ACPIEnumPCIIRQ(ACPI_OBJECT *item)
199 if ((item->Type == 4) && (item->Package.Count == 4))
201 ACPI_OBJECT *jitem;
202 UBYTE bus, device;
204 jitem = &item->Package.Elements[0];
205 bus = (jitem->Integer.Value >> 24);
206 device = (jitem->Integer.Value >> 16) & 0xFF;
209 bug("[PCI.PC] %s: %02d.%02d", __func__, bus, device);
210 if ((jitem->Integer.Value & 0xFFFF) == 0xFFFF)
211 bug(".xx");
212 else
213 bug(".%02d", (jitem->Integer.Value & 0xFFFF));
215 jitem = &item->Package.Elements[2];
216 if (jitem->String.Length > 0)
218 bug(" '%s'\n", jitem->String.Pointer);
220 else
222 jitem = &item->Package.Elements[3];
223 bug(" using GSI %02x\n", jitem->Integer.Value);
228 ACPI_STATUS PCPCI_ACPIDeviceCallback(ACPI_HANDLE Object, ULONG nesting_level, void *Context, void **ReturnValue)
230 ACPI_BUFFER RetVal;
231 RetVal.Length = ACPI_ALLOCATE_BUFFER;
232 int status;
234 D(bug("[PCI.PC] %s: Object = %p, nesting_level=%d, Context=%p\n", __func__, Object, nesting_level, Context);)
236 status = AcpiEvaluateObject(Object, "_PRT", NULL, &RetVal);
237 if (!ACPI_FAILURE(status))
239 ACPI_OBJECT *RObject = RetVal.Pointer;
241 D(bug("[PCI.PC] %s: _PRT @ %p\n", __func__, RetVal.Pointer);)
242 D(bug("[PCI.PC] %s: %d PCI IRQ Entries\n", __func__, RObject->Package.Count);)
244 for (unsigned int i=0; i < RObject->Package.Count; i++)
246 PCIPC_ACPIEnumPCIIRQ((ACPI_OBJECT *)&RObject->Package.Elements[i]);
250 D(bug("[PCI.PC] %s: Finished\n", __func__);)
252 return 0;
255 static int PCPCI_InitClass(LIBBASETYPEPTR LIBBASE)
257 struct pcipc_staticdata *_psd = &LIBBASE->psd;
258 struct pHidd_PCI_AddHardwareDriver msg, *pmsg = &msg;
259 OOP_Object *pci;
261 D(bug("[PCI.PC] Driver initialization\n"));
263 /* Open ACPI and cache the pointer to the MCFG table.. */
264 ACPICABase = OpenLibrary("acpica.library", 0);
265 if (ACPICABase)
266 AcpiGetTable(ACPI_SIG_MCFG, 1, (ACPI_TABLE_HEADER **)&_psd->pcipc_acpiMcfgTbl);
268 _psd->hiddPCIDriverAB = OOP_ObtainAttrBase(IID_Hidd_PCIDriver);
269 _psd->hiddAB = OOP_ObtainAttrBase(IID_Hidd);
270 _psd->hidd_PCIDeviceAB = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
271 if (_psd->hiddPCIDriverAB == 0 || _psd->hiddAB == 0 || _psd->hidd_PCIDeviceAB == 0)
273 D(bug("[PCI.PC] ObtainAttrBases failed\n"));
274 return FALSE;
277 if (ACPICABase)
278 AcpiGetDevices("PNP0A03", PCPCI_ACPIDeviceCallback, LIBBASE, NULL);
280 /* Default to using config mechanism 1 */
281 _psd->ReadConfigLong = ReadConfig1Long;
282 _psd->WriteConfigLong = WriteConfig1Long;
284 PCIPC_ProbeConfMech(&LIBBASE->psd);
286 msg.driverClass = _psd->driverClass;
287 msg.mID = OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_AddHardwareDriver);
288 D(bug("[PCI.PC] Registering Driver with PCI base class..\n"));
290 pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
291 OOP_DoMethod(pci, (OOP_Msg)pmsg);
292 OOP_DisposeObject(pci);
294 D(bug("[PCI.PC] Driver initialization finished\n"));
296 return TRUE;
299 static int PCPCI_ExpungeClass(LIBBASETYPEPTR LIBBASE)
301 struct pcipc_staticdata *_psd = &LIBBASE->psd;
303 D(bug("[PCI.PC] Class destruction\n"));
305 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
306 OOP_ReleaseAttrBase(IID_Hidd_PCIDriver);
307 OOP_ReleaseAttrBase(IID_Hidd);
309 if (ACPICABase)
310 CloseLibrary(ACPICABase);
312 return TRUE;
315 ADD2INITLIB(PCPCI_InitClass, 0)
316 ADD2EXPUNGELIB(PCPCI_ExpungeClass, 0)