2 Copyright © 2004-2006, The AROS Development Team. All rights reserved.
5 Desc: Base PCI driver class
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>
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>
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)
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
);
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");
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
)
99 struct pHidd_PCIDriver_ReadConfigLong mymsg
;
102 First, read whole ConfigWord from PCI config space, using defined
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
)
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
)
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
)
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
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
);
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
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
));
283 VOID
PCIDrv__Root__Get(OOP_Class
*cl
, OOP_Object
*o
,
284 struct pRoot_Get
*msg
)
287 struct DrvInstData
*instance
= (struct DrvInstData
*)OOP_INST_DATA(cl
, o
);
289 if (IS_PCIDRV_ATTR(msg
->attrID
, idx
))
293 case aoHidd_PCIDriver_DirectBus
:
294 *msg
->storage
= (IPTR
)instance
->DirectBus
;
298 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
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
);
329 ADD2INITLIB(PCIDrv_InitMIDs
, 0)