add place-holder directory for the a3000 wd533c93 scsi controller implementation.
[AROS.git] / arch / m68k-amiga / hidd / gayle_ata / probe.c
blobbd581e82f20eebd03ce7ded72bc5a47b7e211069
1 /*
2 Copyright © 2013-2019, 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>
11 #include <proto/exec.h>
13 #include <aros/asmcall.h>
14 #include <aros/symbolsets.h>
15 #include <asm/io.h>
16 #include <exec/lists.h>
17 #include <exec/rawfmt.h>
18 #include <hidd/hidd.h>
19 #include <hidd/storage.h>
20 #include <hidd/ata.h>
21 #include <oop/oop.h>
22 #include <proto/oop.h>
24 #include <hardware/custom.h>
25 #include <graphics/gfxbase.h>
26 #include <hardware/ata.h>
28 #include <string.h>
30 #include "bus_class.h"
31 #include "interface_pio.h"
33 //#define ENABLE_ATAPOWERFLYER
35 static BOOL custom_check(APTR addr)
37 volatile struct Custom *custom = (struct Custom*)0xdff000;
38 volatile struct Custom *maybe_custom = (struct Custom*)addr;
39 UWORD intena;
40 BOOL iscustom = TRUE;
42 intena = custom->intenar;
43 custom->intena = 0x7fff;
44 custom->intena = 0xc000;
45 maybe_custom->intena = 0x7fff;
46 if (custom->intenar == 0x4000) {
47 maybe_custom->intena = 0x7fff;
48 if (custom->intenar == 0x4000)
49 iscustom = FALSE;
51 custom->intena = 0x7fff;
52 custom->intena = intena | 0x8000;
53 return iscustom;
56 static BOOL isFastATA(struct ata_ProbedBus *ddata)
58 #if defined(ENABLE_ATAPOWERFLYER)
59 if (ddata->gayleirqbase == (UBYTE*)GAYLE_IRQ_FASTATA)
60 return TRUE;
61 #endif
62 return FALSE;
65 static UBYTE *getport(struct ata_ProbedBus *ddata)
67 volatile struct Custom *custom = (struct Custom*)0xdff000;
68 UBYTE id, status1, status2;
69 volatile UBYTE *port, *altport;
70 struct GfxBase *gfx;
72 port = NULL;
73 gfx = (struct GfxBase*)TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS);
74 Disable();
75 id = ReadGayle();
76 if (id) {
77 port = (UBYTE*)GAYLE_BASE_1200;
78 ddata->gayleirqbase = (UBYTE*)GAYLE_IRQ_1200;
79 } else {
80 // AGA does not have custom mirror here but lets make sure..
81 if (!custom_check((APTR)0xdd4000) && (custom->vposr & 0x7f00) >= 0x2200) {
82 port = (UBYTE*)GAYLE_BASE_4000;
83 ddata->a4000 = TRUE;
84 ddata->gayleirqbase = (UBYTE*)GAYLE_IRQ_4000;
87 Enable();
88 CloseLibrary((struct Library*)gfx);
90 D(bug("[ATA:Gayle] GayleID : %02x\n", id);)
92 #if defined(ENABLE_ATAPOWERFLYER)
93 // Detect FastATA... FIXME: the check is flawed for an a4000, disabled for now.
94 if (ddata->gayleirqbase)
96 altport = (UBYTE*)GAYLE_BASE_FASTATA;
97 Disable();
98 status1 = altport[GAYLE_BASE_FASTATA_PIO0 + GAYLE_FASTATA_PIO_STAT];
99 status2 = altport[GAYLE_BASE_FASTATA_PIO3 + GAYLE_FASTATA_STAT];
100 Enable();
101 D(bug("[ATA:Gayle] (FastATA) Status=%02x,%02x\n", status1, status2);)
102 if (((status1 != 0x00) && (status1 != 0xFF)) &&
103 ((status1 & 0xfd) == (status2 & 0xfd)))
105 port = (UBYTE*)altport;
106 ddata->gayleirqbase = (UBYTE*)GAYLE_IRQ_FASTATA;
109 #endif
110 if (port == NULL)
112 D(bug("[ATA:Gayle] No Gayle ATA Detected\n");)
113 return NULL;
116 ddata->port = (UBYTE*)port;
117 if ((ddata->port == (UBYTE*)GAYLE_BASE_1200) || (ddata->port == (UBYTE*)GAYLE_BASE_4000))
119 D(bug("[ATA:Gayle] Possible Gayle IDE port @ %08x\n", (ULONG)port & ~3);)
120 altport = port + 0x1010;
122 else
124 D(bug("[ATA:Gayle] Possible FastATA IDE port @ %08x\n", (ULONG)port & ~3);)
125 altport = NULL;
127 ddata->altport = (UBYTE*)altport;
129 Disable();
130 port[ata_DevHead * 4] = ATAF_ERROR;
131 /* If nothing connected, we get back what we wrote, ATAF_ERROR set */
132 status1 = port[ata_Status * 4];
133 port[ata_DevHead * 4] = ATAF_DATAREQ;
134 status2 = port[ata_Status * 4];
135 port[ata_DevHead * 4] = 0;
136 Enable();
138 D(bug("[ATA:Gayle] Status=%02x,%02x\n", status1, status2);)
139 // BUSY and DRDY both active or ERROR/DATAREQ = no drive(s) = do not install driver
140 if ( (((status1 | status2) & (ATAF_BUSY | ATAF_DRDY)) == (ATAF_BUSY | ATAF_DRDY))
141 || ((status1 | status2) & (ATAF_ERROR | ATAF_DATAREQ)))
143 D(bug("[ATA:Gayle] No Devices detected\n");)
144 return NULL;
146 if (ddata->doubler) {
147 UBYTE v1, v2;
148 /* check if AltControl is both readable and writable
149 * It is either floating or DevHead if IDE doubler is connected.
150 * AltControl = DevHead (R)
151 * Device Control = DevHead (W)
153 Disable();
154 altport[ata_AltControl * 4] = 0;
155 port[ata_DevHead * 4] = 1;
156 v1 = altport[ata_AltControl * 4];
157 altport[ata_AltControl * 4] = 2;
158 port[ata_DevHead * 4] = 4;
159 v2 = altport[ata_AltControl * 4];
160 altport[ata_AltControl * 4] = 0;
161 port[ata_DevHead * 4] = 0;
162 Enable();
163 if ((v1 == 0 && v2 == 2) || (v1 == 1 && v2 == 4) || (v1 == 0xff && v2 == 0xff)) {
164 ddata->doubler = 2;
165 } else {
166 ddata->doubler = 0;
168 D(bug("[ATA:Gayle] IDE doubler check (%02X, %02X) = %d\n", v1, v2, ddata->doubler);)
169 ddata->altport = NULL;
171 /* we may have connected drives */
172 return (UBYTE*)port;
175 static int gayle_bus_Scan(struct ataBase *base)
177 struct ata_ProbedBus *probedbus;
178 OOP_Class *busClass = base->GayleBusClass;
179 struct TagItem ata_tags[] =
181 {aHidd_Name , (IPTR)"ata_gayle.hidd" },
182 {aHidd_HardwareName , 0 },
183 #define ATA_TAG_HARDWARENAME 1
184 {TAG_DONE , 0 }
187 probedbus = AllocVec(sizeof(struct ata_ProbedBus), MEMF_ANY | MEMF_CLEAR);
188 if (probedbus && getport(probedbus)) {
189 OOP_Object *ata;
190 if (isFastATA(probedbus))
192 ata_tags[ATA_TAG_HARDWARENAME].ti_Data = (IPTR)"PowerFlyer FastATA IDE Controller";
194 else
196 if (probedbus->doubler == 0)
197 ata_tags[ATA_TAG_HARDWARENAME].ti_Data = (IPTR)"Amiga(tm) Gayle IDE Controller";
198 else
199 ata_tags[ATA_TAG_HARDWARENAME].ti_Data = (IPTR)"Amiga(tm) Gayle IDE Controller + Port Doubler";
201 ata = HW_AddDriver(base->storageRoot, base->ataClass, ata_tags);
202 if (ata) {
203 struct TagItem attrs[] =
205 {aHidd_Name , (IPTR)"ata_gayle.hidd" },
206 {aHidd_HardwareName , 0 },
207 #define BUS_TAG_HARDWARENAME 1
208 {aHidd_DriverData , (IPTR)probedbus },
209 {aHidd_ATABus_PIODataSize , sizeof(struct pio_data) },
210 {aHidd_ATABus_BusVectors , (IPTR)bus_FuncTable },
211 {aHidd_ATABus_PIOVectors , (IPTR)pio_FuncTable },
212 {aHidd_Bus_KeepEmpty , FALSE },
213 {TAG_DONE , 0 }
215 OOP_Object *bus;
218 * We use this field as ownership indicator.
219 * The trick is that HW_AddDriver() fails if either object creation fails
220 * or subsystem-side setup fails. In the latter case our object will be
221 * disposed.
222 * We need to know whether OOP_DisposeObject() or we should deallocate
223 * this structure on failure.
225 probedbus->atapb_Node.ln_Succ = NULL;
228 * Check if we have a FastATA adaptor
230 if (isFastATA(probedbus))
232 busClass = base->FastATABusClass;
233 attrs[BUS_TAG_HARDWARENAME].ti_Data = (IPTR)"FastATA IDE Channel";
235 else
237 attrs[BUS_TAG_HARDWARENAME].ti_Data = (IPTR)"Gayle IDE Channel";
240 bus = HIDD_StorageController_AddBus(ata, busClass, attrs);
241 if (bus)
242 return TRUE;
243 D(bug("[ATA:Gayle] Failed to create object for device IO: %x:%x IRQ: %x\n",
244 probedbus->port, probedbus->altport, probedbus->gayleirqbase);)
247 * Free the structure only upon object creation failure!
248 * In case of success it becomes owned by the driver object!
250 if (!probedbus->atapb_Node.ln_Succ)
251 FreeVec(probedbus);
252 return TRUE;
255 FreeVec(probedbus);
257 return TRUE;
260 ADD2INITLIB(gayle_bus_Scan, 30)