revert between 56095 -> 55830 in arch
[AROS.git] / arch / ppc-sam440 / ata / bus_ppc460.c
blobe07ba8bbfe50da7bdd2e66bb80c709b9e88bc7cb
1 /*
2 Copyright © 2004-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: PCI bus driver for ata.device
6 Lang: English
7 */
9 #define DEBUG 1
11 #include <aros/asmcall.h>
12 #include <aros/debug.h>
13 #include <aros/symbolsets.h>
14 #include <asm/io.h>
15 #include <asm/amcc440.h>
16 #include <exec/lists.h>
17 #include <oop/oop.h>
18 #include <resources/processor.h>
19 #include <proto/exec.h>
20 #include <proto/oop.h>
21 #include <proto/processor.h>
23 #include <string.h>
25 #include "ata.h"
27 typedef struct
29 struct ataBase *ATABase;
30 ULONG ata__buscount;
31 OOP_AttrBase HiddPCIDeviceAttrBase;
32 OOP_MethodID HiddPCIDriverMethodBase;
33 } EnumeratorArgs;
35 static VOID ata460_out(UBYTE val, UWORD offset, IPTR port, APTR data)
37 offset <<= 2;
38 outb(val, (uint8_t *)(port + offset + data));
41 static UBYTE ata460_in(UWORD offset, IPTR port, APTR data)
43 offset <<= 2;
44 return inb((uint8_t *)(port + offset + data));
47 static VOID ata460_outl(ULONG val, UWORD offset, IPTR port, APTR data)
49 offset <<= 2;
50 outl(val, (uint32_t *)(port + offset + data));
53 static VOID ata460_insw(APTR address, UWORD port, ULONG count, APTR data)
55 UWORD *addr = address;
56 UWORD *p = (UWORD*)(port + data);
58 while(count)
60 *addr++ = inw(p);
61 count -= 2;
65 static VOID ata460_insl(APTR address, UWORD port, ULONG count, APTR data)
67 ata460_insw(address, port, count, data);
70 static VOID ata460_outsw(APTR address, UWORD port, ULONG count, APTR data)
72 UWORD *addr = address;
73 UWORD *p = (UWORD*)(port + data);
75 while(count)
77 outw(*addr++, p);
78 count -= 2;
82 static VOID ata460_outsl(APTR address, UWORD port, ULONG count, APTR data)
84 ata460_outsw(address, port, count, data);
87 static AROS_INTH1(ata460_Interrupt, struct ata_Bus *, bus)
89 AROS_INTFUNC_INIT
91 * Our interrupt handler should call this function.
93 ata_HandleIRQ(bus);
95 return FALSE;
97 AROS_INTFUNC_EXIT
100 /* Actually a quick hack. Proper implementation really needs HIDDizing this code. */
101 static BOOL ata460_CreateInterrupt(struct ata_Bus *bus)
103 bus->ab_IntHandler.is_Node.ln_Type = NT_INTERRUPT;
104 bus->ab_IntHandler.is_Node.ln_Name = "Sam460ex SATA/IDE";
105 bus->ab_IntHandler.is_Node.ln_Pri = 0;
106 bus->ab_IntHandler.is_Code = (VOID_FUNC)ata460_Interrupt;
107 bus->ab_IntHandler.is_Data = bus;
109 AddIntServer(INTB_KERNEL + bus->ab_IRQ, &bus->ab_IntHandler);
111 return TRUE;
114 static const struct ata_BusDriver ppc460_driver =
116 ata460_out,
117 ata460_in,
118 ata460_outl,
119 ata460_insw,
120 ata460_outsw,
121 ata460_insl,
122 ata460_outsl,
123 ata460_CreateInterrupt
126 static inline ULONG GetPVR(void)
128 struct Library *ProcessorBase = OpenResource(PROCESSORNAME);
129 ULONG pvr = 0;
131 if (ProcessorBase) {
132 struct TagItem tags[] = {
133 { GCIT_Model, (IPTR)&pvr },
134 { TAG_END }
136 GetCPUInfo(tags);
139 return pvr;
142 #define SDR0_PE0_PHY_CTL_RST 0x30f
145 /* Requires supervisor */
146 ULONG getSDR0_PE0_PHY_CTL_RST(VOID)
148 wrdcr(SDR0_CFGADDR, SDR0_PE0_PHY_CTL_RST);
149 return rddcr(SDR0_CFGDATA);
152 static int ata460_Scan(struct ataBase *base)
154 if (GetPVR() == PVR_PPC460EX_B) {
155 /* ppc460 */
156 ULONG pe0_mode = Supervisor(getSDR0_PE0_PHY_CTL_RST) & 0x3;
158 D(bug("[ATA] Sam460EX PE0 mode = 0x%08x\n", pe0_mode));
159 if (pe0_mode == 1) {
160 ULONG scr0 = inl_le(SATA0_SCR0);
161 if ((scr0 & 0xf) == 0x3) {
162 D(bug("[ATA] Enabling Sam460EX SATA in ATA PIO mode\n"));
163 ata_RegisterBus(0, 0x18, INTR_UIC3_SATA, 0,
164 ARBF_EarlyInterrupt | ARBF_80Wire, &ppc460_driver,
165 (APTR)SATA0_CDR0, base);
170 return TRUE;
174 * ata.device main code has two init routines with 0 and 127 priorities.
175 * All bus scanners must run between them.
177 ADD2INITLIB(ata460_Scan, 40)