Updated PCI IDs to latest snapshot.
[tangerine.git] / arch / common / hidd.pci / pcidriverclass.c
blob1ce1fb2e6c1a3349cf5d4dae900134e385f3c4d3
1 /*
2 Copyright © 2004-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Base PCI driver class
6 Lang: English
8 I am not sure, whether this piece of code is already aware of endianess.
9 Has to be checked soon ;)
12 #include <exec/types.h>
13 #include <hidd/hidd.h>
14 #include <hidd/pci.h>
15 #include <oop/oop.h>
17 #include <utility/tagitem.h>
19 #include <proto/exec.h>
20 #include <proto/utility.h>
21 #include <proto/oop.h>
23 #include <aros/symbolsets.h>
25 #include "pci.h"
27 #define DEBUG 1
28 #include <aros/debug.h>
30 #ifdef HiddPCIDriverAttrBase
31 #undef HiddPCIDriverAttrBase
32 #endif // HiddPCIDriverAttrBase
34 #define HiddPCIDriverAttrBase (PSD(cl)->hiddPCIDriverAB)
35 #define HiddAttrBase (PSD(cl)->hiddAB)
37 typedef union _pcicfg
39 ULONG ul;
40 UWORD uw[2];
41 UBYTE ub[4];
42 } pcicfg;
44 OOP_Object *PCIDrv__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
46 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
47 struct DrvInstData *instance = (struct DrvInstData *)OOP_INST_DATA(cl, o);
49 instance->DirectBus = GetTagData(aHidd_PCIDriver_DirectBus, TRUE, msg->attrList);
51 return o;
55 ULONG PCIDriver::ReadConfigLong(bus, dev, sub, reg)
57 This method is not implemented here (aka it should be the abstract class),
58 and should be well defined in all PCI drivers.
60 ULONG PCIDrv__Hidd_PCIDriver__ReadConfigLong(OOP_Class *cl, OOP_Object *o,
61 struct pHidd_PCIDriver_ReadConfigLong *msg)
63 /* Wheeeee! Someone has forgotten to reimplement the ReadConfigLong!! */
64 bug("[PCIDriver] Alert! PCIDriver::ReadConfigLong() unimplemented!!!\n");
65 return 0xffffffff;
69 PCIDriver::WriteConfigLong(bus, dev, sub, reg, val)
71 This method is not implemented here (aka it should be the abstract class),
72 and should be well defined in all PCI drivers.
74 void PCIDrv__Hidd_PCIDriver__WriteConfigLong(OOP_Class *cl, OOP_Object *o,
75 struct pHidd_PCIDriver_WriteConfigLong *msg)
77 /* Wheeeee! Someone has forgotten to reimplement the WriteConfigLong!! */
78 bug("[PCIDriver] Alert! PCIDriver::WriteConfigLong() unimplemented!!!\n");
83 Please note, that the following methods
85 UWORD PCIDriver::ReadConfigWord()
86 UBYTE PCIDriver::ReadConfigByte()
87 VOID PCIDriver::WriteConfigWord()
88 VOID PCIDriver::WriteConfigByte()
90 *MAY* be implemented in driver class, but *DOESN'T HAVE TO*. I wrote small
91 wrappers here using ReadConfigLong and WriteConfigLong in order to simplify
92 developing of PCI drivers and reducing their size.
95 UBYTE PCIDrv__Hidd_PCIDriver__ReadConfigByte(OOP_Class *cl, OOP_Object *o,
96 struct pHidd_PCIDriver_ReadConfigByte *msg)
98 pcicfg temp;
99 struct pHidd_PCIDriver_ReadConfigLong mymsg;
102 First, read whole ConfigWord from PCI config space, using defined
103 method
105 mymsg.mID = PSD(cl)->mid_RL;
106 mymsg.bus = msg->bus;
107 mymsg.dev = msg->dev;
108 mymsg.sub = msg->sub;
109 mymsg.reg = msg->reg & ~3;
111 temp.ul = OOP_DoMethod(o, (OOP_Msg)&mymsg);
113 // Then, return only this part of the Long which is requested
114 return temp.ub[msg->reg & 3];
117 UWORD PCIDrv__Hidd_PCIDriver__ReadConfigWord(OOP_Class *cl, OOP_Object *o,
118 struct pHidd_PCIDriver_ReadConfigWord *msg)
120 pcicfg temp;
121 struct pHidd_PCIDriver_ReadConfigLong mymsg;
123 mymsg.mID = PSD(cl)->mid_RL;
124 mymsg.bus = msg->bus;
125 mymsg.dev = msg->dev;
126 mymsg.sub = msg->sub;
127 mymsg.reg = msg->reg & ~3;
129 temp.ul = OOP_DoMethod(o, (OOP_Msg)&mymsg);
131 return temp.uw[(msg->reg&2)>>1];
134 void PCIDrv__Hidd_PCIDriver__WriteConfigByte(OOP_Class *cl, OOP_Object *o,
135 struct pHidd_PCIDriver_WriteConfigByte *msg)
137 pcicfg temp;
138 struct pHidd_PCIDriver_ReadConfigLong mymsg;
139 struct pHidd_PCIDriver_WriteConfigLong mymsg2;
141 // Read whole Long from PCI config space.
142 mymsg.mID = PSD(cl)->mid_RL;
143 mymsg.bus = msg->bus;
144 mymsg.dev = msg->dev;
145 mymsg.sub = msg->sub;
146 mymsg.reg = msg->reg & ~3;
148 temp.ul = OOP_DoMethod(o, (OOP_Msg)&mymsg);
150 // Modify proper part of it according to request.
151 temp.ub[msg->reg & 3] = (UBYTE)msg->val;
153 // And put whole Long again into PCI config space.
154 mymsg2.mID = PSD(cl)->mid_WL;
155 mymsg2.bus = msg->bus;
156 mymsg2.dev = msg->dev;
157 mymsg2.sub = msg->sub;
158 mymsg2.reg = msg->reg & ~3;
159 mymsg2.val = temp.ul;
161 OOP_DoMethod(o, (OOP_Msg)&mymsg2);
164 void PCIDrv__Hidd_PCIDriver__WriteConfigWord(OOP_Class *cl, OOP_Object *o,
165 struct pHidd_PCIDriver_WriteConfigWord *msg)
167 pcicfg temp;
168 struct pHidd_PCIDriver_ReadConfigLong mymsg;
169 struct pHidd_PCIDriver_WriteConfigLong mymsg2;
171 // Read whole Long from PCI config space.
172 mymsg.mID = PSD(cl)->mid_RL;
173 mymsg.bus = msg->bus;
174 mymsg.dev = msg->dev;
175 mymsg.sub = msg->sub;
176 mymsg.reg = msg->reg & ~3;
178 temp.ul = OOP_DoMethod(o, (OOP_Msg)&mymsg);
180 // Modify proper part of it according to request.
181 temp.uw[(msg->reg&2)>>1] = (UWORD)msg->val;
183 // And put whole Long again into PCI config space.
184 mymsg2.mID = PSD(cl)->mid_WL;
185 mymsg2.bus = msg->bus;
186 mymsg2.dev = msg->dev;
187 mymsg2.sub = msg->sub;
188 mymsg2.reg = msg->reg & ~3;
189 mymsg2.val = temp.ul;
191 OOP_DoMethod(o, (OOP_Msg)&mymsg2);
196 PCIDriver::CPUtoPCI() converts the address as seen by CPU into the
197 address seen by the PCI bus. Do not reimplement this function, if
198 CPU and PCI address spaces are equal on the machine you're writting
199 driver for
201 APTR PCIDrv__Hidd_PCIDriver__CPUtoPCI(OOP_Class *cl, OOP_Object *o,
202 struct pHidd_PCIDriver_CPUtoPCI *msg)
204 struct DrvInstData *instance = (struct DrvInstData *)OOP_INST_DATA(cl, o);
206 if (instance->DirectBus)
208 return (APTR)msg->address;
209 } else return (APTR)0xffffffff;
213 PCIDriver::PCItoCPU() is opposite to above.
215 APTR PCIDrv__Hidd_PCIDriver__PCItoCPU(OOP_Class *cl, OOP_Object *o,
216 struct pHidd_PCIDriver_PCItoCPU *msg)
218 struct DrvInstData *instance = (struct DrvInstData *)OOP_INST_DATA(cl, o);
220 if (instance->DirectBus)
222 return (APTR)msg->address;
223 } else return (APTR)0xffffffff;
227 PCIDriver::MapPCI(Address, Length) maps the Length bytes of PCI address
228 space at Address to the CPU address space.
230 APTR PCIDrv__Hidd_PCIDriver__MapPCI(OOP_Class *cl, OOP_Object *o,
231 struct pHidd_PCIDriver_MapPCI *msg)
233 /* Generic driver in case of DirecAccess PCI bus */
234 struct DrvInstData *instance = (struct DrvInstData *)OOP_INST_DATA(cl, o);
236 if (instance->DirectBus)
238 struct pHidd_PCIDriver_PCItoCPU mmsg, *pmmsg=&mmsg;
239 mmsg.mID = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_PCItoCPU);
240 mmsg.address = msg->PCIAddress;
242 return ((APTR)OOP_DoMethod(o, (OOP_Msg)pmmsg));
243 } else return (APTR)0xffffffff;
247 PCIDriver::UnmapPCI(Address, Length) unmaps the mapped PCI area previously
248 allocated with MapPCI method.
250 VOID PCIDrv__Hidd_PCIDriver__UnmapPCI(OOP_Class *cl, OOP_Object *o,
251 struct pHidd_PCIDriver_UnmapPCI *msg)
253 /* Generic driver has nothing to do here */
257 PCIDriver::AllocPCIMemory(Size) allocates memory region available for
258 PCI BusMaster devices.
260 APTR PCIDrv__Hidd_PCIDriver__AllocPCIMem(OOP_Class *cl, OOP_Object *o,
261 struct pHidd_PCIDriver_AllocPCIMem *msg)
263 APTR memory = AllocVec(msg->Size + 4096 + AROS_ALIGN(sizeof(APTR)), MEMF_CLEAR);
264 IPTR diff;
266 diff = (IPTR)memory - (AROS_ROUNDUP2((IPTR)memory + sizeof(APTR), 4096));
267 *((APTR*)((IPTR)memory - diff - sizeof(APTR))) = memory;
269 return (APTR)((IPTR)memory - diff);
273 PCIDriver::FreePCIMemory(Address) frees previously allocated memory for PCI
274 devices
276 VOID PCIDrv__Hidd_PCIDriver__FreePCIMem(OOP_Class *cl, OOP_Object *o,
277 struct pHidd_PCIDriver_FreePCIMem *msg)
279 APTR memory = *(APTR*)((IPTR)msg->Address - sizeof(APTR));
280 FreeVec(memory);
283 VOID PCIDrv__Root__Get(OOP_Class *cl, OOP_Object *o,
284 struct pRoot_Get *msg)
286 ULONG idx;
287 struct DrvInstData *instance = (struct DrvInstData *)OOP_INST_DATA(cl, o);
289 if (IS_PCIDRV_ATTR(msg->attrID, idx))
291 switch(idx)
293 case aoHidd_PCIDriver_DirectBus:
294 *msg->storage = (IPTR)instance->DirectBus;
295 break;
297 default:
298 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
299 break;
302 else
304 OOP_DoSuperMethod(cl, o, (OOP_Msg) msg);
308 /* Class initialization and destruction */
310 static int PCIDrv_InitMIDs(LIBBASETYPEPTR LIBBASE)
312 D(bug("[PCIDriver] Dummy Driver initialization\n"));
314 * We do have driver class. Now we can get some MethodID's,
315 * so that whole PCI subsystem works slightly faster ;)
318 LIBBASE->psd.mid_RB = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_ReadConfigByte);
319 LIBBASE->psd.mid_RW = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_ReadConfigWord);
320 LIBBASE->psd.mid_RL = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_ReadConfigLong);
322 LIBBASE->psd.mid_WB = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_WriteConfigByte);
323 LIBBASE->psd.mid_WW = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_WriteConfigWord);
324 LIBBASE->psd.mid_WL = OOP_GetMethodID(IID_Hidd_PCIDriver, moHidd_PCIDriver_WriteConfigLong);
326 return TRUE;
329 ADD2INITLIB(PCIDrv_InitMIDs, 0)