2 Copyright © 2013-2017, The AROS Development Team. All rights reserved.
5 Desc: A600/A1200/A4000 ATA HIDD hardware detection routine
10 #include <aros/debug.h>
12 #define __OOP_NOMETHODBASES__
14 #include <aros/asmcall.h>
15 #include <aros/symbolsets.h>
17 #include <exec/lists.h>
18 #include <exec/rawfmt.h>
20 #include <hidd/hidd.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>
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
;
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)
50 custom
->intena
= 0x7fff;
51 custom
->intena
= intena
| 0x8000;
55 static BOOL
isFastATA(struct ata_ProbedBus
*ddata
)
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
;
68 gfx
= (struct GfxBase
*)TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS
);
72 port
= (UBYTE
*)GAYLE_BASE_1200
;
73 ddata
->gayleirqbase
= (UBYTE
*)GAYLE_IRQ_1200
;
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
;
79 ddata
->gayleirqbase
= (UBYTE
*)GAYLE_IRQ_4000
;
83 CloseLibrary((struct Library
*)gfx
);
85 // Detect FastATA... FIXME: the check is flawed for an a4000, disabled for now.
87 if (ddata
->gayleirqbase
)
89 altport
= (UBYTE
*)GAYLE_BASE_FASTATA
;
91 status1
= altport
[GAYLE_BASE_FASTATA_PIO0
+ GAYLE_FASTATA_PIO_STAT
];
92 status2
= altport
[GAYLE_BASE_FASTATA_PIO3
+ GAYLE_FASTATA_STAT
];
94 D(bug("[ATA:Gayle] Status=%02x,%02x\n", status1
, status2
);)
95 if ((status1
& 0xfd) == (status2
& 0xfd))
97 port
= (UBYTE
*)altport
;
98 ddata
->gayleirqbase
= (UBYTE
*)GAYLE_IRQ_FASTATA
;
104 D(bug("[ATA:Gayle] No Gayle ATA Detected (ID=%02x)\n", id
);)
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;
116 D(bug("[ATA:Gayle] Possible FastATA IDE port @ %08x (ID=%02x)\n", (ULONG
)port
& ~3, id
);)
119 ddata
->altport
= (UBYTE
*)altport
;
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;
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");)
138 if (ddata
->doubler
) {
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)
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;
155 if ((v1
== 0 && v2
== 2) || (v1
== 1 && v2
== 4) || (v1
== 0xff && v2
== 0xff)) {
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 */
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
);
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
},
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
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
);
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
)
224 ADD2INITLIB(ata_Scan
, 30)