small tidy up. keep acpi open for the scope of the class, since we will need it again...
[AROS.git] / arch / all-pc / hidds / pcipc / driverclass.c
blobaf7313bb3f51d502b8e39cb13e5b9623827ed1bb
1 /*
2 Copyright © 2004-2014, 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 #include <aros/debug.h>
12 #include <aros/symbolsets.h>
13 #include <hidd/pci.h>
14 #include <oop/oop.h>
15 #include <utility/tagitem.h>
17 #include <proto/exec.h>
18 #include <proto/utility.h>
19 #include <proto/oop.h>
20 #include <proto/acpica.h>
22 #include <acpica/acnames.h>
23 #include <acpica/accommon.h>
25 #include "pci.h"
27 #undef HiddPCIDriverAttrBase
28 #undef HiddAttrBase
29 #undef HiddPCIDeviceAttrBase
31 #define HiddPCIDriverAttrBase (PSD(cl)->hiddPCIDriverAB)
32 #define HiddAttrBase (PSD(cl)->hiddAB)
33 #define HiddPCIDeviceAttrBase (PSD(cl)->hidd_PCIDeviceAB)
36 We overload the New method in order to introduce the Hidd Name and
37 HardwareName attributes.
39 OOP_Object *PCPCI__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
41 struct pRoot_New mymsg;
42 struct TagItem mytags[] =
44 { aHidd_Name, (IPTR)"pcipc.hidd" },
45 { aHidd_HardwareName, (IPTR)"IA32 native direct access PCI driver" },
46 { TAG_DONE, 0 }
49 mymsg.mID = msg->mID;
50 mymsg.attrList = mytags;
52 if (msg->attrList)
54 mytags[2].ti_Tag = TAG_MORE;
55 mytags[2].ti_Data = (IPTR)msg->attrList;
58 return (OOP_Object *)OOP_DoSuperMethod(cl, o, &mymsg.mID);
61 IPTR PCPCI__Hidd_PCIDriver__HasExtendedConfig(OOP_Class *cl, OOP_Object *o,
62 struct pHidd_PCIDriver_HasExtendedConfig *msg)
64 IPTR mmio = 0;
66 if(PSD(cl)->pcipc_acpiMcfgTbl) {
68 const ACPI_TABLE_MCFG *mcfg_tbl = (APTR)PSD(cl)->pcipc_acpiMcfgTbl;
69 const ACPI_MCFG_ALLOCATION *mcfg_alloc = (APTR)mcfg_tbl + sizeof(ACPI_TABLE_MCFG);
71 do {
72 if( (msg->bus <= mcfg_alloc->EndBusNumber) && (msg->bus >= mcfg_alloc->StartBusNumber) ) {
75 FIXME: Check the validity of the extended configuration space
78 ULONG *extcap;
80 mmio = ((IPTR)mcfg_alloc->Address) + (((msg->bus&255)<<20) | ((msg->dev&31)<<15) | ((msg->sub&7)<<12));
83 Absence of any Extended Capabilities is required to be indicated
84 by an Extended Capability header with a Capability ID of 0000h,
85 a Capability Version of 0h, and a Next Capability Offset of 0h.
87 For PCI devices OnMyHardware(TM) extended capability header at 0x100 reads 0xffffffff.
89 0xffffffff is non valid extended capability header as it would point
90 the next capability outside configuration space.
92 If we get extended capability header set with all ones then we won't use ECAM.
93 (PCI device in mmio space, not PCIe)
96 extcap = (APTR) (mmio + 0x100);
97 D(bug("HasExtendedConfig: bus %d dev %d sub %d extcap %08x\n", msg->bus, msg->dev, msg->sub, *extcap));
98 if(*extcap == 0xffffffff) {
99 D(bug(" Device is PCI not PCIe\n"));
100 mmio = 0;
103 break;
104 }else{
105 D(bug("HasExtendedConfig: Device not found! bus %d dev %d sub %d \n", msg->bus, msg->dev, msg->sub));
108 mcfg_alloc++;
109 }while((APTR)mcfg_alloc < ((APTR)mcfg_tbl + mcfg_tbl->Header.Length));
112 return mmio;
115 ULONG PCPCI__Hidd_PCIDriver__ReadConfigLong(OOP_Class *cl, OOP_Object *o,
116 struct pHidd_PCIDriver_ReadConfigLong *msg)
119 We NEED the device object as it houses the ExtendedConfig attribute per device.
120 We know that the value stored in ExtendedConfig is the mmio base as returned by PCPCI__Hidd_PCIDriver__HasExtendedConfig.
121 If we get ExtendedConfig we will use ECAM method.
123 While the bus is being enumerated we automagically skip ECAM until ExtendedConfig attribute is set and we have a valid device object.
126 IPTR mmio = 0;
128 OOP_GetAttr(msg->device, aHidd_PCIDevice_ExtendedConfig, &mmio);
129 if(mmio) {
130 /* This is the ECAM access method for long read */
131 volatile ULONG *longreg;
133 longreg = (APTR) (mmio + (msg->reg & 0xffc));
135 D(bug("ECAM.read longreg %p %08x\n", longreg, *longreg));
136 return *longreg;
140 Last good long register without ECAM,
141 macros in CAM methods take care of the alignment.
142 we don't want to return some random value.
144 if(msg->reg < 0x100) {
145 return PSD(cl)->ReadConfigLong(msg->bus, msg->dev, msg->sub, msg->reg);
146 } else {
147 return 0xffffffff;
151 UWORD PCPCI__Hidd_PCIDriver__ReadConfigWord(OOP_Class *cl, OOP_Object *o,
152 struct pHidd_PCIDriver_ReadConfigWord *msg)
154 return ReadConfigWord(PSD(cl), msg->bus, msg->dev, msg->sub, msg->reg);
157 UBYTE PCPCI__Hidd_PCIDriver__ReadConfigByte(OOP_Class *cl, OOP_Object *o,
158 struct pHidd_PCIDriver_ReadConfigByte *msg)
160 pcicfg temp;
162 temp.ul = PSD(cl)->ReadConfigLong(msg->bus, msg->dev, msg->sub, msg->reg);
163 return temp.ub[msg->reg & 3];
166 void PCPCI__Hidd_PCIDriver__WriteConfigLong(OOP_Class *cl, OOP_Object *o,
167 struct pHidd_PCIDriver_WriteConfigLong *msg)
169 IPTR mmio = 0;
171 OOP_GetAttr(msg->device, aHidd_PCIDevice_ExtendedConfig, &mmio);
172 if(mmio) {
173 /* This is the ECAM access method for long write */
174 volatile ULONG *longreg;
175 longreg = (APTR) (mmio + (msg->reg & 0xffc));
176 D(bug("ECAM.write.old longreg %p %08x = %08x\n", longreg, *longreg, msg->val));
177 *longreg = msg->val;
178 D(bug("ECAM.write.new longreg %p %08x == %08x?\n", longreg, *longreg, msg->val));
179 } else {
181 Last good long register without ECAM,
182 macros in CAM methods take care of the alignment.
183 we don't want to store the value in some random address.
185 if(msg->reg < 0x100) {
186 PSD(cl)->WriteConfigLong(msg->bus, msg->dev, msg->sub, msg->reg, msg->val);
191 #undef _psd
193 /* Class initialization and destruction */
195 static int PCPCI_InitClass(LIBBASETYPEPTR LIBBASE)
197 struct pcipc_staticdata *_psd = &LIBBASE->psd;
198 struct pHidd_PCI_AddHardwareDriver msg, *pmsg = &msg;
199 OOP_Object *pci;
201 D(bug("[PCI.PC] Driver initialization\n"));
203 /* Open ACPI and cache the pointer to the MCFG table.. */
204 ACPICABase = OpenLibrary("acpica.library", 0);
205 if (ACPICABase)
206 AcpiGetTable(ACPI_SIG_MCFG, 1, (ACPI_TABLE_HEADER **)&_psd->pcipc_acpiMcfgTbl);
208 _psd->hiddPCIDriverAB = OOP_ObtainAttrBase(IID_Hidd_PCIDriver);
209 _psd->hiddAB = OOP_ObtainAttrBase(IID_Hidd);
210 _psd->hidd_PCIDeviceAB = OOP_ObtainAttrBase(IID_Hidd_PCIDevice);
211 if (_psd->hiddPCIDriverAB == 0 || _psd->hiddAB == 0 || _psd->hidd_PCIDeviceAB == 0)
213 D(bug("[PCI.PC] ObtainAttrBases failed\n"));
214 return FALSE;
217 /* Default to using config mechanism 1 */
218 _psd->ReadConfigLong = ReadConfig1Long;
219 _psd->WriteConfigLong = WriteConfig1Long;
221 PCIPC_ProbeConfMech(&LIBBASE->psd);
223 msg.driverClass = _psd->driverClass;
224 msg.mID = OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_AddHardwareDriver);
225 D(bug("[PCI.PC] Registering Driver with PCI base class..\n"));
227 pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
228 OOP_DoMethod(pci, (OOP_Msg)pmsg);
229 OOP_DisposeObject(pci);
231 D(bug("[PCI.PC] Driver initialization finished\n"));
233 return TRUE;
236 static int PCPCI_ExpungeClass(LIBBASETYPEPTR LIBBASE)
238 struct pcipc_staticdata *_psd = &LIBBASE->psd;
240 D(bug("[PCI.PC] Class destruction\n"));
242 OOP_ReleaseAttrBase(IID_Hidd_PCIDevice);
243 OOP_ReleaseAttrBase(IID_Hidd_PCIDriver);
244 OOP_ReleaseAttrBase(IID_Hidd);
246 if (ACPICABase)
247 CloseLibrary(ACPICABase);
249 return TRUE;
252 ADD2INITLIB(PCPCI_InitClass, 0)
253 ADD2EXPUNGELIB(PCPCI_ExpungeClass, 0)