disabling fastata check for now, as it fails on an a4000 and prevents it to find...
[AROS.git] / arch / m68k-amiga / hidd / gayle_ata / probe.c
blob94bbc78ce9a095bf1a49f507e7b86bb1a3c4479f
1 /*
2 Copyright © 2013-2017, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: A600/A1200/A4000 ATA HIDD hardware detection routine
6 Lang: English
7 */
9 #define DEBUG 1
10 #include <aros/debug.h>
12 #define __OOP_NOMETHODBASES__
14 #include <aros/asmcall.h>
15 #include <aros/symbolsets.h>
16 #include <asm/io.h>
17 #include <exec/lists.h>
18 #include <exec/rawfmt.h>
19 #include <hidd/ata.h>
20 #include <hidd/hidd.h>
21 #include <oop/oop.h>
22 #include <proto/exec.h>
23 #include <proto/oop.h>
25 #include <hardware/custom.h>
26 #include <graphics/gfxbase.h>
27 #include <hardware/ata.h>
29 #include <string.h>
31 #include "bus_class.h"
32 #include "interface_pio.h"
34 static BOOL custom_check(APTR addr)
36 volatile struct Custom *custom = (struct Custom*)0xdff000;
37 volatile struct Custom *maybe_custom = (struct Custom*)addr;
38 UWORD intena;
39 BOOL iscustom = TRUE;
41 intena = custom->intenar;
42 custom->intena = 0x7fff;
43 custom->intena = 0xc000;
44 maybe_custom->intena = 0x7fff;
45 if (custom->intenar == 0x4000) {
46 maybe_custom->intena = 0x7fff;
47 if (custom->intenar == 0x4000)
48 iscustom = FALSE;
50 custom->intena = 0x7fff;
51 custom->intena = intena | 0x8000;
52 return iscustom;
55 static BOOL isFastATA(struct ata_ProbedBus *ddata)
57 return FALSE;
60 static UBYTE *getport(struct ata_ProbedBus *ddata)
62 volatile struct Custom *custom = (struct Custom*)0xdff000;
63 UBYTE id, status1, status2;
64 volatile UBYTE *port, *altport;
65 struct GfxBase *gfx;
67 port = NULL;
68 gfx = (struct GfxBase*)TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS);
69 Disable();
70 id = ReadGayle();
71 if (id) {
72 port = (UBYTE*)GAYLE_BASE_1200;
73 ddata->gayleirqbase = (UBYTE*)GAYLE_IRQ_1200;
74 } else {
75 // AGA does not have custom mirror here but lets make sure..
76 if (!custom_check((APTR)0xdd4000) && (custom->vposr & 0x7f00) >= 0x2200) {
77 port = (UBYTE*)GAYLE_BASE_4000;
78 ddata->a4000 = TRUE;
79 ddata->gayleirqbase = (UBYTE*)GAYLE_IRQ_4000;
82 Enable();
83 CloseLibrary((struct Library*)gfx);
85 // Detect FastATA...
86 if (ddata->gayleirqbase)
88 altport = (UBYTE*)GAYLE_BASE_FASTATA;
89 Disable();
90 status1 = altport[GAYLE_BASE_FASTATA_PIO0 + GAYLE_FASTATA_PIO_STAT];
91 status2 = altport[GAYLE_BASE_FASTATA_PIO3 + GAYLE_FASTATA_STAT];
92 Enable();
93 D(bug("[ATA:Gayle] Status=%02x,%02x\n", status1, status2);)
94 if ((status1 & 0xfd) == (status2 & 0xfd))
96 //FIXME: the check is flawed for an a4000, disabled for now.
97 // port = (UBYTE*)altport;
98 // ddata->gayleirqbase = (UBYTE*)GAYLE_IRQ_FASTATA;
102 if (port == NULL)
104 D(bug("[ATA:Gayle] No Gayle ATA Detected (ID=%02x)\n", id);)
105 return NULL;
108 ddata->port = (UBYTE*)port;
109 if ((ddata->port == (UBYTE*)GAYLE_BASE_1200) || (ddata->port == (UBYTE*)GAYLE_BASE_4000))
111 D(bug("[ATA:Gayle] Possible Gayle IDE port @ %08x (ID=%02x)\n", (ULONG)port & ~3, id);)
112 altport = port + 0x1010;
114 else
116 D(bug("[ATA:Gayle] Possible FastATA IDE port @ %08x (ID=%02x)\n", (ULONG)port & ~3, id);)
117 altport = NULL;
119 ddata->altport = (UBYTE*)altport;
121 Disable();
122 port[ata_DevHead * 4] = ATAF_ERROR;
123 /* If nothing connected, we get back what we wrote, ATAF_ERROR set */
124 status1 = port[ata_Status * 4];
125 port[ata_DevHead * 4] = ATAF_DATAREQ;
126 status2 = port[ata_Status * 4];
127 port[ata_DevHead * 4] = 0;
128 Enable();
130 D(bug("[ATA:Gayle] Status=%02x,%02x\n", status1, status2);)
131 // BUSY and DRDY both active or ERROR/DATAREQ = no drive(s) = do not install driver
132 if ( (((status1 | status2) & (ATAF_BUSY | ATAF_DRDY)) == (ATAF_BUSY | ATAF_DRDY))
133 || ((status1 | status2) & (ATAF_ERROR | ATAF_DATAREQ)))
135 D(bug("[ATA:Gayle] No Devices detected\n");)
136 return NULL;
138 if (ddata->doubler) {
139 UBYTE v1, v2;
140 /* check if AltControl is both readable and writable
141 * It is either floating or DevHead if IDE doubler is connected.
142 * AltControl = DevHead (R)
143 * Device Control = DevHead (W)
145 Disable();
146 altport[ata_AltControl * 4] = 0;
147 port[ata_DevHead * 4] = 1;
148 v1 = altport[ata_AltControl * 4];
149 altport[ata_AltControl * 4] = 2;
150 port[ata_DevHead * 4] = 4;
151 v2 = altport[ata_AltControl * 4];
152 altport[ata_AltControl * 4] = 0;
153 port[ata_DevHead * 4] = 0;
154 Enable();
155 if ((v1 == 0 && v2 == 2) || (v1 == 1 && v2 == 4) || (v1 == 0xff && v2 == 0xff)) {
156 ddata->doubler = 2;
157 } else {
158 ddata->doubler = 0;
160 D(bug("[ATA:Gayle] IDE doubler check (%02X, %02X) = %d\n", v1, v2, ddata->doubler);)
161 ddata->altport = NULL;
163 /* we may have connected drives */
164 return (UBYTE*)port;
167 static int ata_Scan(struct ataBase *base)
169 struct ata_ProbedBus *probedbus;
170 OOP_Class *busClass = base->GayleBusClass;
172 probedbus = AllocVec(sizeof(struct ata_ProbedBus), MEMF_ANY | MEMF_CLEAR);
173 if (probedbus && getport(probedbus)) {
174 OOP_Object *ata = OOP_NewObject(NULL, CLID_HW_ATA, NULL);
175 if (ata) {
176 HWBase = OOP_GetMethodID(IID_HW, 0);
177 struct TagItem attrs[] =
179 {aHidd_DriverData , (IPTR)probedbus },
180 {aHidd_ATABus_PIODataSize , sizeof(struct pio_data) },
181 {aHidd_ATABus_BusVectors , (IPTR)bus_FuncTable },
182 {aHidd_ATABus_PIOVectors , (IPTR)pio_FuncTable },
183 {aHidd_ATABus_KeepEmpty , FALSE },
184 {TAG_DONE , 0 }
186 OOP_Object *bus;
189 * We use this field as ownership indicator.
190 * The trick is that HW_AddDriver() fails if either object creation fails
191 * or subsystem-side setup fails. In the latter case our object will be
192 * disposed.
193 * We need to know whether OOP_DisposeObject() or we should deallocate
194 * this structure on failure.
196 probedbus->atapb_Node.ln_Succ = NULL;
199 * Check if we have a FastATA adaptor
201 if (isFastATA(probedbus))
202 busClass = base->FastATABusClass;
204 bus = HW_AddDriver(ata, busClass, attrs);
205 if (bus)
206 return TRUE;
207 D(bug("[ATA:Gayle] Failed to create object for device IO: %x:%x IRQ: %x\n",
208 probedbus->port, probedbus->altport, probedbus->gayleirqbase);)
211 * Free the structure only upon object creation failure!
212 * In case of success it becomes owned by the driver object!
214 if (!probedbus->atapb_Node.ln_Succ)
215 FreeVec(probedbus);
216 return TRUE;
219 FreeVec(probedbus);
221 return TRUE;
224 ADD2INITLIB(ata_Scan, 30)