2 Copyright © 2013-2019, The AROS Development Team. All rights reserved.
5 Desc: A600/A1200/A4000 ATA HIDD hardware detection routine
10 #include <aros/debug.h>
11 #include <proto/exec.h>
13 #include <aros/asmcall.h>
14 #include <aros/symbolsets.h>
16 #include <exec/lists.h>
17 #include <exec/rawfmt.h>
18 #include <hidd/hidd.h>
19 #include <hidd/storage.h>
22 #include <proto/oop.h>
24 #include <hardware/custom.h>
25 #include <graphics/gfxbase.h>
26 #include <hardware/ata.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
;
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)
51 custom
->intena
= 0x7fff;
52 custom
->intena
= intena
| 0x8000;
56 static BOOL
isFastATA(struct ata_ProbedBus
*ddata
)
58 #if defined(ENABLE_ATAPOWERFLYER)
59 if (ddata
->gayleirqbase
== (UBYTE
*)GAYLE_IRQ_FASTATA
)
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
;
73 gfx
= (struct GfxBase
*)TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS
);
77 port
= (UBYTE
*)GAYLE_BASE_1200
;
78 ddata
->gayleirqbase
= (UBYTE
*)GAYLE_IRQ_1200
;
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
;
84 ddata
->gayleirqbase
= (UBYTE
*)GAYLE_IRQ_4000
;
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
;
98 status1
= altport
[GAYLE_BASE_FASTATA_PIO0
+ GAYLE_FASTATA_PIO_STAT
];
99 status2
= altport
[GAYLE_BASE_FASTATA_PIO3
+ GAYLE_FASTATA_STAT
];
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
;
112 D(bug("[ATA:Gayle] No Gayle ATA Detected\n");)
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;
124 D(bug("[ATA:Gayle] Possible FastATA IDE port @ %08x\n", (ULONG
)port
& ~3);)
127 ddata
->altport
= (UBYTE
*)altport
;
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;
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");)
146 if (ddata
->doubler
) {
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)
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;
163 if ((v1
== 0 && v2
== 2) || (v1
== 1 && v2
== 4) || (v1
== 0xff && v2
== 0xff)) {
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 */
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
187 probedbus
= AllocVec(sizeof(struct ata_ProbedBus
), MEMF_ANY
| MEMF_CLEAR
);
188 if (probedbus
&& getport(probedbus
)) {
190 if (isFastATA(probedbus
))
192 ata_tags
[ATA_TAG_HARDWARENAME
].ti_Data
= (IPTR
)"PowerFlyer FastATA IDE Controller";
196 if (probedbus
->doubler
== 0)
197 ata_tags
[ATA_TAG_HARDWARENAME
].ti_Data
= (IPTR
)"Amiga(tm) Gayle IDE Controller";
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
);
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
},
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
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";
237 attrs
[BUS_TAG_HARDWARENAME
].ti_Data
= (IPTR
)"Gayle IDE Channel";
240 bus
= HIDD_StorageController_AddBus(ata
, busClass
, attrs
);
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
)
260 ADD2INITLIB(gayle_bus_Scan
, 30)