2 Copyright © 2004-2016, 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 <aros/debug.h>
13 #include <exec/types.h>
14 #include <hidd/hidd.h>
17 #include <utility/tagitem.h>
18 #include <proto/exec.h>
19 #include <proto/kernel.h>
20 #include <proto/utility.h>
21 #include <proto/oop.h>
22 #include <aros/symbolsets.h>
26 OOP_Object
*PCIDrv__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
28 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
29 struct DrvInstData
*instance
= (struct DrvInstData
*)OOP_INST_DATA(cl
, o
);
31 instance
->DirectBus
= GetTagData(aHidd_PCIDriver_DirectBus
, TRUE
, msg
->attrList
);
32 instance
->IOBase
= GetTagData(aHidd_PCIDriver_IOBase
, 0, msg
->attrList
);
38 ULONG PCIDriver::ReadConfigLong(bus, dev, sub, reg)
40 This method is not implemented here (aka it should be the abstract class),
41 and should be well defined in all PCI drivers.
43 ULONG
PCIDrv__Hidd_PCIDriver__ReadConfigLong(OOP_Class
*cl
, OOP_Object
*o
,
44 struct pHidd_PCIDriver_ReadConfigLong
*msg
)
46 /* Wheeeee! Someone has forgotten to reimplement ReadConfigLong! */
47 bug("[PCIDriver] Alert! PCIDriver::ReadConfigLong() unimplemented!\n");
52 PCIDriver::WriteConfigLong(bus, dev, sub, reg, val)
54 This method is not implemented here (aka it should be the abstract class),
55 and should be well defined in all PCI drivers.
57 void PCIDrv__Hidd_PCIDriver__WriteConfigLong(OOP_Class
*cl
, OOP_Object
*o
,
58 struct pHidd_PCIDriver_WriteConfigLong
*msg
)
60 /* Wheeeee! Someone has forgotten to reimplement WriteConfigLong! */
61 bug("[PCIDriver] Alert! PCIDriver::WriteConfigLong() unimplemented!\n");
65 IPTR PCIDriver::HasExtendedConfiguration(bus, dev, sub)
67 This does not need to be implemented in the driver; in that case
68 ECAM access method is not used and extended configuration is unavailable.
70 IPTR
PCIDrv__Hidd_PCIDriver__HasExtendedConfig(OOP_Class
*cl
, OOP_Object
*o
,
71 struct pHidd_PCIDriver_HasExtendedConfig
*msg
)
73 /* Wheeeee! Someone has forgotten to reimplement HasExtendedConfig! */
74 bug("[PCIDriver] Alert! PCIDriver::HasExtendedConfig() unimplemented!\n");
79 Please note, that the following methods
81 UWORD PCIDriver::ReadConfigWord()
82 UBYTE PCIDriver::ReadConfigByte()
83 VOID PCIDriver::WriteConfigWord()
84 VOID PCIDriver::WriteConfigByte()
86 *MAY* be implemented in driver class, but *DON'T HAVE TO BE*. I wrote small
87 wrappers here using ReadConfigLong and WriteConfigLong in order to simplify
88 development of PCI drivers and reduce their size.
91 UBYTE
PCIDrv__Hidd_PCIDriver__ReadConfigByte(OOP_Class
*cl
, OOP_Object
*o
,
92 struct pHidd_PCIDriver_ReadConfigByte
*msg
)
95 * First, read whole ConfigWord from PCI config space, using defined
98 ULONG temp
= HIDD_PCIDriver_ReadConfigLong(o
, msg
->device
, msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
& ~3);
100 // Then, return only this part of the Long which is requested
101 return (temp
>> ((msg
->reg
& 3) * 8)) & 0xff;
104 UWORD
PCIDrv__Hidd_PCIDriver__ReadConfigWord(OOP_Class
*cl
, OOP_Object
*o
,
105 struct pHidd_PCIDriver_ReadConfigWord
*msg
)
107 ULONG temp
= HIDD_PCIDriver_ReadConfigLong(o
, msg
->device
, msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
& ~3);
109 return (temp
>> ((msg
->reg
& 2) * 8)) & 0xffff;
112 void PCIDrv__Hidd_PCIDriver__WriteConfigByte(OOP_Class
*cl
, OOP_Object
*o
,
113 struct pHidd_PCIDriver_WriteConfigByte
*msg
)
116 const int shift
= (msg
->reg
& 3) * 8;
118 // Read whole Long from PCI config space.
119 temp
= HIDD_PCIDriver_ReadConfigLong(o
, msg
->device
, msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
& ~3);
121 // Modify proper part of it according to request.
122 temp
= (temp
& ~(0xff << shift
)) | ((ULONG
)msg
->val
<< shift
);
124 // And put whole Long again into PCI config space.
125 HIDD_PCIDriver_WriteConfigLong(o
, msg
->device
, msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
& ~3, temp
);
128 void PCIDrv__Hidd_PCIDriver__WriteConfigWord(OOP_Class
*cl
, OOP_Object
*o
,
129 struct pHidd_PCIDriver_WriteConfigWord
*msg
)
132 const int shift
= (msg
->reg
& 2) * 8;
134 // Read whole Long from PCI config space.
135 temp
= HIDD_PCIDriver_ReadConfigLong(o
, msg
->device
, msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
& ~3);
137 // Modify proper part of it according to request.
138 temp
= (temp
& ~(0xffff << shift
)) | ((ULONG
)msg
->val
<< shift
);
140 // And put whole Long again into PCI config space.
141 HIDD_PCIDriver_WriteConfigLong(o
, msg
->device
, msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
& ~3, temp
);
145 PCIDriver::CPUtoPCI() converts the address as seen by CPU into the
146 address seen by the PCI bus. Do not reimplement this function, if
147 CPU and PCI address spaces are equal on the machine you're writing a
150 APTR
PCIDrv__Hidd_PCIDriver__CPUtoPCI(OOP_Class
*cl
, OOP_Object
*o
,
151 struct pHidd_PCIDriver_CPUtoPCI
*msg
)
153 struct DrvInstData
*instance
= (struct DrvInstData
*)OOP_INST_DATA(cl
, o
);
155 if (instance
->DirectBus
)
156 return (APTR
)msg
->address
;
162 PCIDriver::PCItoCPU() is opposite to above.
164 APTR
PCIDrv__Hidd_PCIDriver__PCItoCPU(OOP_Class
*cl
, OOP_Object
*o
,
165 struct pHidd_PCIDriver_PCItoCPU
*msg
)
167 struct DrvInstData
*instance
= (struct DrvInstData
*)OOP_INST_DATA(cl
, o
);
169 if (instance
->DirectBus
)
170 return (APTR
)msg
->address
;
176 PCIDriver::MapPCI(Address, Length) maps the Length bytes of PCI address
177 space at Address to the CPU address space.
179 APTR
PCIDrv__Hidd_PCIDriver__MapPCI(OOP_Class
*cl
, OOP_Object
*o
,
180 struct pHidd_PCIDriver_MapPCI
*msg
)
183 * Generic driver in case of DirectAccess PCI bus.
184 * Our memory space is already mapped, but we may still need
185 * to perform physical to virtual translation (in case our
186 * system uses virtual addressing).
188 struct DrvInstData
*instance
= (struct DrvInstData
*)OOP_INST_DATA(cl
, o
);
190 if (instance
->DirectBus
)
191 return HIDD_PCIDriver_PCItoCPU(o
, msg
->PCIAddress
);
197 PCIDriver::UnmapPCI(Address, Length) unmaps the mapped PCI area previously
198 allocated with MapPCI method.
200 VOID
PCIDrv__Hidd_PCIDriver__UnmapPCI(OOP_Class
*cl
, OOP_Object
*o
,
201 struct pHidd_PCIDriver_UnmapPCI
*msg
)
203 /* Generic driver has nothing to do here */
207 PCIDriver::AllocPCIMem(Size) allocates memory region available for
208 PCI BusMaster devices.
210 APTR
PCIDrv__Hidd_PCIDriver__AllocPCIMem(OOP_Class
*cl
, OOP_Object
*o
,
211 struct pHidd_PCIDriver_AllocPCIMem
*msg
)
213 APTR memory
= AllocVec(msg
->Size
+ 4096 + AROS_ALIGN(sizeof(APTR
)), MEMF_31BIT
|MEMF_CLEAR
);
216 diff
= (IPTR
)memory
- (AROS_ROUNDUP2((IPTR
)memory
+ sizeof(APTR
), 4096));
217 *((APTR
*)((IPTR
)memory
- diff
- sizeof(APTR
))) = memory
;
219 return (APTR
)((IPTR
)memory
- diff
);
223 PCIDriver::FreePCIMemory(Address) frees previously allocated memory for PCI
226 VOID
PCIDrv__Hidd_PCIDriver__FreePCIMem(OOP_Class
*cl
, OOP_Object
*o
,
227 struct pHidd_PCIDriver_FreePCIMem
*msg
)
229 APTR memory
= *(APTR
*)((IPTR
)msg
->Address
- sizeof(APTR
));
233 static void krnIRQwrapper(void *data1
, void *data2
)
235 struct Interrupt
*irq
= (struct Interrupt
*)data1
;
237 AROS_INTC1(irq
->is_Code
, irq
->is_Data
);
240 /*****************************************************************************************
243 moHidd_PCIDriver_AddInterrupt
246 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDriver_AddInterrupt *Msg);
248 OOP_Object *HIDD_PCIDriver_AddInterrupt(OOP_Object *obj, OOP_Object *device,
249 struct Interrupt *interrupt);
255 Add interrupt handler for the specified device.
257 This method is present in order to provide abstraction for
258 different PCI implementations. Default implementation of
259 this method assumes 1:1 mapping between system interrupts
260 and PCI interrupts. However, on some machines this is not
261 true (an example is Amiga(tm) bridgeboards). In this case
262 you will have to provide alternate implementation of this
266 obj - Pointer to your driver object.
267 device - A pointer to the device object.
268 interrupt - Interrupt structure to add.
271 TRUE it succesful or FALSE on failure.
280 moHidd_PCIDriver_RemoveInterrupt
284 *****************************************************************************************/
286 BOOL
PCIDrv__Hidd_PCIDriver__AddInterrupt(OOP_Class
*cl
, OOP_Object
*o
,
287 struct pHidd_PCIDriver_AddInterrupt
*msg
)
291 OOP_GetAttr(msg
->device
, aHidd_PCIDevice_INTLine
, &irq
);
292 msg
->interrupt
->is_Node
.ln_Succ
=
293 KrnAddIRQHandler(irq
, krnIRQwrapper
, msg
->interrupt
, NULL
);
294 return msg
->interrupt
->is_Node
.ln_Succ
? TRUE
: FALSE
;
297 /*****************************************************************************************
300 moHidd_PCIDriver_RemoveInterrupt
303 OOP_Object *OOP_DoMethod(OOP_Object *obj, struct pHidd_PCIDriver_RemoveInterrupt *Msg);
305 OOP_Object *HIDD_PCIDriver_RemoveInterrupt(OOP_Object *obj, OOP_Object *device,
306 struct Interrupt *interrupt);
312 Remove interrupt handler from the specified device.
314 This method is present in order to provide abstraction for
315 different PCI implementations. Default implementation of
316 this method assumes 1:1 mapping between system interrupts
317 and PCI interrupts. However, on some machines this is not
318 true (an example is Amiga(tm) bridgeboards). In this case
319 you will have to provide alternate implementation of this
323 obj - Pointer to your driver object.
324 device - A pointer to the device object.
325 interrupt - Interrupt structure to remove.
337 moHidd_PCIDriver_AddInterrupt
341 *****************************************************************************************/
343 VOID
PCIDrv__Hidd_PCIDriver__RemoveInterrupt(OOP_Class
*cl
, OOP_Object
*o
,
344 struct pHidd_PCIDriver_RemoveInterrupt
*msg
)
346 KrnRemIRQHandler(msg
->interrupt
->is_Node
.ln_Succ
);
349 VOID
PCIDrv__Root__Get(OOP_Class
*cl
, OOP_Object
*o
,
350 struct pRoot_Get
*msg
)
353 struct DrvInstData
*instance
= (struct DrvInstData
*)OOP_INST_DATA(cl
, o
);
355 if (IS_PCIDRV_ATTR(msg
->attrID
, idx
))
359 case aoHidd_PCIDriver_DirectBus
:
360 *msg
->storage
= (IPTR
)instance
->DirectBus
;
363 case aoHidd_PCIDriver_IOBase
:
364 *msg
->storage
= (IPTR
)instance
->IOBase
;
368 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);
374 OOP_DoSuperMethod(cl
, o
, (OOP_Msg
) msg
);