re-word some debug output
[AROS.git] / arch / i386-pc / drivers / pcipc / driverclass.c
blob70d517d98753b76dfcfcd32c59ccfbd864ef10d4
1 /*
2 Copyright © 2004-2006, 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 <exec/types.h>
12 #include <hidd/pci.h>
13 #include <oop/oop.h>
15 #include <utility/tagitem.h>
17 #include <proto/exec.h>
18 #include <proto/utility.h>
19 #include <proto/oop.h>
21 #include <aros/symbolsets.h>
22 #include <asm/io.h>
24 #include "pci.h"
26 #define DEBUG 1
27 #include <aros/debug.h>
29 #undef HiddPCIDriverAttrBase
30 #undef HiddAttrBase
32 #define HiddPCIDriverAttrBase (PSD(cl)->hiddPCIDriverAB)
33 #define HiddAttrBase (PSD(cl)->hiddAB)
35 #define CFGADD(bus,dev,func,reg) \
36 ( 0x80000000 | ((bus)<<16) | \
37 ((dev)<<11) | ((func)<<8) | ((reg)&~3))
38 #define CFG2ADD(dev,reg) \
39 (0xc000 | ((dev)<<8) | (reg))
41 typedef union _pcicfg
43 ULONG ul;
44 UWORD uw[2];
45 UBYTE ub[4];
46 } pcicfg;
49 We overload the New method in order to introduce the Hidd Name and
50 HardwareName attributes.
52 OOP_Object *PCPCI__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
54 struct pRoot_New mymsg;
56 struct TagItem mytags[] = {
57 { aHidd_Name, (IPTR)"PCINative" },
58 { aHidd_HardwareName, (IPTR)"IA32 native direct access PCI driver" },
59 { TAG_DONE, 0 }
62 mymsg.mID = msg->mID;
63 mymsg.attrList = (struct TagItem *)&mytags;
65 if (msg->attrList)
67 mytags[2].ti_Tag = TAG_MORE;
68 mytags[2].ti_Data = (IPTR)msg->attrList;
71 msg = &mymsg;
73 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
75 return o;
78 ULONG ReadConfig1Long(UBYTE bus, UBYTE dev, UBYTE sub, UBYTE reg)
80 ULONG temp;
82 Disable();
83 outl(CFGADD(bus, dev, sub, reg),PCI_AddressPort);
84 temp=inl(PCI_DataPort);
85 Enable();
87 return temp;
90 ULONG ReadConfig2Long(UBYTE bus, UBYTE dev, UBYTE sub, UBYTE reg)
92 ULONG temp;
94 if (dev < 16) {
95 Disable();
96 outb(0xf0|(sub<<1),PCI_AddressPort);
97 outb(bus,PCI_ForwardPort);
98 temp=inl(CFG2ADD(dev, reg));
99 outb(0,PCI_AddressPort);
100 Enable();
101 return temp;
102 } else
103 return 0xffffffff;
107 ULONG ReadConfigLong(struct pci_staticdata *psd, UBYTE bus, UBYTE dev, UBYTE sub, UBYTE reg)
109 switch(psd->ConfType) {
110 case 1:
111 return ReadConfig1Long(bus, dev, sub, reg);
112 case 2:
113 return ReadConfig2Long(bus, dev, sub, reg);
115 return 0xffffffff;
118 ULONG PCPCI__Hidd_PCIDriver__ReadConfigLong(OOP_Class *cl, OOP_Object *o,
119 struct pHidd_PCIDriver_ReadConfigLong *msg)
121 return ReadConfigLong(PSD(cl), msg->bus, msg->dev, msg->sub, msg->reg);
124 UWORD ReadConfigWord(struct pci_staticdata *psd, UBYTE bus, UBYTE dev, UBYTE sub, UBYTE reg)
126 pcicfg temp;
128 temp.ul = ReadConfigLong(psd, bus, dev, sub, reg);
129 return temp.uw[(reg&2)>>1];
133 UWORD PCPCI__Hidd_PCIDriver__ReadConfigWord(OOP_Class *cl, OOP_Object *o,
134 struct pHidd_PCIDriver_ReadConfigWord *msg)
136 return ReadConfigWord(PSD(cl), msg->bus, msg->dev, msg->sub, msg->reg);
139 UBYTE PCPCI__Hidd_PCIDriver__ReadConfigByte(OOP_Class *cl, OOP_Object *o,
140 struct pHidd_PCIDriver_ReadConfigByte *msg)
142 pcicfg temp;
144 temp.ul = ReadConfigLong(PSD(cl), msg->bus, msg->dev, msg->sub, msg->reg);
145 return temp.ub[msg->reg & 3];
148 void WriteConfig1Long(UBYTE bus, UBYTE dev, UBYTE sub, UBYTE reg, ULONG val)
150 Disable();
151 outl(CFGADD(bus, dev, sub, reg),PCI_AddressPort);
152 outl(val,PCI_DataPort);
153 Enable();
156 void WriteConfig2Long(UBYTE bus, UBYTE dev, UBYTE sub, UBYTE reg, ULONG val)
158 if (dev < 16) {
159 Disable();
160 outb(0xf0|(sub<<1),PCI_AddressPort);
161 outb(bus,PCI_ForwardPort);
162 outl(val,CFG2ADD(dev, reg));
163 outb(0,PCI_AddressPort);
164 Enable();
168 void PCPCI__Hidd_PCIDriver__WriteConfigLong(OOP_Class *cl, OOP_Object *o,
169 struct pHidd_PCIDriver_WriteConfigLong *msg)
171 switch(PSD(cl)->ConfType) {
172 case 1:
173 WriteConfig1Long(msg->bus, msg->dev, msg->sub, msg->reg, msg->val);
174 break;
175 case 2:
176 WriteConfig2Long(msg->bus, msg->dev, msg->sub, msg->reg, msg->val);
180 void SanityCheck(struct pci_staticdata *psd)
182 UWORD temp;
184 /* FIXME: This logic was originally taken from Linux operating system. However it
185 fails on newer systems since rules assumed here are no longer met.
186 This code is left for reference in case if new method generates problems too.
187 temp = ReadConfigWord(psd, 0, 0, 0, PCICS_SUBCLASS);
188 if ((temp == PCI_CLASS_BRIDGE_HOST) || (temp == PCI_CLASS_DISPLAY_VGA))
189 return;
190 temp = ReadConfigWord(psd, 0, 0, 0, PCICS_VENDOR);
191 if ((temp == PCI_VENDOR_INTEL) || (temp == PCI_VENDOR_COMPAQ))
192 return; */
193 temp = ReadConfigWord(psd, 0, 0, 0, PCICS_PRODUCT);
194 if ((temp != 0x0000) && (temp != 0xFFFF))
195 return;
196 D(bug("[PCI.PC] Sanity check failed\n"));
197 psd->ConfType = 0;
199 /* Class initialization and destruction */
201 static int PCPCI_InitClass(LIBBASETYPEPTR LIBBASE)
203 OOP_Object *pci;
204 ULONG temp;
206 D(bug("[PCI.PC] Driver initialization\n"));
208 struct pHidd_PCI_AddHardwareDriver msg,*pmsg=&msg;
210 LIBBASE->psd.hiddPCIDriverAB = OOP_ObtainAttrBase(IID_Hidd_PCIDriver);
211 LIBBASE->psd.hiddAB = OOP_ObtainAttrBase(IID_Hidd);
212 if (LIBBASE->psd.hiddPCIDriverAB == 0 || LIBBASE->psd.hiddAB == 0)
214 D(bug("[PCI.PC] ObtainAttrBases failed\n"));
215 return FALSE;
218 LIBBASE->psd.ConfType = 0;
219 outb(0x01, PCI_TestPort);
220 temp = inl(PCI_AddressPort);
221 outl(0x80000000, PCI_AddressPort);
222 if (inl(PCI_AddressPort) == 0x80000000)
223 LIBBASE->psd.ConfType = 1;
224 outl(temp, PCI_AddressPort);
225 if (LIBBASE->psd.ConfType == 1) {
226 D(bug("[PCI.PC] Configuration mechanism 1 detected\n"));
227 SanityCheck(&LIBBASE->psd);
229 if (LIBBASE->psd.ConfType == 0) {
230 outb(0x00, PCI_TestPort);
231 outb(0x00, PCI_AddressPort);
232 outb(0x00, PCI_ForwardPort);
233 if ((inb(PCI_AddressPort) == 0x00) && (inb(PCI_ForwardPort) == 0x00)) {
234 LIBBASE->psd.ConfType = 2;
235 D(bug("[PCI.PC] configuration mechanism 2 detected\n"));
236 SanityCheck(&LIBBASE->psd);
239 /* FIXME: Newer systems may have empty bus 0. In this case SanityCheck() will fail. We
240 assume configuration type 1 for such systems.
241 Probably SanityCheck() should be revised or removed at all. */
242 if (LIBBASE->psd.ConfType == 0) {
243 D(bug("[PCI.PC] Failing back to configuration mechanism 1\n"));
244 LIBBASE->psd.ConfType = 1;
247 msg.driverClass = LIBBASE->psd.driverClass;
248 msg.mID = OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_AddHardwareDriver);
249 D(bug("[PCI.PC] Registering Driver with PCI base class..\n"));
251 pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
252 OOP_DoMethod(pci, (OOP_Msg)pmsg);
253 OOP_DisposeObject(pci);
255 D(bug("[PCI.PC] Driver initialization finished\n"));
257 return TRUE;
260 static int PCPCI_ExpungeClass(LIBBASETYPEPTR LIBBASE)
262 D(bug("[PCI.PC] Class destruction\n"));
264 OOP_ReleaseAttrBase(IID_Hidd_PCIDriver);
265 OOP_ReleaseAttrBase(IID_Hidd);
267 return TRUE;
270 ADD2INITLIB(PCPCI_InitClass, 0)
271 ADD2EXPUNGELIB(PCPCI_ExpungeClass, 0)