2 Copyright © 2004-2006, The AROS Development Team. All rights reserved.
5 Desc: PCI direct driver for Elbox Mediator series
9 #define __OOP_NOATTRBASES__
12 #include <aros/debug.h>
14 #include <exec/types.h>
18 #include <libraries/configvars.h>
19 #include <utility/tagitem.h>
21 #include <proto/exec.h>
22 #include <proto/utility.h>
23 #include <proto/oop.h>
24 #include <proto/expansion.h>
26 #include <aros/symbolsets.h>
29 #include "pci_resource.h"
32 #undef HiddPCIDriverAttrBase
35 #define HiddPCIDriverAttrBase (PSD(cl)->hiddPCIDriverAB)
36 #define HiddAttrBase (PSD(cl)->hiddAB)
38 #define pci_readl(b, d, f, r) base->cfg_readl(base, b, d, f, r)
39 #define pci_writel(b, d, f, r, v) base->cfg_writel(base, b, d, f, r, v)
41 static ULONG
a12k_pci_readl(struct pcibase
*base
, UBYTE bus
, UBYTE dev
, UBYTE sub
, UBYTE reg
)
49 offset
= EMPB_CONF_DEV_STRIDE
* dev
+
50 EMPB_CONF_FUNC_STRIDE
* sub
+
55 base
->setup
[EMPB_SETUP_BRIDGE_OFF
] = EMPB_BRIDGE_CONF
;
56 tmp
= base
->config
[offset
];
57 base
->setup
[EMPB_SETUP_BRIDGE_OFF
] = EMPB_BRIDGE_IO
;
60 return AROS_LE2LONG(tmp
);
63 static VOID
a12k_pci_writel(struct pcibase
*base
, UBYTE bus
, UBYTE dev
, UBYTE sub
, UBYTE reg
, ULONG val
)
70 offset
= EMPB_CONF_DEV_STRIDE
* dev
+
71 EMPB_CONF_FUNC_STRIDE
* sub
+
75 val
= AROS_LONG2LE(val
);
78 base
->setup
[EMPB_SETUP_BRIDGE_OFF
] = EMPB_BRIDGE_CONF
;
79 base
->config
[offset
] = val
;
80 base
->setup
[EMPB_SETUP_BRIDGE_OFF
] = EMPB_BRIDGE_IO
;
84 static BOOL
a12k_init(struct pcibase
*base
)
86 D(bug("MEDIATOR: Attempting A1200 style init\n"));
88 base
->setup
= base
->baseDev
->cd_BoardAddr
;
89 base
->config
= base
->baseDev
->cd_BoardAddr
+ EMPB_BRIDGE_OFF
;
90 base
->cfg_readl
= a12k_pci_readl
;
91 base
->cfg_writel
= a12k_pci_writel
;
93 base
->io
= CreatePCIResourceList((IPTR
)base
->baseDev
->cd_BoardAddr
+ EMPB_BRIDGE_OFF
, EMPB_BRIDGE_SIZE
+ 1);
94 base
->mem
= CreatePCIResourceList((IPTR
)base
->memDev
->cd_BoardAddr
, base
->memDev
->cd_BoardSize
);
99 static ULONG
a4k_pci_readl(struct pcibase
*base
, UBYTE bus
, UBYTE dev
, UBYTE sub
, UBYTE reg
)
107 offset
= EMZ4_CONF_BUS_STRIDE
* bus
+
108 EMZ4_CONF_DEV_STRIDE
* dev
+
109 EMZ4_CONF_FUNC_STRIDE
* sub
+
113 tmp
= base
->config
[offset
];
115 return AROS_LE2LONG(tmp
);
118 static VOID
a4k_pci_writel(struct pcibase
*base
, UBYTE bus
, UBYTE dev
, UBYTE sub
, UBYTE reg
, ULONG val
)
125 offset
= EMZ4_CONF_BUS_STRIDE
* bus
+
126 EMZ4_CONF_DEV_STRIDE
* dev
+
127 EMZ4_CONF_FUNC_STRIDE
* sub
+
131 base
->config
[offset
] = AROS_LONG2LE(val
);
134 static BOOL
a4k_init(struct pcibase
*base
)
136 D(bug("MEDIATOR: Attempting A3000/4000 style init\n"));
138 base
->setup
= base
->baseDev
->cd_BoardAddr
;
139 base
->config
= base
->baseDev
->cd_BoardAddr
+ EMZ4_CONFIG_OFF
;
141 base
->setup
[EMZ4_SETUP_STATUS_OFF
] = 0x00;
142 base
->setup
[EMZ4_SETUP_CONFIG_OFF
] = 0x41;
144 base
->cfg_readl
= a4k_pci_readl
;
145 base
->cfg_writel
= a4k_pci_writel
;
147 base
->io
= CreatePCIResourceList((IPTR
)base
->baseDev
->cd_BoardAddr
+ EMZ4_IOPORT_OFF
, EMZ4_IOPORT_SIZE
+ 1);
148 base
->mem
= CreatePCIResourceList((IPTR
)base
->memDev
->cd_BoardAddr
, base
->memDev
->cd_BoardSize
);
153 static void PCIInitialize(struct pcibase
*base
, int bus
, struct MinList
*io
, struct MinList
*mem
)
158 D(bug("MEDIATOR: Dumping config area for device 0:\n"));
159 for (i
= 0; i
< 256/4; i
++) {
163 D(bug("%c%08x", (i
==2) ? '-' : ' ',pci_readl(0, 0, 0, i
)));
170 /* Initialize all devices attached to this PCIDriver
172 * TODO: Handle PCI bridges
174 for (dev
= 0; dev
< 32; dev
++) {
175 for (sub
= 0; sub
< 8; sub
++) {
178 UBYTE cmd
= PCICMF_BUSMASTER
;
180 venprod
= pci_readl(bus
, dev
, sub
, 0);
181 if (venprod
== 0 || venprod
== ~0)
184 D(bug("MEDIATOR: %d:%02x.%d %04x:%04x\n", bus
, dev
, sub
, venprod
& 0xffff, (venprod
>> 16) & 0xffff));
186 /* Program the 6 BARs */
187 for (i
= 0; i
< 6; i
++) {
188 ULONG bar
, start
, size
;
190 pci_writel(bus
, dev
, sub
, PCICS_BAR0
+ i
* 4, ~0);
191 bar
= pci_readl(bus
, dev
, sub
, PCICS_BAR0
+ i
* 4);
192 size
= bar
& ((bar
& PCIBAR_MASK_TYPE
) ? PCIBAR_MASK_IO
: PCIBAR_MASK_MEM
);
197 if ((bar
& PCIBAR_MASK_TYPE
) == PCIBAR_TYPE_IO
) {
198 start
= AllocPCIResource(base
->io
, size
);
199 cmd
|= PCICMF_IODECODE
;
201 start
= AllocPCIResource(base
->mem
, size
);
202 cmd
|= PCICMF_MEMDECODE
;
206 D(bug("\tBAR%d: %s - %d bytes unallocated\n", i
, (bar
& PCIBAR_MASK_TYPE
) ? "IO" : "Mem", size
));
212 D(bug("\tBAR%d: %s 0x%x-0x%x\n", i
, (bar
& PCIBAR_MASK_TYPE
) ? "IO" : "Mem", start
, start
+ size
- 1));
214 pci_writel(bus
, dev
, sub
, PCICS_BAR0
+ i
*4, start
);
216 if ((bar
& PCIBAR_MEMTYPE_MASK
) == PCIBAR_MEMTYPE_64BIT
) {
217 /* Skip the 2nd part of a 64 bit BAR */
219 pci_writel(bus
, dev
, sub
, PCICS_BAR0
+ i
*4, 0);
223 /* Set up the interrupt */
224 tmp
= pci_readl(bus
, dev
, sub
, PCICS_INT_LINE
);
227 pci_writel(bus
, dev
, sub
, PCICS_INT_LINE
, tmp
);
229 /* Enable the device */
230 tmp
= pci_readl(bus
, dev
, sub
, PCICS_COMMAND
);
233 pci_writel(bus
, dev
, sub
, PCICS_COMMAND
, tmp
);
235 /* If not multi-function, skip the rest */
237 tmp
= pci_readl(bus
, dev
, sub
, PCICS_CACHELS
);
240 if (!(tmp
& PCIHT_MULTIFUNC
))
248 We overload the New method in order to introduce the Hidd Name and
249 HardwareName attributes.
251 OOP_Object
*PCIMediator__Root__New(OOP_Class
*cl
, OOP_Object
*o
, struct pRoot_New
*msg
)
253 struct pRoot_New mymsg
;
254 struct ConfigDev
*baseDev
, *memDev
;
255 struct CurrentBinding cb
;
256 struct Library
*ExpansionBase
;
258 struct TagItem mytags
[] = {
259 { aHidd_Name
, (IPTR
)"PCIMediator" },
260 { aHidd_HardwareName
, (IPTR
)"Elbox Mediator PCI driver" },
264 if (!(ExpansionBase
= OpenLibrary("expansion.library",33))) {
265 OOP_DisposeObject(o
);
269 if (GetCurrentBinding(&cb
, sizeof(cb
)) == sizeof(cb
)) {
270 baseDev
= cb
.cb_ConfigDev
;
271 D(bug("MEDIATOR: Configuring for %d/%d @%p\n", baseDev
->cd_Rom
.er_Manufacturer
, baseDev
->cd_Rom
.er_Product
, baseDev
->cd_BoardAddr
));
272 if ((memDev
= FindConfigDev(baseDev
, baseDev
->cd_Rom
.er_Manufacturer
, baseDev
->cd_Rom
.er_Product
| 0x80))) {
273 D(bug("MEDIATOR: Found companion board\n"));
275 baseDev
->cd_Flags
&= ~CDF_CONFIGME
;
276 baseDev
->cd_Driver
= BASE(cl
);
278 memDev
->cd_Flags
&= ~CDF_CONFIGME
;
279 memDev
->cd_Driver
= BASE(cl
);
281 BASE(cl
)->baseDev
= baseDev
;
282 BASE(cl
)->memDev
= memDev
;
284 mymsg
.mID
= msg
->mID
;
285 mymsg
.attrList
= (struct TagItem
*)&mytags
;
289 mytags
[2].ti_Tag
= TAG_MORE
;
290 mytags
[2].ti_Data
= (IPTR
)msg
->attrList
;
295 /* Set up board, based on whether the baseDev is
296 * in Zorro III space or not.
298 if (baseDev
->cd_Rom
.er_Flags
& ERFF_EXTENDED
) {
304 /* Initialize bus 0 */
305 PCIInitialize(BASE(cl
), 0, BASE(cl
)->io
, BASE(cl
)->mem
);
307 /* We don't need these resource lists any longer */
308 DeletePCIResourceList(BASE(cl
)->io
);
309 DeletePCIResourceList(BASE(cl
)->mem
);
311 o
= (OOP_Object
*)OOP_DoSuperMethod(cl
, o
, (OOP_Msg
)msg
);
313 OOP_DisposeObject(o
);
316 OOP_DisposeObject(o
);
319 CloseLibrary(ExpansionBase
);
324 VOID
PCIMediator__Root__Dispose(OOP_Class
*cl
, OOP_Object
*o
, OOP_Msg msg
)
326 BASE(cl
)->baseDev
->cd_Flags
|= CDF_CONFIGME
;
327 BASE(cl
)->baseDev
->cd_Driver
= NULL
;
328 BASE(cl
)->memDev
->cd_Flags
|= CDF_CONFIGME
;
329 BASE(cl
)->memDev
->cd_Driver
= NULL
;
332 void PCIMediator__Hidd_PCIDriver__WriteConfigLong(OOP_Class
*cl
, OOP_Object
*o
,
333 struct pHidd_PCIDriver_WriteConfigLong
*msg
)
335 BASE(cl
)->cfg_writel(BASE(cl
), msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
, msg
->val
);
338 ULONG
PCIMediator__Hidd_PCIDriver__ReadConfigLong(OOP_Class
*cl
, OOP_Object
*o
,
339 struct pHidd_PCIDriver_ReadConfigLong
*msg
)
341 return BASE(cl
)->cfg_readl(BASE(cl
), msg
->bus
, msg
->dev
, msg
->sub
, msg
->reg
);
344 /* Class initialization and destruction */
345 static int PCIMediator_InitClass(LIBBASETYPEPTR LIBBASE
)
349 struct pHidd_PCI_AddHardwareDriver msg
,*pmsg
=&msg
;
351 D(bug("PCIMediator: Driver initialization\n"));
353 LIBBASE
->psd
.hiddPCIDriverAB
= OOP_ObtainAttrBase(IID_Hidd_PCIDriver
);
354 LIBBASE
->psd
.hiddAB
= OOP_ObtainAttrBase(IID_Hidd
);
355 if (LIBBASE
->psd
.hiddPCIDriverAB
== 0 || LIBBASE
->psd
.hiddAB
== 0)
357 D(bug("PCIMediator: ObtainAttrBases failed\n"));
361 msg
.driverClass
= LIBBASE
->psd
.driverClass
;
362 msg
.mID
= OOP_GetMethodID(IID_Hidd_PCI
, moHidd_PCI_AddHardwareDriver
);
363 D(bug("PCIMediator: Adding Driver to main the class OK\n"));
365 pci
= OOP_NewObject(NULL
, CLID_Hidd_PCI
, NULL
);
366 OOP_DoMethod(pci
, (OOP_Msg
)pmsg
);
367 OOP_DisposeObject(pci
);
369 D(bug("PCIMediator: All OK\n"));
374 static int PCIMediator_ExpungeClass(LIBBASETYPEPTR LIBBASE
)
376 D(bug("PCIMediator: Class destruction\n"));
378 OOP_ReleaseAttrBase(IID_Hidd_PCIDriver
);
379 OOP_ReleaseAttrBase(IID_Hidd
);
384 ADD2INITLIB(PCIMediator_InitClass
, 0)
385 ADD2EXPUNGELIB(PCIMediator_ExpungeClass
, 0)