Forward compatibility: build relative-base link libraries where needed
[AROS.git] / arch / all-linux / hidd / pcilinux / driverclass.c
blob66d7305f477d9920a6691d37355e4ec11585a571
1 /*
2 Copyright © 2004-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: PCI direct driver for x86 linux.
6 Lang: English
7 */
9 #include <exec/interrupts.h>
10 #include <hidd/hidd.h>
11 #include <hidd/pci.h>
12 #include <oop/oop.h>
14 #include <utility/tagitem.h>
16 #include <proto/exec.h>
17 #include <proto/utility.h>
18 #include <proto/oop.h>
20 #include <aros/symbolsets.h>
22 #include "pci.h"
23 #include "syscall.h"
25 #define DEBUG 1
26 #include <aros/debug.h>
28 #include <unistd.h>
30 #ifdef HiddPCIDriverAttrBase
31 #undef HiddPCIDriverAttrBase
32 #endif // HiddPCIDriverAttrBase
33 #undef HiddAttrBase
35 #define HiddPCIDriverAttrBase (PSD(cl)->hiddPCIDriverAB)
36 #define HiddAttrBase (PSD(cl)->hiddAB)
38 #define CFGADD(bus,dev,func,reg) \
39 ( 0x80000000 | ((bus)<<16) | \
40 ((dev)<<11) | ((func)<<8) | ((reg)&~3))
42 typedef union _pcicfg
44 ULONG ul;
45 UWORD uw[2];
46 UBYTE ub[4];
47 } pcicfg;
50 We overload the New method in order to introduce the Hidd Name and
51 HardwareName attributes.
53 OOP_Object *PCILx__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
55 struct pRoot_New mymsg;
57 struct TagItem mytags[] = {
58 { aHidd_Name, (IPTR)"PCILinux" },
59 { aHidd_HardwareName, (IPTR)"Linux direct access PCI driver" },
60 { aHidd_PCIDriver_DirectBus, FALSE },
61 { TAG_DONE, 0 }
64 mymsg.mID = msg->mID;
65 mymsg.attrList = (struct TagItem *)&mytags;
67 if (msg->attrList)
69 mytags[3].ti_Tag = TAG_MORE;
70 mytags[3].ti_Data = (IPTR)msg->attrList;
73 msg = &mymsg;
75 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
77 return o;
81 Some in/out magic to access PCI bus on PCs
83 static inline ULONG inl(UWORD port)
85 ULONG val;
87 asm volatile ("inl %w1,%0":"=a"(val):"Nd"(port));
89 return val;
92 static inline void outl(ULONG val, UWORD port)
94 asm volatile ("outl %0,%w1"::"a"(val),"Nd"(port));
97 ULONG PCILx__Hidd_PCIDriver__ReadConfigLong(OOP_Class *cl, OOP_Object *o,
98 struct pHidd_PCIDriver_ReadConfigLong *msg)
100 ULONG orig,temp;
102 Disable();
103 orig=inl(PCI_AddressPort);
104 outl(CFGADD(msg->bus, msg->dev, msg->sub, msg->reg),PCI_AddressPort);
105 temp=inl(PCI_DataPort);
106 outl(orig, PCI_AddressPort);
107 Enable();
109 return temp;
112 void PCILx__Hidd_PCIDriver__WriteConfigLong(OOP_Class *cl, OOP_Object *o,
113 struct pHidd_PCIDriver_WriteConfigLong *msg)
115 ULONG orig;
117 Disable();
118 orig=inl(PCI_AddressPort);
119 outl(CFGADD(msg->bus, msg->dev, msg->sub, msg->reg),PCI_AddressPort);
120 outl(msg->val,PCI_DataPort);
121 outl(orig, PCI_AddressPort);
122 Enable();
125 IPTR PCILx__Hidd_PCIDriver__MapPCI(OOP_Class *cl, OOP_Object *o,
126 struct pHidd_PCIDriver_MapPCI *msg)
128 ULONG offs = (IPTR)msg->PCIAddress >> 12;
129 ULONG size = msg->Length;
130 IPTR ret;
132 D(bug("[PCILinux] PCIDriver::MapPCI(%x, %x)\n", offs, size));
134 #ifdef __x86_64__
135 asm volatile(
136 "push %%rbp; mov %%rax,%%rbp; mov %1,%%rax; int $0x80; pop %%rbp"
137 :"=a"(ret)
138 :"i"(192), "b"(0), "c"(size), "d"(0x03), "S"(0x01), "D"(PSD(cl)->fd), "0"(offs)
140 #else
141 asm volatile(
142 "push %%ebp; movl %%eax,%%ebp; movl %1,%%eax; int $0x80; pop %%ebp"
143 :"=a"(ret)
144 :"i"(192), "b"(0), "c"(size), "d"(0x03), "S"(0x01), "D"(PSD(cl)->fd), "0"(offs)
146 #endif
148 D(bug("[PCILinux] mmap syscall returned %x\n", ret));
150 return ret;
153 VOID PCILx__Hidd_PCIDriver__UnmapPCI(OOP_Class *cl, OOP_Object *o,
154 struct pHidd_PCIDriver_UnmapPCI *msg)
156 IPTR offs = (IPTR)msg->CPUAddress;
157 ULONG size = msg->Length;
159 syscall2(91, offs, size);
162 BOOL PCILx__Hidd_PCIDriver__AddInterrupt(OOP_Class *cl, OOP_Object *o,
163 struct pHidd_PCIDriver_AddInterrupt *msg)
165 /* We cannot support interrupts, sorry */
166 return FALSE;
169 VOID PCILx__Hidd_PCIDriver__RemoveInterrupt(OOP_Class *cl, OOP_Object *o,
170 struct pHidd_PCIDriver_RemoveInterrupt *msg)
175 /* Class initialization and destruction */
177 #define psd (&LIBBASE->psd)
179 static int PCILx_ExpungeClass(LIBBASETYPEPTR LIBBASE)
181 D(bug("[PCILinux] deleting classes\n"));
183 OOP_ReleaseAttrBase(IID_Hidd_PCIDriver);
184 OOP_ReleaseAttrBase(IID_Hidd);
186 return TRUE;
189 static int PCILx_InitClass(LIBBASETYPEPTR LIBBASE)
191 OOP_Object *pci = NULL;
193 D(bug("LinuxPCI: Driver initialization\n"));
195 psd->hiddPCIDriverAB = OOP_ObtainAttrBase(IID_Hidd_PCIDriver);
196 psd->hiddAB = OOP_ObtainAttrBase(IID_Hidd);
198 if (psd->hiddPCIDriverAB)
201 * The class may be added to the system. Add the driver
202 * to PCI subsystem as well
204 struct pHidd_PCI_AddHardwareDriver msg;
207 * PCI is suppose to destroy the class on its Dispose
209 msg.driverClass = psd->driverClass;
210 msg.mID = OOP_GetMethodID(IID_Hidd_PCI, moHidd_PCI_AddHardwareDriver);
212 // Add it for God's sake! ;)
213 pci = OOP_NewObject(NULL, CLID_Hidd_PCI, NULL);
214 OOP_DoMethod(pci, (OOP_Msg)&msg);
215 OOP_DisposeObject(pci);
217 else
218 return FALSE;
220 D(bug("LinuxPCI: Driver ClassPtr = %x\n", psd->driverClass));
222 return TRUE;
225 ADD2INITLIB(PCILx_InitClass, 0)
226 ADD2EXPUNGELIB(PCILx_ExpungeClass, 0)