2 Copyright © 2004-2013, The AROS Development Team. All rights reserved.
5 Desc: PCI direct driver for x86 linux.
9 #include <exec/interrupts.h>
10 #include <hidd/hidd.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>
26 #include <aros/debug.h>
30 #ifdef HiddPCIDriverAttrBase
31 #undef HiddPCIDriverAttrBase
32 #endif // HiddPCIDriverAttrBase
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))
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
},
65 mymsg
.attrList
= (struct TagItem
*)&mytags
;
69 mytags
[3].ti_Tag
= TAG_MORE
;
70 mytags
[3].ti_Data
= (IPTR
)msg
->attrList
;
75 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
81 Some in/out magic to access PCI bus on PCs
83 static inline ULONG
inl(UWORD port
)
87 asm volatile ("inl %w1,%0":"=a"(val
):"Nd"(port
));
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
)
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
);
112 void PCILx__Hidd_PCIDriver__WriteConfigLong(OOP_Class
*cl
, OOP_Object
*o
,
113 struct pHidd_PCIDriver_WriteConfigLong
*msg
)
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
);
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
;
132 D(bug("[PCILinux] PCIDriver::MapPCI(%x, %x)\n", offs
, size
));
136 "push %%rbp; mov %%rax,%%rbp; mov %1,%%rax; int $0x80; pop %%rbp"
138 :"i"(192), "b"(0), "c"(size
), "d"(0x03), "S"(0x01), "D"(PSD(cl
)->fd
), "0"(offs
)
142 "push %%ebp; movl %%eax,%%ebp; movl %1,%%eax; int $0x80; pop %%ebp"
144 :"i"(192), "b"(0), "c"(size
), "d"(0x03), "S"(0x01), "D"(PSD(cl
)->fd
), "0"(offs
)
148 D(bug("[PCILinux] mmap syscall returned %x\n", 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 */
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
);
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
);
220 D(bug("LinuxPCI: Driver ClassPtr = %x\n", psd
->driverClass
));
225 ADD2INITLIB(PCILx_InitClass
, 0)
226 ADD2EXPUNGELIB(PCILx_ExpungeClass
, 0)