2 Copyright © 2004-2006, The AROS Development Team. All rights reserved.
5 Desc: PCI direct driver for x86_64 linux.
8 #include <exec/types.h>
13 #include <utility/tagitem.h>
15 #include <proto/exec.h>
16 #include <proto/utility.h>
17 #include <proto/oop.h>
19 #include <aros/symbolsets.h>
24 #include <aros/debug.h>
26 #ifdef HiddPCIDriverAttrBase
27 #undef HiddPCIDriverAttrBase
28 #endif // HiddPCIDriverAttrBase
30 #define HiddPCIDriverAttrBase (PSD(cl)->hiddPCIDriverAB)
31 #define HiddAttrBase (PSD(cl)->hiddAB)
33 #define CFGADD(bus,dev,func,reg) \
34 ( 0x80000000 | ((bus)<<16) | \
35 ((dev)<<11) | ((func)<<8) | ((reg)&~3))
45 We overload the New method in order to introduce the Hidd Name and
46 HardwareName attributes.
48 OOP_Object
*PCILx__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
50 struct pRoot_New mymsg
;
52 struct TagItem mytags
[] = {
53 { aHidd_Name
, (IPTR
)"PCILinux" },
54 { aHidd_HardwareName
, (IPTR
)"Linux direct access PCI driver" },
55 { aHidd_PCIDriver_DirectBus
, FALSE
},
60 mymsg
.attrList
= (struct TagItem
*)&mytags
;
64 mytags
[3].ti_Tag
= TAG_MORE
;
65 mytags
[3].ti_Data
= (IPTR
)msg
->attrList
;
70 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
76 Some in/out magic to access PCI bus on PCs
79 static inline ULONG
inl(UWORD port
)
83 asm volatile ("inl %w1,%0":"=a"(val
):"Nd"(port
));
88 static inline void outl(ULONG val
, UWORD port
)
90 asm volatile ("outl %0,%w1"::"a"(val
),"Nd"(port
));
93 ULONG
PCILx__Hidd_PCIDriver__ReadConfigLong(OOP_Class
*cl
, OOP_Object
*o
,
94 struct pHidd_PCIDriver_ReadConfigLong
*msg
)
99 orig
=inl(PCI_AddressPort
);
100 outl(CFGADD(msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
),PCI_AddressPort
);
101 temp
=inl(PCI_DataPort
);
102 outl(orig
, PCI_AddressPort
);
108 void PCILx__Hidd_PCIDriver__WriteConfigLong(OOP_Class
*cl
, OOP_Object
*o
,
109 struct pHidd_PCIDriver_WriteConfigLong
*msg
)
114 orig
=inl(PCI_AddressPort
);
115 outl(CFGADD(msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
),PCI_AddressPort
);
116 outl(msg
->val
,PCI_DataPort
);
117 outl(orig
, PCI_AddressPort
);
121 IPTR
PCILx__Hidd_PCIDriver__MapPCI(OOP_Class
*cl
, OOP_Object
*o
,
122 struct pHidd_PCIDriver_MapPCI
*msg
)
124 ULONG offs
= (IPTR
)msg
->PCIAddress
>> 12;
125 ULONG size
= msg
->Length
;
128 D(bug("[PCILinux] PCIDriver::MapPCI(%x, %x)\n", offs
, size
));
130 "push %%rbp; mov %%rax,%%rbp; mov %1,%%rax; int $0x80; pop %%rbp"
132 :"i"(192), "b"(0), "c"(size
), "d"(0x03), "S"(0x01), "D"(PSD(cl
)->fd
), "0"(offs
)
135 D(bug("[PCILinux] mmap syscall returned %x\n", ret
));
140 VOID
PCILx__Hidd_PCIDriver__UnmapPCI(OOP_Class
*cl
, OOP_Object
*o
,
141 struct pHidd_PCIDriver_UnmapPCI
*msg
)
143 ULONG offs
= (ULONG
)msg
->CPUAddress
;
144 ULONG size
= msg
->Length
;
149 :"a"(91),"b"(offs
),"c"(size
));
152 /* Class initialization and destruction */
154 #define psd (&LIBBASE->psd)
156 static int PCILx_ExpungeClass(LIBBASETYPEPTR LIBBASE
)
158 D(bug("[PCILinux] deleting classes\n"));
160 OOP_ReleaseAttrBase(IID_Hidd_PCIDriver
);
161 OOP_ReleaseAttrBase(IID_Hidd
);
166 static int PCILx_InitClass(LIBBASETYPEPTR LIBBASE
)
168 OOP_Object
*pci
= NULL
;
170 D(bug("LinuxPCI: Driver initialization\n"));
172 psd
->hiddPCIDriverAB
= OOP_ObtainAttrBase(IID_Hidd_PCIDriver
);
173 psd
->hiddAB
= OOP_ObtainAttrBase(IID_Hidd
);
175 if (psd
->hiddPCIDriverAB
)
178 * The class may be added to the system. Add the driver
179 * to PCI subsystem as well
181 struct pHidd_PCI_AddHardwareDriver msg
;
184 * PCI is suppose to destroy the class on its Dispose
186 msg
.driverClass
= psd
->driverClass
;
187 msg
.mID
= OOP_GetMethodID(IID_Hidd_PCI
, moHidd_PCI_AddHardwareDriver
);
189 // Add it for God's sake! ;)
190 pci
= OOP_NewObject(NULL
, CLID_Hidd_PCI
, NULL
);
191 OOP_DoMethod(pci
, (OOP_Msg
)&msg
);
192 OOP_DisposeObject(pci
);
197 D(bug("LinuxPCI: Driver ClassPtr = %x\n", psd
->driverClass
));
202 ADD2INITLIB(PCILx_InitClass
, 0)
203 ADD2EXPUNGELIB(PCILx_ExpungeClass
, 0)