3 #include <aros/debug.h>
4 #include <exec/types.h>
6 #include <asm/mpc5200b.h>
8 #include <exec/tasks.h>
9 #include <exec/memory.h>
10 #include <exec/nodes.h>
11 #include <utility/utility.h>
12 #include <proto/exec.h>
13 #include <proto/timer.h>
14 #include <proto/oop.h>
15 #include <proto/openfirmware.h>
20 extern bestcomm_t
*bestcomm
;
21 extern uint32_t bestcomm_taskid
;
23 extern void bestcomm_init();
26 uint32_t bus_frequency
;
28 volatile ata_5k2_t
*ata_5k2
;
30 static void ata_out(UBYTE val
, UWORD offset
, IPTR port
, APTR data
)
32 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
34 if (port
+offset
* 4 == 0x3a7c)
36 ULONG val
= inl(&mbar
[port
+ offset
* 4]);
37 outb(0, &mbar
[port
+ 1 + offset
* 4]);
40 outl((ULONG
)val
<< 24, &mbar
[port
+ offset
* 4]);
43 static UBYTE
ata_in(UWORD offset
, IPTR port
, APTR data
)
45 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
47 if (port
+offset
* 4 == 0x3a7c)
49 ULONG val
= inl(&mbar
[port
+ offset
* 4]);
50 outb(0, &mbar
[port
+ 1 + offset
* 4]);
53 return inl(&mbar
[port
+ offset
* 4]) >> 24;
56 static void ata_outl(ULONG val
, UWORD offset
, IPTR port
, APTR data
)
58 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
60 outl_le(val
, &mbar
[port
+ offset
* 4]);
63 static VOID
ata_insw(APTR address
, UWORD port
, ULONG count
, APTR data
)
65 UWORD
*addr
= address
;
66 volatile UWORD
*p
= (UWORD
*)(&mbar
[port
]);
68 D(bug("[ATA 5k2] insw(%08x, %04x)\n", address
, count
));
72 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
84 static VOID
ata_outsw(APTR address
, UWORD port
, ULONG count
, APTR data
)
86 UWORD
*addr
= address
;
87 volatile UWORD
*p
= (UWORD
*)(&mbar
[port
]);
89 D(bug("[ATA 5k2] outsw(%08x, %04x)\n", address
, count
));
93 while(inl(&ata_5k2
->ata_status
) & 0x80000000) asm volatile("nop");
102 asm volatile("sync");
105 static void ata_400ns()
107 register ULONG tick_old
, tick
;
109 asm volatile("mftbl %0":"=r"(tick_old
));
112 asm volatile("mftbl %0":"=r"(tick
));
113 } while(tick
< (tick_old
+ 15));
116 static AROS_INTH1(ata_Interrupt
, void *, data
)
120 * Our interrupt handler should call this function.
121 * It's our problem how to store bus pointer. Here we use h_Data for it.
130 /* Actually a quick hack. Proper implementation really needs HIDDizing this code. */
131 static BOOL
CreateInterrupt(struct ata_Bus
*bus
)
133 struct Interrupt
*IntHandler
= &bus
->ab_IntHandler
;
136 Prepare nice interrupt for our bus. Even if interrupt sharing is enabled,
137 it should work quite well
139 IntHandler
->is_Node
.ln_Pri
= 10;
140 IntHandler
->is_Node
.ln_Name
= bus
->ab_Task
->tc_Node
.ln_Name
;
141 IntHandler
->is_Code
= (VOID_FUNC
)ata_Interrupt
;
142 IntHandler
->is_Data
= bus
;
144 AddIntServer(INTB_KERNEL
+ bus
->ab_IRQ
, IntHandler
);
149 static const struct ata_BusDriver mpc_driver
=
156 ata_insw
, /* These are intentionally the same as 16-bit routines */
161 static int ata_mpc_init(struct ataBase
*LIBBASE
)
165 * I've decided to use memory pools again. Alloc everything needed from
166 * a pool, so that we avoid memory fragmentation.
168 LIBBASE
->ata_MemPool
= CreatePool(MEMF_CLEAR
| MEMF_PUBLIC
| MEMF_SEM_PROTECTED
, 8192, 4096);
169 if (LIBBASE
->ata_MemPool
== NULL
)
172 void *OpenFirmwareBase
= OpenResource("openfirmware.resource");
173 void *key
= OF_OpenKey("/builtin");
176 void *prop
= OF_FindProperty(key
, "reg");
179 intptr_t *m_
= OF_GetPropValue(prop
);
181 ata_5k2
= (ata_5k2_t
*)(*m_
+ 0x3a00);
183 D(bug("[ATA] MBAR located at %08x\n", mbar
));
186 /* Get the bus frequency for Efika */
187 prop
= OF_FindProperty(key
, "bus-frequency");
190 bus_frequency
= *(uint32_t *)OF_GetPropValue(prop
);
191 D(bug("[ATA] bus frequency: %d\n", bus_frequency
));
195 key
= OF_OpenKey("/builtin/ata");
198 void *prop
= OF_FindProperty(key
, "reg");
201 ata_5k2
= *(ata_5k2_t
**)OF_GetPropValue(prop
);
203 D(bug("[ATA] ATA registers at %08x\n", ata_5k2
));
207 key
= OF_OpenKey("/builtin/ata/bestcomm-task");
210 void *prop
= OF_FindProperty(key
, "taskid");
213 bestcomm_taskid
= *(uint32_t *)OF_GetPropValue(prop
);
215 D(bug("[ATA] ATA uses bestcomm task %d\n", bestcomm_taskid
));
219 key
= OF_OpenKey("/builtin/sram");
222 void *prop
= OF_FindProperty(key
, "reg");
225 sram
= *(void **)OF_GetPropValue(prop
);
227 D(bug("[ATA] SRAM at %08x\n", sram
));
230 key
= OF_OpenKey("/builtin/bestcomm");
233 void *prop
= OF_FindProperty(key
, "reg");
236 bestcomm
= *(void **)OF_GetPropValue(prop
);
238 D(bug("[ATA] bestcomm at %08x\n", bestcomm
));
241 D(bug("[ATA] ata_config=%08x\n", inl(&ata_5k2
->ata_config
)));
242 D(bug("[ATA] ata_status=%08x\n", inl(&ata_5k2
->ata_status
)));
243 D(bug("[ATA] ata_pio1=%08x\n", inl(&ata_5k2
->ata_pio1
)));
244 D(bug("[ATA] ata_pio2=%08x\n", inl(&ata_5k2
->ata_pio2
)));
246 /* Disable XLB pipelining... */
247 D(bug("[ATA] xlb_config=%08x\n", inl(mbar
+0x1f40)));
248 outl(inl(mbar
+ 0x1f40) | 0x80000000, mbar
+ 0x1f40);
250 outl(0, &ata_5k2
->ata_invalid
);
251 outl(0xc3000000, &ata_5k2
->ata_config
);
253 for (i
=0; i
< 100 / 4; i
++)
256 /* Hacky timing pokes */
257 outl(0x03000000, &ata_5k2
->ata_config
);
258 outl(132 << 16, &ata_5k2
->ata_invalid
);
260 /* PIO2 timing table. Replace it by correct calculations soon !!! */
262 #warning TODO: Set the timings in right way!
264 outl(0x21270e00, &ata_5k2
->ata_pio1
);
265 outl(0x03050600, &ata_5k2
->ata_pio2
);
270 * FIXME: This code uses static data variables.
271 * Move them into DriverData instead.
273 ata_RegisterBus(0x3a60, 0x3a5c - 8, MPC5200B_ATA
, 0, FALSE
, &mpc_driver
, NULL
, LIBBASE
);
278 ADD2INITLIB(ata_mpc_init
, 20)