2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
8 #include <aros/debug.h>
9 #include <exec/types.h>
11 #include <asm/mpc5200b.h>
12 #include <exec/exec.h>
13 #include <exec/tasks.h>
14 #include <exec/memory.h>
15 #include <exec/nodes.h>
16 #include <utility/utility.h>
17 #include <proto/exec.h>
18 #include <proto/timer.h>
19 #include <proto/oop.h>
20 #include <proto/openfirmware.h>
25 extern bestcomm_t
*bestcomm
;
26 extern uint32_t bestcomm_taskid
;
28 extern void bestcomm_init();
31 uint32_t bus_frequency
;
33 volatile ata_5k2_t
*ata_5k2
;
35 static void ata_out(UBYTE val
, UWORD offset
, IPTR port
, APTR data
)
37 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
39 if (port
+offset
* 4 == 0x3a7c)
41 ULONG val
= inl(&mbar
[port
+ offset
* 4]);
42 outb(0, &mbar
[port
+ 1 + offset
* 4]);
45 outl((ULONG
)val
<< 24, &mbar
[port
+ offset
* 4]);
48 static UBYTE
ata_in(UWORD offset
, IPTR port
, APTR data
)
50 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
52 if (port
+offset
* 4 == 0x3a7c)
54 ULONG val
= inl(&mbar
[port
+ offset
* 4]);
55 outb(0, &mbar
[port
+ 1 + offset
* 4]);
58 return inl(&mbar
[port
+ offset
* 4]) >> 24;
61 static void ata_outl(ULONG val
, UWORD offset
, IPTR port
, APTR data
)
63 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
65 outl_le(val
, &mbar
[port
+ offset
* 4]);
68 static VOID
ata_insw(APTR address
, UWORD port
, ULONG count
, APTR data
)
70 UWORD
*addr
= address
;
71 volatile UWORD
*p
= (UWORD
*)(&mbar
[port
]);
73 D(bug("[ATA 5k2] insw(%08x, %04x)\n", address
, count
));
77 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
89 static VOID
ata_outsw(APTR address
, UWORD port
, ULONG count
, APTR data
)
91 UWORD
*addr
= address
;
92 volatile UWORD
*p
= (UWORD
*)(&mbar
[port
]);
94 D(bug("[ATA 5k2] outsw(%08x, %04x)\n", address
, count
));
98 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
100 asm volatile("sync");
107 asm volatile("sync");
110 static void ata_400ns()
112 register ULONG tick_old
, tick
;
114 asm volatile("mftbl %0":"=r"(tick_old
));
117 asm volatile("mftbl %0":"=r"(tick
));
118 } while(tick
< (tick_old
+ 15));
121 static AROS_INTH1(ata_Interrupt
, void *, data
)
125 * Our interrupt handler should call this function.
126 * It's our problem how to store bus pointer. Here we use h_Data for it.
135 /* Actually a quick hack. Proper implementation really needs HIDDizing this code. */
136 static BOOL
CreateInterrupt(struct ata_Bus
*bus
)
138 struct Interrupt
*IntHandler
= &bus
->ab_IntHandler
;
141 Prepare nice interrupt for our bus. Even if interrupt sharing is enabled,
142 it should work quite well
144 IntHandler
->is_Node
.ln_Pri
= 10;
145 IntHandler
->is_Node
.ln_Name
= bus
->ab_Task
->tc_Node
.ln_Name
;
146 IntHandler
->is_Code
= (VOID_FUNC
)ata_Interrupt
;
147 IntHandler
->is_Data
= bus
;
149 AddIntServer(INTB_KERNEL
+ bus
->ab_IRQ
, IntHandler
);
154 static const struct ata_BusDriver mpc_driver
=
161 ata_insw
, /* These are intentionally the same as 16-bit routines */
166 static int ata_mpc_init(struct ataBase
*LIBBASE
)
170 * I've decided to use memory pools again. Alloc everything needed from
171 * a pool, so that we avoid memory fragmentation.
173 LIBBASE
->ata_MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
174 if (LIBBASE
->ata_MemPool
== NULL
)
177 void *OpenFirmwareBase
= OpenResource("openfirmware.resource");
178 void *key
= OF_OpenKey("/builtin");
181 void *prop
= OF_FindProperty(key
, "reg");
184 intptr_t *m_
= OF_GetPropValue(prop
);
186 ata_5k2
= (ata_5k2_t
*)(*m_
+ 0x3a00);
188 D(bug("[ATA] MBAR located at %08x\n", mbar
));
191 /* Get the bus frequency for Efika */
192 prop
= OF_FindProperty(key
, "bus-frequency");
195 bus_frequency
= *(uint32_t *)OF_GetPropValue(prop
);
196 D(bug("[ATA] bus frequency: %d\n", bus_frequency
));
200 key
= OF_OpenKey("/builtin/ata");
203 void *prop
= OF_FindProperty(key
, "reg");
206 ata_5k2
= *(ata_5k2_t
**)OF_GetPropValue(prop
);
208 D(bug("[ATA] ATA registers at %08x\n", ata_5k2
));
212 key
= OF_OpenKey("/builtin/ata/bestcomm-task");
215 void *prop
= OF_FindProperty(key
, "taskid");
218 bestcomm_taskid
= *(uint32_t *)OF_GetPropValue(prop
);
220 D(bug("[ATA] ATA uses bestcomm task %d\n", bestcomm_taskid
));
224 key
= OF_OpenKey("/builtin/sram");
227 void *prop
= OF_FindProperty(key
, "reg");
230 sram
= *(void **)OF_GetPropValue(prop
);
232 D(bug("[ATA] SRAM at %08x\n", sram
));
235 key
= OF_OpenKey("/builtin/bestcomm");
238 void *prop
= OF_FindProperty(key
, "reg");
241 bestcomm
= *(void **)OF_GetPropValue(prop
);
243 D(bug("[ATA] bestcomm at %08x\n", bestcomm
));
246 D(bug("[ATA] ata_config=%08x\n", inl(&ata_5k2
->ata_config
)));
247 D(bug("[ATA] ata_status=%08x\n", inl(&ata_5k2
->ata_status
)));
248 D(bug("[ATA] ata_pio1=%08x\n", inl(&ata_5k2
->ata_pio1
)));
249 D(bug("[ATA] ata_pio2=%08x\n", inl(&ata_5k2
->ata_pio2
)));
251 /* Disable XLB pipelining... */
252 D(bug("[ATA] xlb_config=%08x\n", inl(mbar
+0x1f40)));
253 outl(inl(mbar
+ 0x1f40) | 0x80000000, mbar
+ 0x1f40);
255 outl(0, &ata_5k2
->ata_invalid
);
256 outl(0xc3000000, &ata_5k2
->ata_config
);
258 for (i
=0; i
< 100 / 4; i
++)
261 /* Hacky timing pokes */
262 outl(0x03000000, &ata_5k2
->ata_config
);
263 outl(132 << 16, &ata_5k2
->ata_invalid
);
265 /* PIO2 timing table. Replace it by correct calculations soon !!! */
267 #warning TODO: Set the timings in right way!
269 outl(0x21270e00, &ata_5k2
->ata_pio1
);
270 outl(0x03050600, &ata_5k2
->ata_pio2
);
275 * FIXME: This code uses static data variables.
276 * Move them into DriverData instead.
278 ata_RegisterBus(0x3a60, 0x3a5c - 8, MPC5200B_ATA
, 0, FALSE
, &mpc_driver
, NULL
, LIBBASE
);
283 ADD2INITLIB(ata_mpc_init
, 20)