added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / x86_64-linux / pcilinux / driverclass.c
blobdbcf16a98bbc049f47b083cb05fc3ee41551202d
1 /*
2 Copyright © 2004-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: PCI direct driver for x86_64 linux.
6 Lang: English
7 */
8 #include <exec/types.h>
9 #include <hidd/hidd.h>
10 #include <hidd/pci.h>
11 #include <oop/oop.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>
21 #include "pci.h"
23 #define DEBUG 1
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))
37 typedef union _pcicfg
39 ULONG ul;
40 UWORD uw[2];
41 UBYTE ub[4];
42 } pcicfg;
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 },
56 { TAG_DONE, 0 }
59 mymsg.mID = msg->mID;
60 mymsg.attrList = (struct TagItem *)&mytags;
62 if (msg->attrList)
64 mytags[3].ti_Tag = TAG_MORE;
65 mytags[3].ti_Data = (IPTR)msg->attrList;
68 msg = &mymsg;
70 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
72 return o;
76 Some in/out magic to access PCI bus on PCs
79 static inline ULONG inl(UWORD port)
81 ULONG val;
83 asm volatile ("inl %w1,%0":"=a"(val):"Nd"(port));
85 return val;
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)
96 ULONG orig,temp;
98 Disable();
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);
103 Enable();
105 return temp;
108 void PCILx__Hidd_PCIDriver__WriteConfigLong(OOP_Class *cl, OOP_Object *o,
109 struct pHidd_PCIDriver_WriteConfigLong *msg)
111 ULONG orig;
113 Disable();
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);
118 Enable();
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;
126 IPTR ret;
128 D(bug("[PCILinux] PCIDriver::MapPCI(%x, %x)\n", offs, size));
129 asm volatile(
130 "push %%rbp; mov %%rax,%%rbp; mov %1,%%rax; int $0x80; pop %%rbp"
131 :"=a"(ret)
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));
137 return 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;
146 asm volatile(
147 "int $0x80"
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);
163 return TRUE;
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);
194 else
195 return FALSE;
197 D(bug("LinuxPCI: Driver ClassPtr = %x\n", psd->driverClass));
199 return TRUE;
202 ADD2INITLIB(PCILx_InitClass, 0)
203 ADD2EXPUNGELIB(PCILx_ExpungeClass, 0)