use the correct acpi status check. don't try to call the acpi function if acpi isnt...
[AROS.git] / arch / all-pc / hidds / pcipc / driverclass.c
blobdedd049e6718e7d774ebf0d65236be654e216165
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 ACPI_STATUS callback(ACPI_HANDLE Object, ULONG nesting_level, void *Context, void **RerturnValue)
199 ACPI_BUFFER RetVal;
200 RetVal.Length = ACPI_ALLOCATE_BUFFER;
201 int status;
203 bug("callback. Object = %p, nesting_level=%d, Context=%p\n", Object, nesting_level, Context);
205 status = AcpiEvaluateObject(Object, "_PRT", NULL, &RetVal);
207 bug("result of PRT evaluate=%d\n", status);
209 if (!ACPI_FAILURE(status))
211 bug("RetVal.Length=%d\n", RetVal.Length);
212 bug("RetVal.Pointer=%p\n", RetVal.Pointer);
213 ACPI_OBJECT *RObject = RetVal.Pointer;
214 bug("Object->Type =%d\n", RObject->Type);
215 bug("Object->Package.Count=%d\n", RObject->Package.Count);
216 for (unsigned int i=0; i < RObject->Package.Count; i++)
218 ACPI_OBJECT *item = &RObject->Package.Elements[i];
219 bug("%03d: %p Type=%d Count=%d \n ", i, item, item->Type, item->Package.Count);
220 for (unsigned int j=0; j < item->Package.Count; j++)
222 ACPI_OBJECT *jitem = &item->Package.Elements[j];
223 bug("%08x ", jitem->Integer.Value);
225 bug("\n");
230 return 0;
233 static int PCPCI_InitClass(LIBBASETYPEPTR LIBBASE)
235 struct pcipc_staticdata *_psd = &LIBBASE->psd;
236 struct pHidd_PCI_AddHardwareDriver msg, *pmsg = &msg;
237 OOP_Object *pci;
239 D(bug("[PCI.PC] Driver initialization\n"));
241 /* Open ACPI and cache the pointer to the MCFG table.. */
242 ACPICABase = OpenLibrary("acpica.library", 0);
243 if (ACPICABase)
244 AcpiGetTable(ACPI_SIG_MCFG, 1, (ACPI_TABLE_HEADER **)&_psd->pcipc_acpiMcfgTbl);
246 _psd->hiddPCIDriverAB = OOP_ObtainAttrBase(IID_Hidd_PCIDriver);
247 _psd->hiddAB = OOP_ObtainAttrBase(IID_Hidd);
248 _psd->hidd_PCIDeviceAB = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
249 if (_psd->hiddPCIDriverAB == 0 || _psd->hiddAB == 0 || _psd->hidd_PCIDeviceAB == 0)
251 D(bug("[PCI.PC] ObtainAttrBases failed\n"));
252 return FALSE;
255 if (ACPICABase)
256 AcpiGetDevices("PNP0A03", callback, LIBBASE, NULL);
258 /* Default to using config mechanism 1 */
259 _psd->ReadConfigLong = ReadConfig1Long;
260 _psd->WriteConfigLong = WriteConfig1Long;
262 PCIPC_ProbeConfMech(&LIBBASE->psd);
264 msg.driverClass = _psd->driverClass;
265 msg.mID = OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_AddHardwareDriver);
266 D(bug("[PCI.PC] Registering Driver with PCI base class..\n"));
268 pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
269 OOP_DoMethod(pci, (OOP_Msg)pmsg);
270 OOP_DisposeObject(pci);
272 D(bug("[PCI.PC] Driver initialization finished\n"));
274 return TRUE;
277 static int PCPCI_ExpungeClass(LIBBASETYPEPTR LIBBASE)
279 struct pcipc_staticdata *_psd = &LIBBASE->psd;
281 D(bug("[PCI.PC] Class destruction\n"));
283 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
284 OOP_ReleaseAttrBase(IID_Hidd_PCIDriver);
285 OOP_ReleaseAttrBase(IID_Hidd);
287 if (ACPICABase)
288 CloseLibrary(ACPICABase);
290 return TRUE;
293 ADD2INITLIB(PCPCI_InitClass, 0)
294 ADD2EXPUNGELIB(PCPCI_ExpungeClass, 0)