2 Copyright © 2013, The AROS Development Team. All rights reserved.
5 Desc: A600/A1200/A4000 ATA HIDD hardware detection routine
11 #define __OOP_NOMETHODBASES__
13 #include <aros/asmcall.h>
14 #include <aros/debug.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 UBYTE
*getport(struct ata_ProbedBus
*ddata
)
57 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
58 UBYTE id
, status1
, status2
;
59 volatile UBYTE
*port
, *altport
;
63 gfx
= (struct GfxBase
*)TaggedOpenLibrary(TAGGEDOPEN_GRAPHICS
);
67 port
= (UBYTE
*)GAYLE_BASE_1200
;
68 ddata
->gayleirqbase
= (UBYTE
*)GAYLE_IRQ_1200
;
70 // AGA does not have custom mirror here but lets make sure..
71 if (!custom_check((APTR
)0xdd4000) && (custom
->vposr
& 0x7f00) >= 0x2200) {
72 port
= (UBYTE
*)GAYLE_BASE_4000
;
74 ddata
->gayleirqbase
= (UBYTE
*)GAYLE_IRQ_4000
;
78 CloseLibrary((struct Library
*)gfx
);
80 D(bug("[ATA] Gayle ID=%02x. Possible IDE port=%08x.\n", id
, (ULONG
)port
& ~3));
84 ddata
->port
= (UBYTE
*)port
;
85 altport
= port
+ 0x1010;
86 ddata
->altport
= (UBYTE
*)altport
;
88 port
[ata_DevHead
* 4] = ATAF_ERROR
;
89 /* If nothing connected, we get back what we wrote, ATAF_ERROR set */
90 status1
= port
[ata_Status
* 4];
91 port
[ata_DevHead
* 4] = ATAF_DATAREQ
;
92 status2
= port
[ata_Status
* 4];
93 port
[ata_DevHead
* 4] = 0;
95 D(bug("[ATA] Status=%02x,%02x\n", status1
, status2
));
96 // BUSY and DRDY both active or ERROR/DATAREQ = no drive(s) = do not install driver
97 if ( (((status1
| status2
) & (ATAF_BUSY
| ATAF_DRDY
)) == (ATAF_BUSY
| ATAF_DRDY
))
98 || ((status1
| status2
) & (ATAF_ERROR
| ATAF_DATAREQ
)))
100 D(bug("[ATA] Drives not detected\n"));
103 if (ddata
->doubler
) {
105 /* check if AltControl is both readable and writable
106 * It is either floating or DevHead if IDE doubler is connected.
107 * AltControl = DevHead (R)
108 * Device Control = DevHead (W)
111 altport
[ata_AltControl
* 4] = 0;
112 port
[ata_DevHead
* 4] = 1;
113 v1
= altport
[ata_AltControl
* 4];
114 altport
[ata_AltControl
* 4] = 2;
115 port
[ata_DevHead
* 4] = 4;
116 v2
= altport
[ata_AltControl
* 4];
117 altport
[ata_AltControl
* 4] = 0;
118 port
[ata_DevHead
* 4] = 0;
120 if ((v1
== 0 && v2
== 2) || (v1
== 1 && v2
== 4) || (v1
== 0xff && v2
== 0xff)) {
125 D(bug("[ATA] IDE doubler check (%02X, %02X) = %d\n", v1
, v2
, ddata
->doubler
));
126 ddata
->altport
= NULL
;
128 /* we may have connected drives */
132 static int ata_Scan(struct ataBase
*base
)
134 struct ata_ProbedBus
*probedbus
;
136 probedbus
= AllocVec(sizeof(struct ata_ProbedBus
), MEMF_ANY
| MEMF_CLEAR
);
137 if (probedbus
&& getport(probedbus
)) {
138 OOP_Object
*ata
= OOP_NewObject(NULL
, CLID_HW_ATA
, NULL
);
140 HWBase
= OOP_GetMethodID(IID_HW
, 0);
141 struct TagItem attrs
[] =
143 {aHidd_DriverData
, (IPTR
)probedbus
},
144 {aHidd_ATABus_PIODataSize
, sizeof(struct pio_data
) },
145 {aHidd_ATABus_BusVectors
, (IPTR
)bus_FuncTable
},
146 {aHidd_ATABus_PIOVectors
, (IPTR
)pio_FuncTable
},
147 {aHidd_ATABus_KeepEmpty
, FALSE
},
153 * We use this field as ownership indicator.
154 * The trick is that HW_AddDriver() fails if either object creation fails
155 * or subsystem-side setup fails. In the latter case our object will be
157 * We need to know whether OOP_DisposeObject() or we should deallocate
158 * this structure on failure.
160 probedbus
->atapb_Node
.ln_Succ
= NULL
;
162 bus
= HW_AddDriver(ata
, base
->busClass
, attrs
);
165 D(bug("[GAYLE-ATA] Failed to create object for device IO: %x:%x IRQ: %x\n",
166 probedbus
->port
, probedbus
->altport
, probedbus
->gayleirqbase
));
169 * Free the structure only upon object creation failure!
170 * In case of success it becomes owned by the driver object!
172 if (!probedbus
->atapb_Node
.ln_Succ
)
182 ADD2INITLIB(ata_Scan
, 30)